Skip Menu |

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

Report information
The Basics
Id: 49517
Status: open
Priority: 0/
Queue: DBD-JDBC

People
Owner: Nobody in particular
Requestors: DAMI [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.71
Fixed in: (no value)



Subject: DBD::JDBC ignores the internal Perl utf8 flag
Perl strings can be internally encoded as latin1 or utf8; an internal flag makes the difference, but it's supposed to be transparent for programmers. So the DBD::JDBC should look a the flag and convert data appropriately before sending it to the jdbc proxy server. Ex. # string with internal representation latin1 my $latin1 = "il était une bergère"; # string with internal representation utf8, correctly flagged my $utf8 = $latin1; utf8::upgrade($utf8); # string with internal representation utf8, but without the flag my $raw_utf8 = $latin1; utf8::encode($raw_utf8); On the Perl side, we have $latin1 eq $utf8 and $latin1 ne $raw_utf8. But on the database side, after inserting those 3 values, we have $latin1 ne $utf8 and $utf8 eq $raw_utf8. This is a problem when the data to be sent to the database comes from various sources like HTTP, JSON, YAML, XML, etc. because some modules convert everything to utf8, some others don't, and the programmer is not supposed to care about those differences.
For info, here is how I temporarily fixed the problem in our applications : install a wrapper around DBD::JDBC::_send_request that walks through the $encode_list and downgrades all strings to internal latin1 representation (see attachment).
{ require DBD::JDBC; my $original_method = \&DBD::JDBC::_send_request or die "NO DBD::JDBC::_send_request !"; # wrapper around _send_request that downgrades strings to internal latin1 my $wrapper = sub { # my ($h, $socket, $ber, $encode_list, $decode_list, $method, # $avoid_set_err) = @_; _downgrade_utf8_strings($_[3]); goto $original_method; }; # install wrapper instead of original functions no warnings 'redefine'; *DBD::JDBC::_send_request = $wrapper; *DBD::JDBC::dr::_send_request = $wrapper; *DBD::JDBC::db::_send_request = $wrapper; *DBD::JDBC::st::_send_request = $wrapper; } use Scalar::Util qw/reftype/; sub _downgrade_utf8_strings { my $list = shift; foreach my $item (@$list) { my $type = reftype $item; if (!$type) { utf8::downgrade($item) if utf8::is_utf8($item); } elsif ($type eq 'ARRAY') { _downgrade_utf8_strings($item); } elsif ($type eq 'HASH') { _downgrade_utf8_strings([values %$item]); foreach my $key (grep {utf8::is_utf8($_)} keys %$item) { my $val = delete $item->{$key}; utf8::downgrade($key); $item->{$key} = $val; } } } }