Skip to content

Commit fcaccd7

Browse files
committed
WriteLOBs storage component and 2 implementations
Factor out the LOB Writing code through an API from ::Sybase::ASE into a generic component, ::Storage::DBI::WriteLOBs which requires the composing class to implement just two methods, _write_lobs and _empty_lob and implements insert, update and insert_bulk as well as a bunch of low level methods (which are private.) These methods are documented in the component as top comments. ::DBI::Oracle::Generic and ::Sybase::ASE implement this component. The implementation is stackable, so that a composing class override of LOB handling using the low level methods will not conflict with the inherited methods, however for performance reasons a flag has been added: local $self->{_skip_writelobs_impl} = 1; to shortcircuit the implementation even faster. This flag is not documented and will be replaced using the capability system in the future, it is used in the ASE implementation of insert_bulk because of the special identities handling it requires. This refactor addresses a number of issues: - rows can now be identified by unique constraints, not just PKs for LOB ops - ASE UPDATEs with LIKE queries on TEXT columns in the WHERE condition now work - LOB ops now work in Oracle with quoting turned on - LOB ops work in Oracle with DBD::Oracle 1.23 - insert_bulk now works with LOBs for Oracle, as long as the slices can be uniquely identified
1 parent 6343a20 commit fcaccd7

File tree

7 files changed

+575
-262
lines changed

7 files changed

+575
-262
lines changed

Changes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
Revision history for DBIx::Class
22

3+
- Loosen primary key requirement restriction on TEXT/IMAGE operations
4+
for Sybase ASE to unique constraints
5+
- Support TEXT/IMAGE UPDATE operations with TEXT queries in WHERE for
6+
Sybase ASE
7+
- Support BLOB/CLOB operations for Oracle with quoting enabled (by
8+
switching to ora_auto_lob => 0)
9+
- Support BLOB/CLOB operations for Oracle on DBD::Oracle version 1.23
10+
- Support insert_bulk with BLOBs/CLOBs for Oracle
11+
312
0.08200 2012-08-24 (UTC)
413
* Fixes
514
- Change one of the new tests for the previous release to not require

lib/DBIx/Class/Storage/DBI.pm

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ use namespace::clean;
2323
__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor');
2424

2525
__PACKAGE__->mk_group_accessors('inherited' => qw/
26-
sql_limit_dialect sql_quote_char sql_name_sep
26+
sql_limit_dialect sql_quote_char sql_name_sep _prepare_attributes
2727
/);
2828

29+
__PACKAGE__->_prepare_attributes({}); # see _dbh_sth
30+
2931
__PACKAGE__->mk_group_accessors('component_class' => qw/sql_maker_class datetime_parser_type/);
3032

3133
__PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker');
@@ -2304,8 +2306,8 @@ sub _dbh_sth {
23042306

23052307
# 3 is the if_active parameter which avoids active sth re-use
23062308
my $sth = $self->disable_sth_caching
2307-
? $dbh->prepare($sql)
2308-
: $dbh->prepare_cached($sql, {}, 3);
2309+
? $dbh->prepare($sql, $self->_prepare_attributes)
2310+
: $dbh->prepare_cached($sql, $self->_prepare_attributes, 3);
23092311

23102312
# XXX You would think RaiseError would make this impossible,
23112313
# but apparently that's not true :(

lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package DBIx::Class::Storage::DBI::Oracle::Generic;
22

33
use strict;
44
use warnings;
5-
use base qw/DBIx::Class::Storage::DBI/;
5+
use base qw/DBIx::Class::Storage::DBI::WriteLOBs/;
66
use mro 'c3';
77
use DBIx::Class::Carp;
88
use Scope::Guard ();
@@ -456,6 +456,37 @@ sub bind_attribute_by_data_type {
456456
}
457457
}
458458

459+
sub _empty_lob {
460+
my ($self, $source, $col) = @_;
461+
462+
return $self->_is_text_lob_type($source->column_info($col)->{data_type}) ?
463+
\'EMPTY_CLOB()' : \'EMPTY_BLOB()';
464+
}
465+
466+
sub _write_lobs {
467+
my ($self, $source, $lobs, $where) = @_;
468+
469+
my @lobs = keys %$lobs;
470+
471+
local $self->_prepare_attributes->{ora_auto_lob} = 0;
472+
473+
my $cursor = $self->select($source, \@lobs, $where, { for => 'update' });
474+
475+
my $dbh = $self->_get_dbh;
476+
477+
while (my @locators = $cursor->next) {
478+
my %lobs;
479+
@lobs{@lobs} = @locators;
480+
481+
foreach my $lob (@lobs) {
482+
my $data = \$lobs->{$lob};
483+
484+
$dbh->ora_lob_trim($lobs{$lob}, 0);
485+
$dbh->ora_lob_write($lobs{$lob}, 1, $$data);
486+
}
487+
}
488+
}
489+
459490
# Handle blob columns in WHERE.
460491
#
461492
# For equality comparisons:

0 commit comments

Comments
 (0)