Skip Menu |

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

Report information
The Basics
Id: 46034
Status: open
Priority: 0/
Queue: DBD-TSM

People
Owner: Nobody in particular
Requestors: milan.from.qp [...] gmail.com
Cc:
AdminCc:

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



In the test case of DBD-TSM, I met some error: [mullerc@infrat3l2]$ ./test.pl CSV, DBM, ExampleP, File, Oracle, Proxy, Sponge, TSM, mysql DEBUG - DBD::TSM::dr->connect: DBI::dr=HASH(0xd37d910) bckpp1a1 reports reports HASH(0xd36f980) DEBUG - DBD::TSM::Functions->tsm_connect: $VAR1 = [ bless( {}, 'DBI::db' ), 'bckpp1a1', 'reports', 'reports' ]; \/opt\/tivoli\/tsm\/client\/ba\/bin\/dsmadmc \/opt\/tivoli\/tsm\/client\/ba\/bin \/opt\/tivoli\/tsm\/client\/ba\/bin\/dsm\.sys DBD::TSM::Functions->tsm_choose_dsm_dir: Cannot found DSM_DIR, DSMADMC, DSM_CONFIG at /usr/lib/perl5/vendor_perl/5.8.8/DBD/TSM.pm line 124 DEBUG - DBD::TSM::db->DESTROY: call DBI::db=HASH(0xd36f920) This is fixed when I change the constant declaration for DSM_DIR, DSMADMC, DSM_CONFIG in .../DBD/TSM/Functions.pm : --- /usr/lib/perl5/vendor_perl/5.8.8/DBD/TSM/Functions.pm 2009-05-13 15:48:52.000000000 +0200 +++ /usr/lib/perl5/vendor_perl/5.8.8/DBD/TSM/Functions.pm_SAVE 2008-08-20 22:29:06.000000000 +0200 @@ -20,9 +20,9 @@ ## Automatically replace during installation ## -use constant TSM_DSMADMC => '/opt/tivoli/tsm/client/ba/bin/dsmadmc'; -use constant TSM_DSMDIR => '/opt/tivoli/tsm/client/ba/bin'; -use constant TSM_DSMCONFIG => '/opt/tivoli/tsm/client/ba/bin/dsm.sys'; +use constant TSM_DSMADMC => quotemeta('/opt/tivoli/tsm/client/ba/bin/dsmadmc'); +use constant TSM_DSMDIR => quotemeta('/opt/tivoli/tsm/client/ba/bin'); +use constant TSM_DSMCONFIG => quotemeta('/opt/tivoli/tsm/client/ba/bin/dsm.sys'); use Data::Dumper; With the "quotemeta" subroutine in Functions.pm, the "connect" method called in test.pl does not work....
Subject: test.pl
#!/usr/bin/perl use warnings; use DBI; #use DBD::TSM; my @drivers = DBI->available_drivers; print join(", ", @drivers), "\n"; my ($server_name,$user,$password)=('bckpp1a1','reports','reports'); #or set DBI_DSN,DBI_USER,DBI_PASS #my $dbh=DBI->connect("DBD:TSM:$server_name",$user,$password, #my $dbh=DBD::TSM->connect("DBD:TSM:$server_name",$user,$password, my $dbh=DBI->connect("DBI:TSM:$server_name",$user,$password, {RaiseError => 0, PrintError => 0}) or die $DBI::errstr; #If you use environment variable $dbh=DBI->connect(); my $sth=$dbh->prepare("select * from db") or die $dbh->errstr; $sth->execute() or die $sth->errstr(); print "@{$sth->{NAME}}\n"; $sth->dump_results();
The modified (and functionnal) Functions.pm attached ....
Subject: Functions.pm
#!/usr/local/bin/perl # @(#)Functions.pm 1.12 package DBD::TSM::Functions; use strict; use warnings; use Exporter; use POSIX; use Carp; use File::Spec; use constant DEBUG => 1;; use constant DEBUG_LEVEL2 => 1; our $VERSION = 0.12; ## ## Automatically replace during installation ## use constant TSM_DSMADMC => '/opt/tivoli/tsm/client/ba/bin/dsmadmc'; use constant TSM_DSMDIR => '/opt/tivoli/tsm/client/ba/bin'; use constant TSM_DSMCONFIG => '/opt/tivoli/tsm/client/ba/bin/dsm.sys'; use Data::Dumper; our @ISA = qw(Exporter); our @EXPORT = qw(tsm_connect tsm_data_sources tsm_execute); # I do my best effort sub tsm_choose_dsm_dir { if (exists $ENV{DSM_DIR} and -d $ENV{DSM_DIR} and exists $ENV{DSM_CONFIG} and -f $ENV{DSM_CONFIG} ) { my $dsm_config=(-f File::Spec->catfile($ENV{DSM_DIR},"dsm.sys"))?File::Spec->catfile($ENV{DSM_DIR},"dsm.sys"): File::Spec->catfile($ENV{DSM_CONFIG}); DEBUG && carp "VAR: ", join(", ",$ENV{DSM_DIR}, File::Spec->catfile($ENV{DSM_DIR}, "dsmadmc"), $dsm_config), "\n"; return ($ENV{DSM_DIR}, File::Spec->catfile($ENV{DSM_DIR},"dsmadmc"), $dsm_config, ); } if (-f TSM_DSMADMC and -d TSM_DSMDIR and -f TSM_DSMCONFIG ) { return (TSM_DSMDIR,TSM_DSMADMC,TSM_DSMCONFIG); } print TSM_DSMADMC ; print "\n"; print TSM_DSMDIR ; print "\n"; print TSM_DSMCONFIG ; print "\n"; croak(__PACKAGE__,"->tsm_choose_dsm_dir: Cannot found DSM_DIR, DSMADMC, DSM_CONFIG\n"); return; #Never here } sub _tsm_windows_cmd { my @cmd = @_; my $cmd; foreach my $elt (@cmd) { if ($elt =~ m/\s+/) { $elt = "\"$elt\""; } $cmd .= " $elt"; } DEBUG && carp "DEBUG - _tsm_windows_cmd: $cmd\n"; return $cmd; } sub tsm_connect { my ($dbh, $dbname, $user, $auth)=@_; DEBUG && print "DEBUG - ",__PACKAGE__,"->tsm_connect: ",Dumper(\@_); $dbname = uc($dbname); my ($dsm_dir, $dsmadmc) = tsm_choose_dsm_dir(); $ENV{DSM_DIR} = $ENV{DSM_DIR} || $dsm_dir; unless (tsm_data_sources($dbh, $dbname)) { $dbh->set_err(1,"Connect: Invalid dbname '$dbname'."); return; } @{$dbh->{tsm_connect}} = ( $dsmadmc, "-servername=$dbname", "-id=$user", "-password=$auth", ); my @cmd = ( @{$dbh->{tsm_connect}}, "-quiet", "query status", ); DEBUG && carp "DEBUG:", __PACKAGE__, "->tsm_connect: ", Dumper(\@cmd); my $rc_dsmadmc = 0; if ($dbh->{tsm_pipe}) { my $dsmadmc_h; unless (open $dsmadmc_h, '-|', @cmd) { $dbh->set_err(1,"Connect: Invalid user id or password '$user/$auth': $rc_dsmadmc/$!."); return; } DEBUG && carp <$dsmadmc_h>; close $dsmadmc_h; $rc_dsmadmc = WEXITSTATUS($?); DEBUG && carp "DEBUG:", __PACKAGE__, "->tsm_connect: rc=$?, text=$!, rcbis=$rc_dsmadmc"; } else { my $cmd = _tsm_windows_cmd(@cmd); my @query_status = qx($cmd); $rc_dsmadmc = $?; } DEBUG && carp "DEBUG:", __PACKAGE__, "->tsm_connect: rc=", $rc_dsmadmc; if ($rc_dsmadmc) { $dbh->set_err(1,"Connect: Invalid user id or password '$user/$auth': $rc_dsmadmc/$!."); return; } return 1; } sub tsm_data_sources { my ($dbh,$data_source)=@_; my ($junk1, $junk2, $dsm_sys) = tsm_choose_dsm_dir(); DEBUG && print "DEBUG - ",__PACKAGE__,"->tsm_data_sources: dsm.sys = $dsm_sys\n"; unless (-r $dsm_sys) { $dbh->DBI::set_err(1,"data sources: could not read file '$dsm_sys'."); return; } my $fh; unless (open $fh, '<', $dsm_sys) { $dbh->DBI::set_err(1,"data sources: could not open file '$dsm_sys'."); return; } my %data_sources; local $_; while (<$fh>) { chomp; DEBUG_LEVEL2 && warn "DEBUG - ", __PACKAGE__,"->tsm_data_sources: ", $_; if (my ($server_name) = (m/^\s*[sS][eE]\w*\s+(\S+)/) ) { $data_sources{uc($server_name)}++; } } close $fh; DEBUG && print "DEBUG - ",__PACKAGE__,"->tsm_data_sources: ",Dumper(\%data_sources); if ($data_source) { if (exists $data_sources{$data_source}) { return 1; } else { $dbh->DBI::set_err(1,"data sources: could not find data source '$data_source'."); return; } } my @data_sources=keys(%data_sources); map {s/^/DBI:TSM:/} @data_sources; return (@data_sources); } sub tsm_execute { my ($sth, $statement)=@_; DEBUG && print "DEBUG - ",__PACKAGE__,"->tsm_execute: AutoCommit = ",$sth->FETCH('AutoCommit'),"\n"; my @cmd=@{$sth->{Database}->{tsm_connect}}; push(@cmd,'-itemcommit') if ($sth->FETCH('AutoCommit')); push(@cmd,'-noconfirm','-displaymode=list',$statement); DEBUG && print "DEBUG - ",__PACKAGE__,"->tsm_execute: command = \"",join('" "',@cmd),"\"\n"; # A changer dès que possible pour supporter les grosses tables # Bidouille pour windows, à vérifier avec les dernières # versions de Perl Windows my ($rc_dsmadmc, @raw, $dsmadmc_h, $select_flag); if ($sth->{tsm_pipe}) { unless (open $dsmadmc_h, '-|', @cmd) { $sth->DBI::set_err(1,"Cannot open '@cmd'.\n"); return; } } else { my $cmd = _tsm_windows_cmd(@cmd); unless (open($dsmadmc_h, "$cmd |")) { $sth->DBI::set_err(1,"Cannot open '@cmd'.\n"); return; } } # On ne prend pas que les lignes intéressantes pour un select $select_flag++ if ($statement =~ m/select/i or $statement =~ m/^\s*[qQ][uUeErRyY]*\s+/); DEBUG && undef $select_flag; my $rc=0; my $errstr=""; my (@data, @fields, %fields, $not_first_raw, @values, $begin_data); no warnings; DEBUG && warn "DEBUG: select_flag = $select_flag\n"; local $_; LINE: while (<$dsmadmc_h>) { $errstr .= $_ if m/^[A-Z][A-Z][A-Z]\d\d\d\d[^I]/; # On prend tout si ce n'est pas un select if (!$select_flag) { push @raw, $_; } if (m/^ANS8002I\s+Highest\s+return\s+code\s+was\s+(-?\d+)./) { $rc = $1; last LINE; } # Pas besoin de traitement si ce n'est pas un select next LINE if (!$select_flag); # Tant que l'on a pas le début, on saute cette partie # Le jour ou on utilise dataonly => client ITSM > à 5.3 # partout if (m/ANS8000I/) { $begin_data++; next LINE; } next LINE unless ($begin_data); # On saute les messages next LINE if (m/^\s*AN[SR]/); DEBUG && "DEBUG:Inside: $not_first_raw: $_\n"; if ( my ($field, $value) = (m/\s*([^:]+):\s+(.*)/) ) { push @values, $value; # Bidouille liée au fait que l'on utilise le style # paragraphe (le seul pour avoir le nom des champs) next LINE if $not_first_raw; # On stocke les champs lors de la première ligne if (exists $fields{$field}) { # On vérifie le cas des champs dupliqués dans le cas # des jointures de table. On met un message # Marchait pas avant marche comme ca maintenant, à mettre # dans les bugs warn "Functions.pm: Duplicate field '$field' !!! Move to 'Dup_$field'.\n"; $field = 'Dup_' . $field; } $fields{$field}++; push @fields, $field; next LINE; } # Fin d'un paragraphe if (m/^\s*$/ and @fields and @values) { DEBUG && warn "DEBUG:PARSE:", Dumper(\@fields, \@values); if (@values != @fields) { # On est dans l'auto debug pour avoir des remontées # d'erreur warn "Functions.pm: Bad number of values: ", scalar(@values)," for", scalar(@fields), " fields, request line number ", $not_first_raw+1, "\n"; DEBUG && warn "DEBUG: ", Dumper(\@fields, \@values); next LINE; } $not_first_raw++; # C'est vrai à partir de maintenant # Pour pouvoir créer une référence anonyme, obligé # de faire une recopie full mémoire : bof mais pas d'autres # idées my @for_ref = @values; push @data, \@for_ref; # On réinitialise car on essaye de bosser en push @values = (); } } close $dsmadmc_h; $rc_dsmadmc = $?; # On continue à donner de l'info même en cas d'erreur # la partie rawdata peut aider à diagnostiquer la panne # Ca sautera un jour car bouffe de la place $sth->DBI::set_err($rc, $errstr) if ($rc); DEBUG && warn "DEBUG:Execute_data: ", Dumper(\@data, \@fields, \@raw); return (\@data, \@fields, \@raw); } 1;