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

I am trying to extract information from within a stream of information coming from a web server to a web browser. To do this I have been using the HTTP::Proxy (http://search.cpan.org/~book/HTTP-Proxy-0.24/lib/HTTP/Proxy.pm). I have been successful at installing the proxy and getting the browser to access the server using the proxy. I have even been successful at getting the proxy to store the data in a MySQL database.

My problem is when I try to set up the DBI interface in the init subroutine and use it in the filter subroutine. I want to do this way as to not incur the cost of setting up the DBI connection each time the filter is called. This will happen at least 1 time per second.

Here is the code:
package testfilter; use strict; use warnings; use DBI; use base qw( HTTP::Proxy::HeaderFilter ); sub init {my ($self) = @_; # Connect to the database.and store the reference in the hash my $dbh = DBI->connect("dbi:mysql:woo",'swoo','password', {'RaiseE +rror' => 1}); my $inth = $dbh->prepare( q{INSERT INTO foo (id, name) VALUES (?, +?)}); $inth->execute("1","jim"); $self->{INSERT} = \$inth; } sub filter { my ( $self, $headers, $message ) = @_; my $inth = $self->{INSERT}; $inth->execute("2","tom"); my $dbha = DBI->connect("dbi:mysql:woo",'woo','password', {'RaiseE +rror' => 1}); my $intha = $dbha->prepare( q{INSERT INTO foobar (id, name) VALUES + (?, ?)}); $intha->execute("1","$self->{INSERT}"); } 1;
I know the init is being called to initialize the object and I know the filter is being called when a message is passed through the proxy. I can tell this by the DB entries that are made after running the code.

The problem is that the query objects are not being stored in the hash of the filter object or they are not being retrieved properly. So, how do I store an object within an object and retrieve it.

Thanks for any help you can give

PS The way I attacked this problem was to store the reference to the query object in the filter object's hash in the init and then to retrieve that reference in the filter. Not to sure how to cast a reference back to an object. This may be the problem.

Replies are listed 'Best First'.
Re: Object in an object
by ikegami (Patriarch) on Oct 03, 2009 at 03:31 UTC

    The problem is that the query objects are not being stored in the hash of the filter object or they are not being retrieved properly

    Are you saying that $inth->execute("2","tom"); is failing since $inth doesn't contain the prepared statement? If so, what does $self->{INSERT} contain? Data::Dumper should be useful here.

    $intha->execute("1","$self->{INSERT}")

    What is that trying to do? Is that your debug code for figuring out what $self->{INSERT} contains? If so, you forgot to tell us.

      Thanks for the reply. I thought that that was the problem. As for the line of code you asked about; that was an attempt to determine if the object was being stored in the hash of the filter object or not. I was hoping to see the reference stored in the DB if it was being stored in the filter's hash. This experiment did not work, though. Nothing was stored in the DB for this line of code.

        If $inth->execute("2","tom"); fails, it'll throw an exception, so the "$dbha" code will never be reached. In other words, your debugging code is buggy. Change

        $inth->execute("2","tom");
        to
        eval { $inth->execute("2","tom"); };
        or change the order of your code.

        If $inth->execute("2","tom"); fails, it'll throw an exception, so the "$dbha" code will never be reached. In other words, your debugging code is buggy. Change

        $inth->execute("2","tom");
        to
        eval { $inth->execute("2","tom"); };
        or change the order of your code.
Re: Object in an object
by CountZero (Bishop) on Oct 03, 2009 at 07:04 UTC
    If I understand your problem well, you are trying to implement some form of persistent connections to your database to avoid the start-up cost of fresh connections for every request through your proxy and you are trying to do so at the level of a prepared database statement handle.

    But did you consider the fact that HTTP::Proxy can handle multiple request concurrently (it being a forking proxy) and thus you could end up with separate instances of the proxy-code using the same prepared database statement handle? I'm not too sure whether DBI supports that. At the very best, you may be able to share the database handle, but that will save you already the connection cost. The time used to prepare a statement handle is usually very small: many drivers just store the SQL-string and return immediately without doing any real preparation work. All that is part of their execute code.

    Try your above code again but just store the $dbh handle in the object and --BTW-- you do not have to store a reference to the database handle in the object, just the database handle itself should do fine.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James