Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Checking installed MySQL databases with DBI

by fpi (Monk)
on Mar 22, 2001 at 02:10 UTC ( [id://66159]=perlmeditation: print w/replies, xml ) Need Help??

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.

    Replies are listed 'Best First'.
    Re: Checking installed MySQL databases with DBI
    by tadman (Prior) on Mar 23, 2001 at 00:07 UTC
      I've always been a fan of:
      sub DBList { my ($db_ref) = $db->selectcol_arrayref("SHOW DATABASES"); return @$db_ref if ($db_ref); return; }
      I'm not sure about the portability of that...
    Re: Checking installed MySQL databases with DBI
    by Dragonfly (Priest) on Mar 22, 2001 at 13:58 UTC
      Thank you very much for posting these, I have a nagging feeling I'll need to refer to this post at some point in the extremely near future. (:

      Perhaps someone could figure out how to extend the DBI into a sub-module that abstracted the database issue? It could check for environmentals and depending on what it found, execute the database-specific code from there... it would be only sort of non-portable then, kind of like DBD::xxx ... hmmm... too early, should probably drink some coffee before I go spouting off like this. =P

    Re: Checking installed MySQL databases with DBI
    by elwarren (Priest) on Mar 23, 2001 at 02:19 UTC
      There is only so much you can do to make this portable to other database platforms such as Oracle. Reason is that Oracle handles things like databases and schemas much differently than mySQL.

      In Oracle you will need to connect to each database/instance as a user/schema with DBA privileges and submit a query to list all of the users/schemas. Without an existing account and an existing database you won't get very far.

      Actually, if you only wanted a list of databases/instances you could load and parse the /etc/oratab file. This file contains a list of all oracle databases on the host, along with their respective ORACLE_HOME locations, and whether or not they should startup or shutdown automatically. This would give you your database list but you'd still have to connect as a user to get a user list.

      HTH
    Re: Checking installed MySQL databases with DBI
    by $code or die (Deacon) on Mar 23, 2001 at 17:54 UTC
      Hi, I'm slightly off topic, but have you seen this database frontend to mySQL.

      It might be useful to look at the modules included in that distro.

      $ perldoc perldoc
    Re: Checking installed MySQL databases with DBI
    by geektron (Curate) on Jan 11, 2005 at 21:11 UTC
      search++, and this node++ ( even if it is old ).

      i was just tackling the same problem, walking down the same goofs, and then search gave this node up.

      thanks!

    Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Domain Nodelet?
    Node Status?
    node history
    Node Type: perlmeditation [id://66159]
    Approved by root
    help
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this?Last hourOther CB clients
    Other Users?
    Others studying the Monastery: (2)
    As of 2024-04-26 03:12 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found