Author: byterock
Date: Tue Mar 25 11:48:00 2008
New Revision: 11001
Modified:
dbd-oracle/trunk/Oracle.pm
dbd-oracle/trunk/oci8.c
Log:
well pres lobs will be truncated if asked also updated the pod
Modified: dbd-oracle/trunk/Oracle.pm
==============================================================================
--- dbd-oracle/trunk/Oracle.pm (original)
+++ dbd-oracle/trunk/Oracle.pm Tue Mar 25 11:48:00 2008
@@ -2712,48 +2712,33 @@
$dbh->{RowCacheSize} = 10;
$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. If one requires only the first few rows
+there is no need to set a large prefetch value. 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 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.
-With large record sets it is best not to attempt to go to the last record as
this may take some time. If one requires only the
-first few rows there is no need to set a large prefetch value. 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.
-
-
-Setting Prefetch Count
-
-In order to minimize server round trips and optimize the performance, the OCI
can prefetch result set rows when executing a query. You can customize this
prefetching by setting either the OCI_ATTR_PREFETCH_ROWS or
OCI_ATTR_PREFETCH_MEMORY attribute of the statement handle using the
OCIAttrSet() function. These attributes are used as follows:
-
- *
-
- OCI_ATTR_PREFETCH_ROWS sets the number of rows to be prefetched. If it
is not set, then the default value is 1. If the iters parameter of
OCIStmtExecute() is 0 and prefetching is enabled, the rows are buffered during
calls to OCIStmtFetch2(). The prefetch value can be altered after execution and
between fetches.
- *
-
- OCI_ATTR_PREFETCH_MEMORY sets the memory allocated for rows to be
prefetched. The application then fetches as many rows as will fit into that
much memory.
-
-When both of these attributes are set, the OCI prefetches rows up to the
OCI_ATTR_PREFETCH_ROWS limit unless the OCI_ATTR_PREFETCH_MEMORY limit is
reached, in which case the OCI returns as many rows as will fit in a buffer of
size OCI_ATTR_PREFETCH_MEMORY.
-
-By default, prefetching is turned on, and the OCI fetches an extra row all the
time. To turn prefetching off, set both the OCI_ATTR_PREFETCH_ROWS and
OCI_ATTR_PREFETCH_MEMORY attributes to zero.
-
-
=head1 Data Interface for Persistent LOBs
Oracle 10.2 and later extended the OCI API work directly with LOB datatypes.
In other words you can treat all LOB type data 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. 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. The data
interface only supports LOBs of size less than 2 GB.
-
-
-I believe it works more like your first option.
-
-Prefetch tells the OCI layer to grab x rows at a time whenever it has to grab
more rows, and to buffer those rows on the client side. When your application
requests rows, it can select 1 row at a time (for simplicity of program logic)
and get that row from the cache OCI has on the client, rather than incurring
the overhead of going to the database for each row. If your application
requests rows that have already been fetched by OCI, it will get those rows. If
your application requests rows that OCI has not already fetched, OCI will grab
x rows from the server and then fulfill your request.
-
-I'm assuming in the above discussion that your application is fetching fewer
than x (prefetch size) records, since that's the case 99% of the time. I would
assume that if your application fethes 2x records, that would be done in a
single database round-trip rather than 2 round-trips, but I'm not sure of that.
-
+used, normally one can get an entire LOB is a single round trip. The data
interface is suppose to supports LOBs of any size less than 2 GB,
+however it seems there is an pratical limit of about 15mb which may be an
operating system limitation.
=head2 Simple Usage
@@ -2763,7 +2748,8 @@
use DBD::Oracle qw(:ora_types);
and ensure the set statement handle's prepare method "ora_pers_lob" attribute
is set to '1' and the database
-handle's 'LongReadLen' attribute is set to a value that will exceed the
expected size of the LOB.
+handle's 'LongReadLen' attribute is set to a value that will exceed the
expected size of the LOB. If the size of the lob excedes this then DBD::Oracle
+will return a 'ORA-24345: A Truncation' error. To stop this set the handle's
LongTruncOk attribute to '1'.
For example give this table;
@@ -2775,19 +2761,23 @@
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 2
Megabytes in length.
+Will select out all of the LOBs in the table as long as they are all under 2MB
in length longer lobs will throw a error. Addeing this line
+
+ $dbh->{LongTruncOk}=0;
+
+before the execute will return all the lobs but they will only be a maximum of
2MB in size.
=head2 Binding for Updates and Inserts
@@ -2807,6 +2797,8 @@
$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 the only limit reached with this form of insert is the BLOBS mus be
under 2GB in size.
=head2 Support for Remote Lobs;
@@ -2894,10 +2886,7 @@
So far this is relatively new technology and this is a first attempt to
incorporate it into DBD::ORCALE so
please report any problems you may have with it.
-As well there seems to be some issues with retrieving LOBs that have been
truncated, It has yet to be determined if this is Oracle version/patch
-issue or a DBI/DBD::Oracle issue.
-
-If you encounter "ORA-24345 A Truncation or null fetch error occurred" error
try increasing the size of LongReadLen to see if it fixes the problem.
+If you are doing some critial progamming I would use the regular LOB functions
as they are well tried.
Not all of the interface has been implemented yet, the following are not
supported yet;
@@ -2907,6 +2896,10 @@
=item Array binds for INSERT and UPDATE operations.
+=item Piecewise and callback binds for SELECT operation.
+
+=back
+
=head1 Handling LOBs
=head2 Simple Usage
Modified: dbd-oracle/trunk/oci8.c
==============================================================================
--- dbd-oracle/trunk/oci8.c (original)
+++ dbd-oracle/trunk/oci8.c Tue Mar 25 11:48:00 2008
@@ -1520,10 +1520,10 @@
1. pin the object
2. bind with dty = SQLT_NTY
3. OCIDefineObject using the TDO
- 4. on fetech get the null indicator of the objcet with OCIObjectGetInd
- The the obj_ind is for the entier object not the propertiesy 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 in the get below.
+ 4. one gets the null indicator of the objcet with OCIObjectGetInd
+ 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
The thing to remember is that OCI and C have no way of representing a DB NULLs
so we use the OCIInd find out
@@ -2327,6 +2327,7 @@
fbh->fb_ary = fb_ary_alloc(define_len, 1);
fb_ary = fbh->fb_ary;
+
if (fbh->ftype == 116) { /* RSET */
OCIHandleAlloc_ok(imp_sth->envhp,
(dvoid*)&((OCIStmt **)fb_ary->abuf)[0],