Tim Bunce wrote on 08/11/2000 10:22:14:
> I need a volunteer to write a test script (like the other t/*.t files)
> that will... create a table with NULL and NOT NULL variants of CHAR and
> VARCHAR columns, and then do a series of inserts and selects with and
> without trailing spaces etc with ora_ph_type set to various values.
> 
> Wouldn`t be too hard to do as a series of nested loops (a little like
> t/long.t, only simpler) driven by a data structure that says what to
> expect in each case.
> 
> Any volunteers? This is your chance to give back...

We've been having problems migrating from OCI_V7 to OCI_V8 using DBD-Oracle
because of VARCHAR2 trailing space issues.  I have tried and failed to get
the $dbh->{ora_ph_type} trick mentioned in Changes to work.  Invariably,
when ora_ph_type is set to "5" (or "97"), I get the following error from the
following pseudocode:

 $dbh->{ora_ph_type} = 5;
 $dbh->do("CREATE TABLE foobar (foo VARCHAR2(20))");
 $sth = $dbh->prepare("INSERT INTO foobar VALUES (?)");
 $sth->execute("trailing ");

   ORA-01461: can bind a LONG value only for insert into a LONG column
        (DBD ERROR: OCIStmtExecute)

I have taken you up on your challenge to produce a test file, t/ph_type.t.
It doesn't do much right now, so feel free to beef it up.  At least it
reproduces the problem.

Let me know if there is anything more I can do.

james

t/ph_type.t:
#!perl -w

sub ok ($$;$) {
    my($n, $ok, $warn) = @_;
    ++$t;
    die "sequence error, expected $n but actually $t"
    if $n and $n != $t;
    ($ok) ? print "ok $t\n"
          : print "# failed test $t at line ".(caller)[2]."\nnot ok $t\n";
        if (!$ok && $warn) {
                $warn = $DBI::errstr || "(DBI::errstr undefined)" if $warn eq '1';
                warn "$warn\n";
        }
}

use strict;
use DBI;
$| = 1;

my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger';
my $dsn    = $ENV{ORACLE_DSN}    || 'dbi:Oracle:';
my $dbh = DBI->connect($dsn, $dbuser, '', {AutoCommit=>0,PrintError=>1});

unless($dbh) {
        warn "Unable to connect to Oracle ($DBI::errstr)\nTests skipped.\n";
        print "1..0\n";
        exit 0;
}

use vars qw($tests);
print "1..$tests\n";

my ($sth,$expect,$tmp);

# drop table but do not even warn if not there
eval { $dbh->do("DROP TABLE foobar") };
#warn $@ if $@;

ok(0, $dbh->do("CREATE TABLE foobar (foo VARCHAR2(20))"));

my $val_with_trailing_space = "trailing ";
my $val_with_embedded_nul = "embedded\0nul";

my @tests =
 ([  1, "VARCHAR2", 1, 1 ],
  [  5, "STRING",   0, 0 ],
  [ 96, "CHAR",     0, 1 ],
  [ 97, "CHARZ",    0, 0 ]);

for my $test_ary (@tests) {
  my ($ph_type, $name, $strips_trailing, $embed_nul_ok) = @$test_ary;
  print "#testing $name..\n";
  ok(0, $dbh->{ora_ph_type} = $ph_type );

  $expect = $val_with_trailing_space;
  $expect =~ s/\s+$// if $strips_trailing;
  ok(0, $sth = $dbh->prepare("INSERT INTO foobar VALUES (?)"));
  ok(0, $sth->execute($val_with_trailing_space));
  ok(0, $sth = $dbh->prepare("SELECT foo FROM foobar WHERE foo = '$expect'"));
  ok(0, $sth->execute );
  ok(0, $tmp = $sth->fetchrow_hashref );
  ok(0, $sth && $sth->finish );
  ok(0, $dbh->rollback );

  ($expect = $val_with_embedded_nul) =~ s/\0.*//;
  ok(0, $sth = $dbh->prepare("INSERT INTO foobar VALUES (?)"));
  ok(0, $sth->execute($val_with_embedded_nul));
  ok(0, $sth = $dbh->prepare("SELECT foo FROM foobar WHERE foo = '$expect'"));
  ok(0, $sth->execute );
  $tmp = $sth->fetchrow_hashref;
  ok(0, $embed_nul_ok ? !$tmp : $tmp );
  ok(0, $sth && $sth->finish );
  ok(0, $dbh->rollback );
}

ok(0, $dbh->disconnect );

BEGIN { $tests = 62 }

Reply via email to