Blame Oracle.
Or blame me - for a decision I made many many years ago now to switch
from binding strings as type 5 (STRING) to type 1 (VARCHAR2).
Oraperl used to use 5 but that type doesn't support embedded \0 bytes.
Type 1 does support embedded nul bytes but has it's own set of issues.
You can choose your own poison via the $dbh->{ora_ph_type} attribute.
See also http://search.cpan.org/src/PYTHIAN/DBD-Oracle-1.17/t/40ph_type.t
Tim.
On Mon, Mar 06, 2006 at 08:09:39PM +0100, H.Merijn Brand wrote:
> Trailing \r characters are trimmed on varchar2 fields.
>
> HP-UX 11.11
> Oracle 9.2.0
> perl-5.8.5-64all-dor
> DBI-1.50
> DBD::Oracle-1.17
>
> DBD::Oracle states:
> --8<---
> ORA_VARCHAR2
> Strip trailing spaces and allow embedded \0 bytes. This is
> the normal default placeholder type.
> -->8---
>
> No mention of \r
>
> Script:
> --8<--- dd.pl
> #!/pro/bin/perl
>
> use strict;
> use warnings;
>
> use DBI;
>
> my %attr = (
> RaiseError => 1,
> PrintError => 1,
> AutoCommit => 0,
> ChopBlanks => 0,
> ShowErrorStatement => 1,
> FetchHashKeyName => "NAME_lc",
> );
>
> my $up = $ENV{DBUSER} || $ENV{ORACLE_USERID};
> my $dbh = DBI->connect ("DBI:Oracle:", (split m:/: => $up), \%attr) or
> die "connect: $!";
>
> $dbh->do (q;
> create table x_cr (
> k_xx varchar2 (8),
> c_xx numeric (9),
> xx varchar2 (255)
> ););
> $dbh->commit;
>
> foreach my $xx (
> (pack "C", 13),
> (pack "CC", 1, 13),
> (pack "CC", 13, 13),
> (pack "CCC", 1, 13, 0),
> ) {
> my $sth = $dbh->prepare ("insert into x_cr values (?, ?, ?)");
> $sth->execute ("zzz", 13, $xx);
> $dbh->commit;
> }
>
> my $sts = $dbh->prepare ("select * from x_cr");
> my ($k, $c, $x);
> $sts->execute;
> $sts->bind_columns (\($k, $c, $x));
> while ($sts->fetch) {
> for ($k, $c, $x) {
> my $l = length $_;
> print "'$_', ($l)\n";
> my @x = split //, $_, -1;
> print ">> ", (map { sprintf "0x%02x ", ord $x[$_] } 0 .. ($l - 1)),
> "\n";
> }
> print "---\n";
> }
> $sts->finish;
>
> $dbh->commit;
> $dbh->do ("drop table x_cr");
> $dbh->commit;
> $dbh->disconnect;
> -->8---
>
> Output:
> bev r3:/tmp 136 > perl dd.pl
> 'zzz', (3)
> >> 0x7a 0x7a 0x7a
> '13', (2)
> >> 0x31 0x33
> Use of uninitialized value in length at dd.pl line 46.
> Use of uninitialized value in concatenation (.) or string at dd.pl line 47.
> '', (0)
> Use of uninitialized value in split at dd.pl line 48.
> >>
> ---
> 'zzz', (3)
> >> 0x7a 0x7a 0x7a
> '13', (2)
> >> 0x31 0x33
> '', (1)
> >> 0x01
> ---
> 'zzz', (3)
> >> 0x7a 0x7a 0x7a
> '13', (2)
> >> 0x31 0x33
> Use of uninitialized value in length at dd.pl line 46.
> Use of uninitialized value in concatenation (.) or string at dd.pl line 47.
> '', (0)
> Use of uninitialized value in split at dd.pl line 48.
> >>
> ---
> 'zzz', (3)
> >> 0x7a 0x7a 0x7a
> '13', (2)
> >> 0x31 0x33
> ', (3)
> >> 0x01 0x0d 0x00
> ---
>
> A DBI trace shows me for the first (pack "C", 13) insert:
> --8<---
> DBI 1.50-nothread default trace level set to 0x0/9 (pid 18857)
> >> execute DISPATCH (DBI::st=HASH(0x80000001002dc208) rc1/1 @4 g0
> ima1041 pid#18857) at dd.pl line 37
> ') -> execute for DBD::Oracle::st
> (DBI::st=HASH(0x80000001002dc208)~0x80000001002db970 'zzz' 13 '
> bind :p1 <== 'zzz' (type 0)
> rebinding :p1 (not-utf8, ftype 1, csid 0, csform 0, inout 0)
> bind :p1 <== 'zzz' (size 3/4/0, ptype 4, otype 1)
> bind :p1 <== 'zzz' (size 3/3, otype 1, indp 0, at_exec 1)
>
> OCIBindByName(8000000100336140,800000010034c5c8,800000010032d5a8,":p1",3,80000001003c3d20,3,1,800000010034c5e2,0,800000010034c5e0,0,0,2)=SUCCESS
>
> OCIBindDynamic(8000000100335b38,800000010032d5a8,800000010034c590,800003fffef2a2a0,800000010034c590,800003fffef2a610)=SUCCESS
>
> OCIAttrGet(8000000100335b38,OCI_HTYPE_BIND,800000010034c5ac,0,31,800000010032d5a8)=SUCCESS
> bind :p1 <== 'zzz' (in, not-utf8, csid 1->0->1, ftype 1, csform 0->0,
> maxlen 3, maxdata_size 0)
>
> OCIAttrSet(8000000100335b38,OCI_HTYPE_BIND,800003fffeff2c0a,0,31,800000010032d5a8)=SUCCESS
> bind :p2 <== 13 (type 0)
> rebinding :p2 (not-utf8, ftype 1, csid 0, csform 0, inout 0)
> bind :p2 <== 13 (size 2/3/0, ptype 5, otype 1)
> bind :p2 <== '13' (size 2/2, otype 1, indp 0, at_exec 1)
>
> OCIBindByName(8000000100336140,80000001003c2670,800000010032d5a8,":p2",3,80000001003c41a8,2,1,80000001003c268a,0,80000001003c2688,0,0,2)=SUCCESS
>
> OCIBindDynamic(8000000100335a80,800000010032d5a8,80000001003c2638,800003fffef2a2a0,80000001003c2638,800003fffef2a610)=SUCCESS
>
> OCIAttrGet(8000000100335a80,OCI_HTYPE_BIND,80000001003c2654,0,31,800000010032d5a8)=SUCCESS
> bind :p2 <== 13 (in, not-utf8, csid 1->0->1, ftype 1, csform 0->0,
> maxlen 2, maxdata_size 0)
>
> OCIAttrSet(8000000100335a80,OCI_HTYPE_BIND,800003fffeff2c0a,0,31,800000010032d5a8)=SUCCESS
> ' (type 0)d :p3 <== '
> rebinding :p3 (not-utf8, ftype 1, csid 0, csform 0, inout 0)
> ' (size 1/2/0, ptype 4, otype 1)
> ' (size 1/1, otype 1, indp 0, at_exec 1)
>
> OCIBindByName(8000000100336140,80000001003c2b10,800000010032d5a8,":p3",3,80000001003c41e8,1,1,80000001003c2b2a,0,80000001003c2b28,0,0,2)=SUCCESS
>
> OCIBindDynamic(80000001003359c8,800000010032d5a8,80000001003c2ad8,800003fffef2a2a0,80000001003c2ad8,800003fffef2a610)=SUCCESS
>
> OCIAttrGet(80000001003359c8,OCI_HTYPE_BIND,80000001003c2af4,0,31,800000010032d5a8)=SUCCESS
> ' (in, not-utf8, csid 1->0->1, ftype 1, csform 0->0, maxlen 1, maxdata_size 0)
>
> OCIAttrSet(80000001003359c8,OCI_HTYPE_BIND,800003fffeff2c0a,0,31,800000010032d5a8)=SUCCESS
> dbd_st_execute INSERT (out0, lob0)...
> in ':p1' [0,0]: len 3, ind 0
> in ':p2' [0,0]: len 2, ind 0
> in ':p3' [0,0]: len 1, ind 0
>
> OCIStmtExecute(800000010032d4d8,8000000100336140,800000010032d5a8,1,0,0,0,0)=SUCCESS
>
> OCIAttrGet(8000000100336140,OCI_HTYPE_STMT,800003fffeff2980,0,9,800000010032d5a8)=SUCCESS
>
> OCIAttrGet(8000000100336140,OCI_HTYPE_STMT,800003fffeff29c8,0,10,800000010032d5a8)=SUCCESS
> dbd_st_execute INSERT returned (SUCCESS, rpc1, fn3, out0)
> <- execute= 1 at dd.pl line 37
> -->8---
>
> A clear length of 1 for :p3, and a success.
>
> A trace on the login gives me
> charsetid=1 ncharsetid=1 (csid: utf8=871 al32utf8=873)
>
> --
> H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/)
> using & porting perl 5.6.2, 5.8.x, 5.9.x on HP-UX 10.20, 11.00, 11.11,
> & 11.23, SuSE 10.0, AIX 4.3 & 5.2, and Cygwin. http://qa.perl.org
> http://mirrors.develooper.com/hpux/ http://www.test-smoke.org
> http://www.goldmark.org/jeff/stupid-disclaimers/