2011/11/07

More Details on Traveling Salesman

I have just received mail from a programmer in France who is interested in learning Perl and  asked about some of the constructs in my Traveling Salesman code, specifically asking about MyDB.pm and do_connect. That module and that function are about one thing: getting a DBI object without having to have my login and password and all that within the body of the program, so I can do things like paste it into my blog without worrying. Adapted, it looks like this:

package MyDB ;
use strict;
use warnings;
use DBI;

use Exporter qw(import);
our %EXPORT_TAGS = ('all' => [ qw(
                                   db_connect
                            ) ],
                    );
our @EXPORT_OK   = ( @{$EXPORT_TAGS{'all'}} );
our $VERSION = 0.0.1;
our %_DB = (
    default => {
        user       => 'YouDontGetThis',
        password   => 'YouDontGetThis',
        host       => 'YouDontGetThis',
        port       => '3306',
        database   => 'YouDontGetThis',
        },
    test => {
        user       => 'YouDontGetThis',
        password   => 'YouDontGetThis',
        host       => 'YouDontGetThis',
        port       => '3306',
        database   => 'YouDontGetThis',
        },
    );

my $_db_params  = '';       # String of current database parameters.
my $_dbh;                   # Save the handle.

sub db_connect {
    my ($param_ptr, $attr_ptr) = @_;

    # If database is already opened then check for a fast return.

    if (defined $_dbh &&
        (!defined $param_ptr || $param_ptr eq ''))    { return $_dbh }

    # Check for a different set of parameters to use via a the name (string)
    #   of the parameter (e.g., 'test').

    my $which_db = 'default';

    if (defined $param_ptr && ref($param_ptr) eq '' && $param_ptr ne '') {
        if (defined $_DB{$param_ptr})   { $which_db = $param_ptr }
        else { return; }
    }

    # Get the base parameters ... copy and flatten from global array

    my %params = ();
    my %attr   = ();

    foreach (keys %{$_DB{$which_db}} ) {
        $params{$_} = $_DB{$which_db}{$_};
        }

    # Add in extra parameters if given and if the database is not the default.

    if (defined $param_ptr
        && ref($param_ptr) eq 'HASH'
        && (!defined $param_ptr->{database} ||
             $param_ptr->{database} ne 'default') ) {

        foreach (keys %{$_DB{default}})  {
            if (defined $param_ptr->{$_}) { $params{$_} = $param_ptr->{$_} }
            }
        }

    if (defined $attr_ptr && ref($attr_ptr) eq 'HASH') {
        foreach (keys %$attr_ptr)  { $attr{$_} = $attr_ptr->{$_} }
        }

    # Now make up an order string of the parameters so that we can compare
    #   them to the old ones.

    my $new_db_params = '';
    foreach (sort keys %params)  { $new_db_params .= $params{$_} };

    # Can also do a quick return if params are same as old ones

    if (defined $_dbh && $new_db_params eq $_db_params)  {
        return $_dbh;
        }

    # At this point either the database has never been opened or
    #   new parameters are to be used. Close database and reopen.

    $_db_params = $new_db_params;

    if (defined $_dbh) { $_dbh->disconnect }    # no error check

    my $source = "dbi:mysql:$params{database}:$params{host}:$params{port}";

    $_dbh = DBI->connect($source, $params{user},
                               $params{password}, \%attr);

    return $_dbh;

    } # End of db_connect

1;

 For the particulars, I used something, I think WolframAlpha, to get the latitude and longitude of each capital, then looked into some geometry to calculate the distances. Perhaps I should include some database dumps here. for that info.
Post a Comment