http://search.cpan.org/~pythian/DBD-Oracle-1.19/Oracle.pm#Oracle_and_Unicode says roughly that Oracle 8 and Unicode don't mix well. If possible, try to upgrade the Oracle server to at least 9.2 and use AL32UTF32 as charset.

(I'm not an Oracle expert. I'm just using it occasionally.)

Alexander


On 15.02.2007 17:32, Peter J. Holzer wrote:
I think I've reported that problem before but we didn't get close
enough to fix the problem, so I'm taking another stab at it.

Environment:

Oracle server is 8.1.7. Oracle client is 9.2 (same problem with 10g)
DBD::Oracle version 1.18
LANG=en_US.UTF-8
NLS_LANG=.UTF8

When a parameter has the UTF-8 bit set, the query fails with "ORA-12704:
character set mismatch". However, strings returned from queries do have
this bit set, so in a (rather stupid) sequence like:

my $text0 = "test";
my ($id1, $text1) = $dbh->selectrow_array("select id, t from ora817utf8bug where 
t=?", {}, $text0);
print "$id1, $text1\n";
my ($id2, $text2) = $dbh->selectrow_array("select id, t from ora817utf8bug where 
t=?", {}, $text1);
print "$id2, $text2\n";

the first selectrow_array works, and the second fails.

In a level 9 trace, the relevant (I hope) bits look like this:

1 <- prepare= DBI::st=HASH(0x9432f1c) at ./ora817utf8bug line 46 bind :p1 <== 'test' (type 0)
       rebinding :p1 (not-utf8, ftype 1, csid 0, csform 0, inout 0)
       bind :p1 <== 'test' (size 4/5/0, ptype 4, otype 1)
       bind :p1 <== 'test' (size 4/4, otype 1, indp 0, at_exec 1)
        
OCIBindByName(94d3a20,95381fc,94cbd94,":p1",3,9537908,4,1,9538214,0,953820c,0,0,2)=SUCCESS
        OCIBindDynamic(94d3830,94cbd94,95381d8,499ab0,95381d8,499da0)=SUCCESS
        OCIAttrGet(94d3830,OCI_HTYPE_BIND,95381e8,0,31,94cbd94)=SUCCESS
       bind :p1 <== 'test' (in, not-utf8, csid 871->0->871, ftype 1, csform 
0->0, maxlen 4, maxdata_size 0)
        OCIAttrSet(94d3830,OCI_HTYPE_BIND,bfffb38a,0,31,94cbd94)=SUCCESS
    dbd_st_execute SELECT (out0, lob0)...
       in  ':p1' [0,0]: len  4, ind 0
        OCIStmtExecute(94cbd20,94d3a20,94cbd94,0,0,0,0,0)=SUCCESS
        OCIAttrGet(94d3a20,OCI_HTYPE_STMT,bfffb4ba,0,10,94cbd94)=SUCCESS
    dbd_st_execute SELECT returned (SUCCESS, rpc0, fn4, out0)
[...]
1   <- prepare= DBI::st=HASH(0x92507a4) at ./ora817utf8bug line 48
       bind :p1 <== "test" (type 0)
       rebinding :p1 (is-utf8, ftype 1, csid 0, csform 0, inout 0)
       bind :p1 <== "test" (size 4/5/0, ptype 4, otype 1)
       bind :p1 <== 'test' (size 4/4, otype 1, indp 0, at_exec 1)
        
OCIBindByName(94d3a20,95382f4,94cbd94,":p1",3,954d750,4,1,953830c,0,9538304,0,0,2)=SUCCESS
        OCIBindDynamic(94d3830,94cbd94,95382d0,499ab0,95382d0,499da0)=SUCCESS
       rebinding :p1 with UTF8 value so setting csform=SQLCS_IMPLICIT   
OCIAttrSet(94d3830,OCI_HTYPE_BIND,bfffb383,0,32,94cbd94)=SUCCESS
        OCIAttrGet(94d3830,OCI_HTYPE_BIND,95382e0,0,31,94cbd94)=SUCCESS
       bind :p1 <== "test" (in, is-utf8, csid 871->0->871, ftype 1, csform 
0->2, maxlen 4, maxdata_size 0)
        OCIAttrSet(94d3830,OCI_HTYPE_BIND,bfffb38a,0,31,94cbd94)=SUCCESS
    dbd_st_execute SELECT (out0, lob0)...
       in  ':p1' [0,0]: len  4, ind 0
        OCIStmtExecute(94cbd20,94d3a20,94cbd94,0,0,0,0,0)=ERROR
        OCIAttrGet(94d3a20,OCI_HTYPE_STMT,bfffb3be,0,129,94cbd94)=SUCCESS
        OCIErrorGet(94cbd94,1,"<NULL>",bfffafec,"ORA-12704: character set mismatch 
",1024,2)=SUCCESS

AFAICS, the difference is the csform in the final bind. In the
successful case it's "csform 0->0", in the unsuccessful case it's
"csform 0->2". I assume that 2 is SQLCS_IMPLICIT mentioned 2 lines
above.

The code works if run against Oracle 9i or 10g servers, so I think that
maybe Oracle 8.1.7 doesn't support csform=SQLCS_IMPLICIT?

Here is a full script to demonstrate the problem (it tries to read the
parameters for connect ($data_source, $username, $auth) from a file
specified with --cred or the env. variable DBI_CREDENTIAL_FILE - I
normally keep such files in ~/.dbi)

#!/usr/local/bin/perl -w

=head1 NAME

ora817utf8bug - demonstrate bug with Oracle 8.1.7 and UTF8

=head1 SYNOPSIS

export LANG=en_US.UTF-8
export NLS_LANG=.UTF8
export DBI_TRACE=9

./ora817utf8bug

=head1 DESCRIPTION

=cut

use strict;
use DBI;
use Getopt::Long;
use Pod::Usage;


my $help;
my $credfile = $ENV{DBI_CREDENTIAL_FILE} || "default";

GetOptions(
    'help|?'            => \$help,
    'credfile=s'                => \$credfile,
) or pod2usage(2);
pod2usage(1) if $help;

my @cred = read_cred($credfile);
my $dbh = DBI->connect($cred[0], $cred[1], $cred[2], {RaiseError => 1, AutoCommit 
=> 0});
$dbh->{FetchHashKeyName} = 'NAME_lc';

$dbh->{RaiseError} = 0;
$dbh->do("drop table ora817utf8bug");
$dbh->do("create table ora817utf8bug(id number, t varchar2(40))");
$dbh->{RaiseError} = 1;
$dbh->do("insert into ora817utf8bug(id, t) values(1, 'test')");


my $text0 = "test";
my ($id1, $text1) = $dbh->selectrow_array("select id, t from ora817utf8bug where 
t=?", {}, $text0);
print "$id1, $text1\n";
my ($id2, $text2) = $dbh->selectrow_array("select id, t from ora817utf8bug where 
t=?", {}, $text1);
print "$id2, $text2\n";
$dbh->do("drop table ora817utf8bug");

$dbh->disconnect();



sub read_cred {
    my ($fn) = @_;

    if ($fn !~ m{/}) {
        $fn = "$ENV{HOME}/.dbi/$fn";
    }
    open(FN, "<$fn") or die "cannot open $fn: $!";
my $line = <FN>; close(FN); my @cred = split(/[\s\n]/, $line); return @cred;
}





--
Alexander Foken
mailto:[EMAIL PROTECTED]  http://www.foken.de/alexander/

Reply via email to