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

G'day all

I am writing 5 scripts, which all use the same mySQL database. I have sorted out the DBI and it all works now :) (Cheers fellow monks!)

The problem is, each of these 5 scripts have to have a section defining the variables such as the username, password, database etc so as to access mySQL.

I'd like to store this information in a file, which they can all access and require(). I understand that 'pointers' are required to to this as I am using strict... however I'm not sure exactly how to use a pointer or where to read up on them. I've tried a search without success...

this is what I currently have in each script
## Read the current vote number from the mySQL database. my $dbh = DBI->connect("DBI:mysql:$database","$username","$passwor +d") || error_fatal ("[ vote.cgi: Admin: Unable to open mySQL database + - $! ]"); my $sth_1 = $dbh->prepare("SELECT current_vote FROM vote_count;"); $sth_1->execute(); my @vote_no = $sth_1->fetchrow_array(); my $current_vote = $vote_no[0];
I'd like to be able to have $current_vote and the other variables worked out in the library file and then I can just use them in the other scripts as this is common to all of them.

I currently have this in the library file
sub return_variables { my $server_root = "/var/www/"; ## MySQL database configuration. my $database = "mercury:localhost"; my $username = "mercurus"; my $password = "mercurus"; my @variables = ("$server_root","$db_database","$db_username", +"$db_password"); return @variables; }
How do I use pointers to access these variables from the library file in the main script? (using strict)

Cheers
lagrenouille

Replies are listed 'Best First'.
Re: Includes, strict and pointers.
by jarich (Curate) on Sep 23, 2002 at 05:37 UTC
    I have no idea where you got the idea that you needed pointers, but if this is common code, you might want to create a library/module and put the code in there.

    For example:

    package Mylibrary; use strict; use DBI; my $database="somedb:localhost"; my $username="username"; my $password="password"; sub connect { my $dbh = DBI->connect("DBI:mysql:$database", "$username","$password") or error_fatal("blah"); return $dbh; } sub get_current_vote { my ($dbh) = @_; # if we're not connected (or weren't passed # a connection), connect $dbh ||= connect(); my $sth = $dbh->prepare("SELECT current_vote FROM vote_count;"); $sth->execute() or die $dbh->errstr(); my $current_vote = ($sth->fetchrow_array())[0]; return $current_vote; } 1;
    and then you can do the following in your scripts:
    # my funky script use strict; use DBI; use Mylibrary; # connect to library: my $dbh = Mylibrary::connect(); # get current vote: my $current_vote = Mylibrary::get_current_vote($dbh);

    No need for pointers, and the yucky require can be omitted too. What is more, you've got a ready location for any extra functions you find yourself using in all, or most of your scripts. (You can also export your functions from the Mylibrary namespace, but you can read up on that.)

    Hope it helps,
    jarich.

    Update: Call the file with the Mylibrary package in it Mylibrary.pm, and either store it in the same directory with all the scripts that use it or add a use lib line in your scripts like the following:

    # my funky script use strict; use DBI; use lib '/path/to/my/library/'; use Mylibrary;
    Note that the use lib line must be before the use Mylibrary line.
      Hi,

      To add my $0.02... if you're going the OO way, you can add a DESTROY {} routine which checks for open DB connections and properly closes them before going out of scope. This is especially useful when using commit/rollback (you should do a rollback in this case of course!).

      sub DESTROY { $self = shift; # assume database handle is stored in blessed object if ($self->{dbh}) $self->{dbh}->rollback(); $self->{dbh}->disconnect() || croak $self->{dbh}->errstr; } }

      I like this "trick" very much, because it saves me if some unforeseen error occurs and of course it serves the virtue of laziness.

      --
      Cheers, Joe

      Cheers

      That makes a lot of sense, I'll go with that...

      One question though... the "use Mylibrary" will use a file I assume, called Mylibrary.pm ..?
      If so, where does this file need to be located ?
      or can I specify it with a path prepended to the package name?

      Cheers
      lagrenouille
Re: Includes, strict and pointers.
by blakem (Monsignor) on Sep 23, 2002 at 05:41 UTC
    Its a bit more abstraction than you're asking for, but I've found DBIx::DWIW to be a perfect fit for this situation.

    After the initial configuration (i.e. putting your user/pass in a customized VoteDBI.pm package), you can replace all the username/password/connect code above with a single line, such as:

    my $db = VoteDBI->Connect('vote_table') or die;
    Besides, its what Yahoo! Finance is using, so its got to be good, right?

    p.s. As shipped, the module is MySQL specific, but I have a hacked version that works with postgresql. A couple lines changes and you can probably get it working with your favorite database, too.

    -Blake

Re: Includes, strict and pointers.
by graff (Chancellor) on Sep 23, 2002 at 06:24 UTC
    Funny, someone else asked a related question a little while ago, which led me to look up this post of mine from a few months ago.

    It's a module that serves as a "wrapper" for DBI, which lets me do "use DbiFunc;" instead of "use DBI" in all the DB related scripting I do (using oracle on solaris for a wide range of distinct projects, table spaces, DB accounts).

    In addition to solving the problem about keeping the account name/password/environment settings all in one place, it also provides a small number of easy-to-use (and easy-to-remember) methods that make the DB transactions a lot quicker to code, and cover virtually all the kinds of actions I typically need. I hope it gives a useful example of the approach, at least.

Re: Includes, strict and pointers.
by krisahoch (Deacon) on Sep 23, 2002 at 12:18 UTC

    lagrenouille

    use Config::Properties

    Contents of a properties file.
    dbdriver = DBI:mysql
    dbname = DatabaseName
    dbhost = localhost
    dbport = 3306
    dbuser = root
    dbpass = rotorooter

    You would not believe how awesome that module is. I have 3 different databases to access (At work). I use the same script to access, and disconnect for each of them. I simply feed the script a fh reference to the proerties file, or the properties file name, and the script does the rest.

    If you like, I will post the code here for you.

    Kristofer Hoch