Ronny Riedel: mehr als 407 Zeichen mit "$x->func('dbms_output_get');" lesen

Hallo zusammen,

gegeben sei folgendes PERL-Skript:

#!/usr/bin/perl  
  
use strict;  
use DBI;  
  
# die Umgebungsvariable "ORACLE\_HOME" muss gesetzt werden  
$ENV{ORACLE\_HOME} = '/path/to/oracle/10.2.0';  
  
# DB-Verbindung oeffnen und initialisieren  
my $dbh = DBI->connect("dbi:Oracle:[db]", '[user]', '[pw]');  
$dbh->{RaiseError} = 1;  
$dbh->func(1000000, 'dbms\_output\_enable');  
  
# PL/SQL-Prozedur der DB aufrufen  
my $csr = $dbh->prepare(q{  
             BEGIN  
                FOR i IN 1 .. 407 LOOP  
                   dbms\_output.put('a');  
                END LOOP;  
                --  
                dbms\_output.new\_line;  
             END;  
          });  
$csr->execute;  
  
# alle Daten aus dem Puffer von "dbms\_output" holen  
my @ausgaben = $dbh->func( 'dbms\_output\_get' );  
  
# diese Daten in eine Datei schreiben  
foreach my $ausgabe (@ausgaben) {  
   print $ausgabe;  
   print "\n";  
}  
  
# DB-Verbindung schliessen  
$dbh->disconnect;  
~~~~~~~~~~~~~~~~~~~~~~~~~~~ snap ~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  
Wenn ich das Skript aufrufe, dann erhalte ich 407 mal "a" als ein langer String. Wenn ich jetzt allerdings aus der 407 eine 408 mache, dann erhalte ich gar nichts.  
  
Kann mir bitte jemand erklären, warum das so ist?  
  
Danke & Gruß  
  Ronny R.  

  1. Anmerkung:

    my $csr = $dbh->prepare(q{  
                 BEGIN  
                    FOR i IN 1 .. 407 LOOP  
                       dbms_output.put('a');  
                    END LOOP;  
                    --  
                    dbms_output.new_line;  
                    dbms_output.put_line('Hello World');  
                 END;  
              });
    

    aaaaa[...]aaaa
    Hello World

    Jedoch

    my $csr = $dbh->prepare(q{  
                 BEGIN  
                    FOR i IN 1 .. 408 LOOP  
                       dbms_output.put('a');  
                    END LOOP;  
                    --  
                    dbms_output.new_line;  
                    dbms_output.put_line('Hello World');  
                 END;  
              });
    

    produziert gar keinen Output

  2. getestet unter:

    user@host1> perl -v

    This is perl, v5.10.0 built for x86_64-linux-thread-multi

    Copyright 1987-2007, Larry Wall

    und unter:

    user@host2{~} perl -v

    This is perl, v5.8.8 built for x86_64-linux-thread-multi

    Copyright 1987-2006, Larry Wall

  3. hi,

    Du hast $dbh->{RaiseError} = 1; gesetzt. Nutze es auch, prüfe ob eine Exception auftritt und teste die Prozedur auch mal unabhängig von Perl.

    use English; # now, $@ means $EVAL_ERROR

    Hotti

    1. Moin Moin!

      hi,

      Du hast $dbh->{RaiseError} = 1; gesetzt. Nutze es auch, prüfe ob eine Exception auftritt

      Mumpitz! Da ist kein eval weit und breit, Exceptions hätten das Script sofort beendet.

      und teste die Prozedur auch mal unabhängig von Perl.

      use English; # now, $@ means $EVAL_ERROR

      Was kaum jemandem nützt und in dieser Form jeglichen Code, der RegExps benutzt, massiv ausbremst.

      "Wenn man keine Ahnung hat: Einfach mal Fresse halten." -- Dieter Nuhr

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      1. Moin Moin!

        Du hast $dbh->{RaiseError} = 1; gesetzt. Nutze es auch, prüfe ob eine Exception auftritt

        Mumpitz! Da ist kein eval weit und breit,

        Stimmt, ich habe es bereits beim ->connect vermisst;

        Exceptions hätten das Script sofort beendet.

        Korrekt.

        use English; # now, $@ means $EVAL_ERROR

        Was kaum jemandem nützt

        Das erkläre besser demjenigen, der {RaiseError} = 1; setzt und nicht einmal merkt, dass es

          
          RaiseError => 1  
        
        

        Heißen muss. Ich habs auch nicht gleich gesehen ;)

        "Wenn man keine Ahnung hat: Einfach mal Fresse halten." -- Dieter Nuhr

        Woher kommt eigentlich der Ausdruck 'Fresse'? Ich dächte aus dem Thüringischen, also irgendwie aus dem nördlichen Sprachraum. Da jedoch wohnen Fischköppe und die haben ein 'Maul'.

        Hotti

        1. Hallo nochmal,

          zu

          Das erkläre besser demjenigen, der {RaiseError} = 1; setzt und nicht einmal merkt, dass es

          RaiseError => 1

          
          >   
          > Heißen muss. Ich habs auch nicht gleich gesehen ;)  
            
          Ich hab das von hier: "http://search.cpan.org/~pythian/DBD-Oracle-1.23/Oracle.pm#plsql\_errstr". Im "Example" steht eben  
            
          ~~~perl
            
             $dbh->{RaiseError} = 1;  
          
          

          Wenn die das schon nicht richtig machen, wer dann?

          Grüße
            Ronny R.

          1. Moin Moin!

            Hotti hat keinen Plan. Er frickelt auf Anfängerniveau mit Perl herum und hält sich für den Oberexperten.

            Ich hab das von hier: "http://search.cpan.org/~pythian/DBD-Oracle-1.23/Oracle.pm#plsql_errstr". Im "Example" steht eben

            $dbh->{RaiseError} = 1;

            
            >   
            > Wenn die das schon nicht richtig machen, wer dann?  
              
            <erbsenzähler>Die [DBI](http://search.cpan.org/perldoc?DBI)-Autoren.</erbsenzähler>  
              
            Es ist richtig.  
              
            Es gibt im Grunde zwei unterschiedliche Varianten, das [RaiseError](http://search.cpan.org/~timb/DBI-1.616/DBI.pm#RaiseError)-Attribut zu setzen.  
              
            Entweder als Attribut-Hash-Argument für die [connect](http://search.cpan.org/~timb/DBI-1.616/DBI.pm#connect)-Methode bzw. die [connect_cached](http://search.cpan.org/~timb/DBI-1.616/DBI.pm#connect_cached)-Methode:  
              
            `my $dbh=DBI->connect(...,...,...,{ RaiseError => 1, ... });`{:.language-perl}  
              
            Oder indem Du das Attribut direkt setzt:  
              
            `$dbh->{'RaiseError'}=1;`{:.language-perl}  
              
            Der feine Unterschied ist, dass die erste Variante schon während des connect() wirkt, d.h. ein fehlgeschlagenes connect() löst eine Exception aus. Die zweite Variante wirkt natürlich erst ab der Zuweisung, sollte connect() fehlschlagen, ist $dbh einfach nicht definiert (undef). Das führt dazu, dass Code à la `$dbh->{'SomeAttribute'}=SomeValue`{:.language-perl} bzw. `$dbh->someMethod(...)`{:.language-perl} "viel" später auf die Nase fällt ("Can't call method "someMethod" on an undefined value" bzw. "Can't use an undefined value as a HASH reference"). Daher ist die erste Variante zu bevorzugen.  
              
            Übrigens ist RaiseError eines der Attribute, die man für alle DBI-Handle-Typen setzen kann. Typischerweise setzt man es für den Datenbank-Handle und DBI vererbt das Attribut an die Statement-Handles, aber man kann das Attribut auch manuell für ein Statement-Handle setzen. (Mir fällt nur gerade nicht ein, warum man das machen wollen würde.)  
              
              
            Alexander
            
            -- 
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            
        2. Moin Moin!

          Das erkläre besser demjenigen, der {RaiseError} = 1; setzt und nicht einmal merkt, dass es

          RaiseError => 1

          
          >   
          > Heißen muss. Ich habs auch nicht gleich gesehen ;)  
            
          UNSINN!  
            
          Halt einfach die Klappe, lies die DBI-Doku, und poste erst NACH dem Denken.  
            
          Alexander
          
          -- 
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          
  4. Moin Moin!

    Wenn ich das Skript aufrufe, dann erhalte ich 407 mal "a" als ein langer String. Wenn ich jetzt allerdings aus der 407 eine 408 mache, dann erhalte ich gar nichts.

    Ich sehe keinen offensichtlichen Fehler, und 407 / 408 (plus ggf. 2 Bytes für CR/LF) ist für meinen Geschmack weit unter einer kritischen Größe für irgendwelche Puffer.

    Frag mal bei dbi-users nach.

    Oh, und es gibt kein PERL. Perl mit großem P ist die Sprache, perl mit kleinem p ist das Executable, das Perl-Code verdaut.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
  5. hi,

    $dbh->{RaiseError} = 1;

    Argh. Damit ist dein Script schon tot bevor es lebendig wird. Deine Fehlerbehandlung ist sehr verbesserungsbedürftig, überarbeite das und dann  findest Du auch den Fehler.

    Hotti

    1. Moin Moin!

      hi,

      $dbh->{RaiseError} = 1;

      Argh. Damit ist dein Script schon tot bevor es lebendig wird.

      UNSINN!

      Der Code ist so ok, außer dass er connect()-Fehler nicht abfängt.

      Macht aber nichts, weil $dbh bei einem fehlgeschlagenen connect() undefiniert ist und die nächste Zeile das Script mit "Can't use an undefined value as a HASH reference" killt.

      Deine Fehlerbehandlung ist sehr verbesserungsbedürftig, überarbeite das und dann  findest Du auch den Fehler.

      Bullshit.

      Verkneif Dir bitte solche Schlaumeier-Antworten, wenn Du vom Thema keine Ahnung hast. Das ist nicht hilfreich für den Fragesteller!

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".