BigJoe has asked for the wisdom of the Perl Monks concerning the following question:

I have written a script that reads on record out of the database and it fills in a form. When this runs I get an error embedded in my html output. I am running this on Win32 and I am connecting to Oracle using the DBI. In this script the policy is split into 6 blocks of 4000 characters. (This is running only on selected internal boxes for data-entry so security critical)
#!/usr/bin/perl -w use strict; use warnings; use DBI; use CGI; use CGI::Carp qw(fatalsToBrowser); my $q = new CGI; print $q->header; print $q->start_html(-title=>'Search The Grand Rapids Web Site'); print $q->comment('By Joseph Harnish'); print <<EODUMP; #html header is printed here EODUMP if( defined($q->param('type'))){ # if the type is set it will enter here if($q->param('type') eq 'new'){ #if the type was set to new it will create a blank form } elsif ($q->param('type') eq 'add'){ #if the type is add a db connection will be created to the dat +abase and the #form will be entered into the database. my $dbh = DBI->connect("DBI:Oracle:host=172.16.21.16;sid=nlab" +, 'xxxxx', 'xxxxx') or die "Connecting : $DBI::errstr\n"; my $ii = 0; my $partialstring = ""; my $keywordfound = 0; my $policynumber = $q->param('id'); my $DATE_CR = $q->param('dated'); my $ISSUEDBY = $q->param('issuedby'); my $newsubject = $q->param('subject'); my $newpurpose = $q->param('purpose'); my $newpolicy = $q->param('policy'); my $username = $q->remote_user(); if (!defined($newsubject)){ #do error stuff here } if (!defined($newpurpose)){ #do error stuff here } if (!defined($newpolicy)){ #do error stuff here } $newpolicy =~ s/\n/<br>/g; $newpolicy =~ s/\'/&#039;/g; $newpurpose =~ s/\'/&#039;/g; $newsubject =~ s/\'/&#039;/g; print "$DATE_CR"; print " $ISSUEDBY"; print " $policynumber"; $dbh->do("Insert into City_Policies (ID, DATE_CREATED, ISSEDBY, SU +BJECT) values ('$policynumber', '$DATE_CR', '$ISSUEDBY', '$newsubject +')") or print "I died"; $dbh->do("Update City_Policies set PURPOSE='$newpurpose' where ID= +'$policynumber'") or die "Error with PURPOSE"; for ($ii = 0; $ii< ((length($newpolicy))/4000); $ii++){ my $testnum = ((length($newpolicy)) - ($ii * 4000)); if ($testnum < 4000) { $partialstring = substr($newpolicy, (($ii) * 4000)); } else { $partialstring = substr($newpolicy, (($ii) * 4000), +4000); } print $partialstring; $dbh->do("Update City_Policies set POLICY" . ($ii+1) . + "='$partialstring' where ID='$policynumber'") or die "Error in Policy \n $newpolicy which ha +s a size of ". length($partialstring) ." instead of 4000"; $partialstring = ""; } $dbh->disconnect; } elsif ($q->param('type') eq 'del'){ # if the param is delete then I come here my $dbh = DBI->connect("DBI:Oracle:host=172.16.21.16;sid=nlab", +'xxxx', 'xxxxx') or die "Connecting : $DBI::errstr\n"; my $idnum = $q->param('id'); $dbh->do("Delete from City_policies where ID='$idnum'"); $dbh->disconnect; } }else { #if the type param was not set I enter here my $IDNUM = $q->param("ID"); my $POLICY1 = ""; my $DATE_CR = ""; my $POLICY2 = ""; my $POLICY3 = ""; my $POLICY4 = ""; my $POLICY5 = ""; my $POLICY6 = ""; my $ISSUEDBY = ""; my $SUBJECT =""; my $PURPOSE = ""; my $dbh = DBI->connect("DBI:Oracle:host=172.16.21.16;sid=nlab", 'xxxx' +, 'xxxxx') or die "Connecting : $DBI::errstr\n"; my $sth = $dbh->prepare("Select ID, ISSEDBY, DATE_CREATED, SUBJECT, PU +RPOSE, POLICY1, POLICY2, POLICY3, POLICY4, POLICY5, POLICY6 from city +_policies where ID='$IDNUM'") or die "Error in prepare"; $sth->execute or die "Error in excute"; ($IDNUM, $ISSUEDBY, $DATE_CR, $SUBJECT, $PURPOSE, $POLICY1, $POLICY2, +$POLICY3, $POLICY4, $POLICY5, $POLICY6) = $sth->fetchrow_array; $POLICY1 =~s/<br>/\n/g; $POLICY2 =~s/<br>/\n/g; $POLICY3 =~s/<br>/\n/g; $POLICY4 =~s/<br>/\n/g; $POLICY5 =~s/<br>/\n/g; $POLICY6 =~s/<br>/\n/g; $POLICY1 =~s/<BR>/\n/g; $POLICY2 =~s/<BR>/\n/g; $POLICY3 =~s/<BR>/\n/g; $POLICY4 =~s/<BR>/\n/g; $POLICY5 =~s/<BR>/\n/g; $POLICY6 =~s/<BR>/\n/g; $sth->finish; $dbh->disconnect; print <<EOF; #prints out form for editing data but when I put it in it actually use +s it. #footer goes here EOF }
The error I get is :
[Wed Nov 29 10:08:22 2000] G:\Inetpub\wwwroot\adminpolicy.pl: (in +cleanup) Can't call method "FETCH" on an undefined value at c:/Perl/s +ite/lib/Win32/TieRegistry.pm line 1486 during global destruction.
I am not sure why TieRegistry is even being called. I put all my prints into print <<somthing; to stop concatination errors. I belive I am doing something wrong with DBI but I haven't use it enough to see it. Are there any tricks or tips that would help me clean up this code and/or make it more efficient? Thanks

--BigJoe

Learn patience, you must.
Young PerlMonk, craves Not these things.
Use the source Luke.

Replies are listed 'Best First'.
Re: A seeming random error.
by Russ (Deacon) on Nov 29, 2000 at 23:36 UTC
    Look at the actual strings you are sending to $dbh->do. If the user has a single-quote in a field (like dated, issuedby, etc), the SQL string will be bad.
    my $Str = "Insert into City_Policies (ID, DATE_CREATED, ISSEDBY, SUBJE +CT) values ('$policynumber', '$DATE_CR', '$ISSUEDBY', '$newsubject')"; warn $Str; $dbh->do($Str) or print "I died";
    This may be a good reason to go ahead and build statement handles and use placeholders. DBI will handle embedded quotes for you.

    BTW, may I suggest a stylistic change? ;-)

    my $POLICY1 = ""; my $DATE_CR = ""; my $POLICY2 = ""; my $POLICY3 = ""; my $POLICY4 = ""; my $POLICY5 = ""; my $POLICY6 = ""; my $ISSUEDBY = ""; my $SUBJECT =""; my $PURPOSE = ""; $POLICY1 =~s/<br>/\n/g; $POLICY2 =~s/<br>/\n/g; $POLICY3 =~s/<br>/\n/g; $POLICY4 =~s/<br>/\n/g; $POLICY5 =~s/<br>/\n/g; $POLICY6 =~s/<br>/\n/g; $POLICY1 =~s/<BR>/\n/g; $POLICY2 =~s/<BR>/\n/g; $POLICY3 =~s/<BR>/\n/g; $POLICY4 =~s/<BR>/\n/g; $POLICY5 =~s/<BR>/\n/g; $POLICY6 =~s/<BR>/\n/g;
    can be more succinctly written as:
    my ($IDNUM, $ISSUEDBY, $DATE_CR, $SUBJECT, $PURPOSE, $POLICY1, $POLICY2, $POLICY3, $POLICY4, $POLICY5, $POLICY6) = $sth->fetchrow_array; $_ ||= '' for ($DATE_CR, $ISSUEDBY, $SUBJECT, $PURPOSE); $_ ||= '', s/<br>/\n/ig for ($POLICY1, $POLICY2, $POLICY3, $POLICY4, $POLICY5, $POLICY6) +;
    Far fewer lines, and you get to use the cool ||= and postfix for operators! :-)

    Russ
    Brainbench 'Most Valuable Professional' for Perl

      Thanks I really didn't think about grouping it like that.

      --BigJoe

      Learn patience, you must.
      Young PerlMonk, craves Not these things.
      Use the source Luke.
(tye)Re: A seeming random error.
by tye (Sage) on Feb 10, 2001 at 11:15 UTC

    Download (from CPAN) and install the latest version (0.24) of Win32::TieRegistry to eliminate the spurious error. Installing the module only involves put a single *.pm file in place so it isn't much work to install the new version in your own directory if you can't get the site to update the module.

    I can't believe it took me this long to fix this... I'm so ashamed. ).: (I changed jobs, had a truncated *.zip file as my first backup, had a bad block on my tape backup, still don't have my new computer working again, ...)

            - tye (but my friends call me "Tye")
      Thanks tye. It worked great.

      --BigJoe

      Learn patience, you must.
      Young PerlMonk, craves Not these things.
      Use the source Luke.
Re: A seeming random error.
by 2501 (Pilgrim) on Nov 29, 2000 at 23:08 UTC
    I have gotten these errors before from the following:
    If you are using https, and a mac (with IE, and I THINK netscape) and you leave the secure area, and try to back your browser back into the secure area, you will get that error.
    It sort of looked like macs weren't caching secure pages. This error does not occur if you use a pc though.