Skip to content

Commit fbe32b7

Browse files
authored
Merge pull request #61 from charsbar/mariadb_blob
blob for MariaDB
2 parents ec484e0 + e0b2184 commit fbe32b7

7 files changed

Lines changed: 154 additions & 12 deletions

File tree

cpanfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ on develop => sub {
2323
on test => sub {
2424
requires 'version';
2525
requires 'Tie::IxHash';
26+
requires 'Digest::SHA';
2627
};
2728

2829
feature 'test_sqlite', 'Test SQLite' => sub {

lib/Data/ObjectDriver/Driver/DBD/MariaDB.pm

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,59 @@
33
package Data::ObjectDriver::Driver::DBD::MariaDB;
44
use strict;
55
use warnings;
6+
use Carp;
67
use base qw( Data::ObjectDriver::Driver::DBD::mysql );
78

89
sub fetch_id { $_[3]->{mariadb_insertid} || $_[3]->{insertid} }
910

11+
sub bind_param_attributes {
12+
my ($dbd, $data_type) = @_;
13+
if ($data_type) {
14+
if ($data_type eq 'blob') {
15+
return DBI::SQL_BINARY;
16+
} elsif ($data_type eq 'binchar') {
17+
return DBI::SQL_BINARY;
18+
}
19+
}
20+
return;
21+
}
22+
23+
sub bulk_insert {
24+
my $dbd = shift;
25+
my $dbh = shift;
26+
my $table = shift;
27+
28+
my $cols = shift;
29+
my $rows_ref = shift;
30+
my $attrs = shift || {};
31+
32+
croak "Usage bulk_insert(dbd, dbh, table, columnref, rowsref)"
33+
unless (defined $dbd && defined $dbh && defined $table && defined $cols &&
34+
defined $rows_ref);
35+
36+
return 0e0 if (scalar(@{$rows_ref}) == 0);
37+
38+
my $sql = "INSERT INTO $table (" . join(',', @{$cols}) . ") VALUES\n";
39+
40+
my $one_data_row = "(" . (join ',', (('?') x @$cols)) . ")";
41+
my $ph = join ",", (($one_data_row) x @$rows_ref);
42+
$sql .= $ph;
43+
44+
# For now just write all data, at some point we need to lookup the
45+
# maximum packet size for SQL
46+
47+
if (%$attrs) {
48+
my $sth = $dbh->prepare($sql);
49+
my $i = 1;
50+
for my $row (@$rows_ref) {
51+
for (my $j = 0; $j < @$cols; $j++) {
52+
$sth->bind_param($i++, $row->[$j], $attrs->{$cols->[$j]});
53+
}
54+
}
55+
$sth->execute;
56+
} else {
57+
return $dbh->do($sql, undef, map { @$_ } @$rows_ref);
58+
}
59+
}
60+
1061
1;

lib/Data/ObjectDriver/Driver/DBD/Oracle.pm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ sub bulk_insert {
6868
my $table = shift;
6969
my $cols = shift;
7070
my $rows_ref = shift;
71+
my $attrs = shift || {};
7172

7273
my $sql = "INSERT INTO $table("
7374
. join(',', @$cols)
@@ -76,7 +77,11 @@ sub bulk_insert {
7677
. ")";
7778
my $sth = $dbh->prepare($sql);
7879
foreach my $row (@{ $rows_ref || []}) {
79-
$sth->execute(@$row);
80+
my $i = 1;
81+
for (my $j = 0; $j < @$cols; $j++) {
82+
$sth->bind_param($i++, $row->[$j], $attrs->{$cols->[$j]});
83+
}
84+
$sth->execute;
8085
}
8186
return 1;
8287
}

lib/Data/ObjectDriver/Driver/DBD/Pg.pm

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,33 @@ sub bulk_insert {
5151

5252
my $cols = shift;
5353
my $rows_ref = shift;
54-
55-
my $sql = "COPY $table (" . join(',', @{$cols}) . ') from stdin';
56-
57-
$dbh->do($sql);
58-
foreach my $row (@{$rows_ref}) {
59-
my $line = join("\t", map {$_ || '\N'} @{$row});
60-
$dbh->pg_putline("$line\n");
54+
my $attrs = shift || {};
55+
56+
if (%$attrs) {
57+
my $sql = "INSERT INTO $table (" . join(',', @{$cols}) . ") VALUES\n";
58+
59+
my $one_data_row = "(" . (join ',', (('?') x @$cols)) . ")";
60+
my $ph = join ",", (($one_data_row) x @$rows_ref);
61+
$sql .= $ph;
62+
63+
my $sth = $dbh->prepare($sql);
64+
my $i = 1;
65+
for my $row (@$rows_ref) {
66+
for (my $j = 0; $j < @$cols; $j++) {
67+
$sth->bind_param($i++, $row->[$j], $attrs->{$cols->[$j]});
68+
}
69+
}
70+
$sth->execute;
71+
} else {
72+
my $sql = "COPY $table (" . join(',', @{$cols}) . ') from stdin';
73+
74+
$dbh->do($sql);
75+
foreach my $row (@{$rows_ref}) {
76+
my $line = join("\t", map {$_ || '\N'} @{$row});
77+
$dbh->pg_putline("$line\n");
78+
}
79+
return $dbh->pg_endcopy();
6180
}
62-
return $dbh->pg_endcopy();
6381
}
6482

6583
sub map_error_code {

lib/Data/ObjectDriver/Driver/DBD/SQLite.pm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,18 @@ sub bulk_insert {
4646

4747
my $cols = shift;
4848
my $rows_ref = shift;
49+
my $attrs = shift || {};
4950

5051
my $sql = "INSERT INTO $table(" . join(',', @{$cols}) . ") VALUES (" . join(',', map {'?'} @{$cols}) . ")\n";
5152

5253
my $sth = $dbh->prepare($sql);
5354

5455
foreach my $row (@{$rows_ref}) {
55-
$sth->execute(@{$row});
56+
my $i = 1;
57+
for (my $j = 0; $j < @$cols; $j++) {
58+
$sth->bind_param($i++, $row->[$j], $attrs->{$cols->[$j]});
59+
}
60+
$sth->execute;
5661
}
5762

5863
# For now just write all data, at some point we need to lookup the

lib/Data/ObjectDriver/Driver/DBI.pm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,9 +642,19 @@ sub bulk_insert {
642642
# pass this directly to the backend DBD
643643
my $dbh = $driver->rw_handle($class->properties->{db});
644644
my $tbl = $driver->table_for($class);
645-
my @db_cols = map {$dbd->db_column_name($tbl, $_) } @{$cols};
646645

647-
return $dbd->bulk_insert($dbh, $tbl, \@db_cols, $data);
646+
my @db_cols;
647+
my %attrs;
648+
my $col_defs = $class->properties->{column_defs};
649+
for my $col (@$cols) {
650+
my $db_col = $dbd->db_column_name($tbl, $col);
651+
push @db_cols, $db_col;
652+
my $type = $col_defs->{$col} || 'char';
653+
my $attr = $dbd->bind_param_attributes($type) or next;
654+
$attrs{$db_col} = $attr;
655+
}
656+
657+
return $dbd->bulk_insert($dbh, $tbl, \@db_cols, $data, \%attrs);
648658
}
649659

650660
sub begin_work {

t/10-resultset-blob.t

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# $Id: 01-col-inheritance.t 989 2005-09-23 19:58:01Z btrott $
2+
3+
use strict;
4+
use warnings;
5+
6+
use lib 't/lib';
7+
8+
$Data::ObjectDriver::DEBUG = 0;
9+
use Test::More;
10+
use DodTestUtil;
11+
BEGIN { eval { require Digest::SHA; 1 } or plan skip_all => 'requires Digest::SHA' }
12+
13+
BEGIN { DodTestUtil->check_driver }
14+
15+
plan tests => 5;
16+
17+
setup_dbs({
18+
global => [ qw( wines ) ],
19+
});
20+
21+
use Wine;
22+
use Storable;
23+
24+
my $wine = Wine->new;
25+
$wine->name("Saumur Champigny, Le Grand Clos 2001");
26+
$wine->rating(4);
27+
28+
## generate some binary data (SQL_BLOB / MEDIUMBLOB)
29+
my $binary = Digest::SHA::sha1("binary");
30+
$wine->content($binary);
31+
ok($wine->save, 'Object saved successfully');
32+
33+
my $iter;
34+
35+
$iter = Data::ObjectDriver::Iterator->new(sub {});
36+
my $wine_id = $wine->id;
37+
undef $wine;
38+
$wine = Wine->lookup($wine_id);
39+
40+
ok $wine;
41+
ok $wine->content eq $binary;
42+
43+
my @names = qw(Margaux Latour);
44+
Wine->bulk_insert([qw(name content)], [ map {[$_, Digest::SHA::sha1($_)]} @names ]);
45+
46+
for my $name (@names) {
47+
my ($found) = Wine->search({name => $name});
48+
ok $found->content eq Digest::SHA::sha1($name);
49+
}
50+
51+
disconnect_all($wine);
52+
teardown_dbs(qw( global ));

0 commit comments

Comments
 (0)