I just wanted to share what I discovered the hard way when using Perl to do something as simple as checking to see what MySQL databases are installed locally on a Unix machine. This may be easy stuff for the experienced users, but none of this was apparent from reading the man DBI, man DBD::mysql pages and O'Reilly's MySQL book which contains a couple of chapters focusing on Perl.

Given:
use DBI; use DBD::mysql; #although not used in this example
Assume that the code already verifies that mysqld is running.
Also assume you have the default mysql:user grant table in MySQL:
HostnameUserPassword (permissions...)
localhostroot abcdefg (full...)
localhost (blank) (blank) (limited...)

Problem: Get a list of existing MySQL databases on the local Unix machine.My initial concern was to keep the code as portable as possible in terms of linking to another database engine (e.g., changing the 'mysql' to 'oracle') in the future. Also, this program is meant to be installed and used on many machines, i.e. not just as a standalone website or one-time solution.

Solutions:
option 1: From what I understood from the docs, the most portable way of accessing a list of existing mySQL databases was to use the following:
my @installed_databases = DBI->data_sources('mysql');
This method works fine for MySQL and on my machine, until I started installing the script on another machine with the same architecture.Then I began to get privilege errors and I couldn't figure out why. I knew from the docs that this statement only works for the localhost access, but it still should have worked. Finally I discovered the reason: because you can't specify a user and password with this method, it defaults to the user running the perl program. if you specified a MySQL root password in your grant table, then you can't run your perl program as root (or any user with a localhost entry with a password in your grant table for that matter). You need to run the program as any user without a password.
  • ADVANTAGES: Supposed to be most portable to other database engines. Also, easiest option if your program is a one-time solution that will live just on your machine.
  • DISADVANTAGES:Can't specify host, so only good for default localhost. Can't specify user and password, so you essentially can't run the perl program as a user that has a password in the MySQL grant table, including root.


  • option 2: Ok, so the next recommended option was to go with a supported, but less portable way:
    my $drh=DBI->install_driver('mysql'); my @installed_databases= $drh->func($HOST,'_ListDBs');
    This install_driver method comes straight out of the DBI docs. I used it because at first I didn't know it was possible to connect to MySQL without specifying a database. It works fine, but it had the same problem as above, in that you couldn't run the program as a user that had a password in the MySQL grant table, eg. as root.
  • ADVANTAGES: You can specify host.
  • DISADVANTAGES: Not portable to other database engines? Can't specify user or password, so you essentially can't run the perl program as a user that has a password in the MySQL grant table, including root.


  • option 3: So at this point I found a way to list the databases where I could specify my username and password....by using the command line:
    my @installed_databases = `mysqlshow --user=$USERNAME --password=$PASS +WORD`;
    which worked fine,and you could even specify a --host tag if you needed. (By the way, those are `back quotes`, not 'single quotes', if you've never used them before). It didn't matter if you ran the program as root or any other user. However,the problem with this was that it would definitely not be portable to other database engines that I would try in the future.
  • ADVANTAGES: You can easily specify host, user, password. You can test output right away from the command line.
  • DISADVANTAGES: Definitely NOT portable to other database engines.


  • option 4: But after a post to Perl Monks, I learned something important from a reply: you do not have to specify a database when using the DBI connect method - something which is never mentioned in the docs or book. So I go back to option 2, but modify it like this:
    my $dbh=DBI->connect("DBI:mysql:host=$HOST",$USER,$PASSWORD); my @installed_databases= $dbh->func('_ListDBs');
    You can leave out the host=$HOST to default to localhost (but leave the trailing colon after mysql, i.e. 'DBI:mysql:').
    Works fine. Portable to other databases engines? I'm not sure, but I'm sure it is more portable than option 3.
  • ADVANTAGES: You can easily specify host, user, password. And a database, once you have an existing one.
  • DISADVANTAGES: May not be portable to other database engines?


  • Comments, corrections, and other options are welcome. If none, then I hope this just helps someone in the future.

    Update: Summarized options with advantages/disadvantages.

    In reply to Checking installed MySQL databases with DBI by fpi

    Title:
    Use:  <p> text here (a paragraph) </p>
    and:  <code> code here </code>
    to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.