Nic Sandfield > Mojar-Mysql-2.033 > Mojar::Mysql::Connector

Download:
Mojar-Mysql-2.033.tar.gz

Dependencies

Annotate this POD

Website

View/Report Bugs
Module Version: 2.033   Source   Latest Release: Mojar-Mysql-2.034

NAME ^

Mojar::Mysql::Connector - MySQL connector (dbh producer) with added convenience

SYNOPSIS ^

In an application making only one type of connection.

  use Mojar::Mysql::Connector (
    cnfdir => '/var/local/auth/myapp',
    cnf => 'rw_localhost',
    schema => 'Users'
  );
  ...
  my $dbh = Mojar::Mysql::Connector->connect;

In an application making multiple types of connection.

  use Mojar::Mysql::Connector (
    cnfdir => '/var/local/auth/myapp'
  );

  my $read_connector = Mojar::Mysql::Connector->new(
    cnf => 'ro_remotehost',
    schema => 'Orders'
  );
  my $write_connector = Mojar::Mysql::Connector->new(
    cnf => 'rw_localhost',
    schema => 'Reports'
  );
  ...
  $read_connector->connect->do(q{...});
  ...
  my $read_dbh = $read_connector->connect(
    auto_reconnect => 1
  );
  my $write_dbh = $write_connector->connect;

Employing a helper.

  use Mojar::Mysql::Connector (
    cnfdir => '/var/local/auth/myapp',
    cnf => 'rw_localhost',
    schema => 'Users',
    -dbh => 1
  );
  sub do_some_db_doodah {
    my $self = shift;
    my $dbh = $self->dbh;
    ...
  }

From the commandline.

  perl -MMojar::Mysql::Connector="cnf,ro_localhost,schema,Users,-dbh,1"
    -E'say join qq{\n}, @{main->dbh->real_tables}'

DESCRIPTION ^

MySQL-specific extension (subclass) to DBI in order to improve convenience, security, and error handling. Supports easy use of credential/init files, akin to

  mysql --defaults-file=$CRED_FILE

It aims to reduce boilerplate, verbosity, mistakes, and parameter overload, but above all it tries to make it quick and easy to Do The Right Thing.

As the name implies, the class provides connector objects -- containers for storing and updating your connection parameters. When you call connect, the connector returns a handle created using its retained parameters plus any call-time parameters you may have used in the call. You don't however have to use connectors and for simple usage it can be easier to use connect directly from the class.

USAGE ^

One of the main advantages of using this subclass in place of the standard DBI is the provision of a set of defaults that can be overridden. For instance, a script can define a cnfdir and cnf early on, then redefine cnf for connections to a different server. Various examples of usage are given below ("Using defaults") after the parameters themselves have been introduced.

Class/object parameters

  RaiseError           => 1,
  PrintError           => 0,
  PrintWarn            => 0,
  AutoCommit           => 1,
  TraceLevel           => 0,
  mysql_enable_utf8    => 1,
  mysql_auto_reconnect => 0,
  label                => undef,
  cnfdir               => '.',
  cnf                  => undef,
  cnfgroup             => undef,
  driver               => 'mysql',
  host                 => undef,
  port                 => undef,
  user                 => undef,
  password             => undef,
  schema               => undef

These are the parameters that can be set as class defaults, connector defaults, connection-specific ('one of'), or a combination of those. The following subset are those parameters that govern behaviour of a db connection:

  RaiseError
  PrintError
  PrintWarn
  AutoCommit
  TraceLevel
  mysql_enable_utf8
  mysql_auto_reconnect

"ATTRIBUTES COMMON TO ALL HANDLES" in DBI is the authority on the first five, their effects and when/why to use them, while "DATABASE-HANDLES" in DBD::mysql is the authority on the latter two, their effects and when/why to use them.

Note that unless RaiseError is changed, connections will throw exceptions rather than need their return values checked. This is the most robust style since it is never fooled by genuinely 0 or undef return values, and the exception can be handled at whatever call-level you deem appropriate. (This style works best if you use a try-catch mechanism such as eval {} or do {} in core perl or try/catch in Try::Tiny or Error.)

If your data uses characters that are non-ascii and non-UTF8 then be sure to override mysql_enable_utf8:

  mysql_enable_utf8 => 0

The following subset are those parameters that govern making a db connection (DSN) series:

  driver
  host
  port
  user
  password
  schema

None of host, port, user, password is required if you are using credentials files (recommended). One of the primary motivations for this (sub)class is to avoid having credentials mixed in with your code.

The following subset is simply to identify a credentials set that will be passed to the DBI (actually DBD::mysql) with the connection string.

  cnfdir
  cnf
  cnfgroup

Note that currently the credentials file is passed to DBI without being parsed first. (A future version may support parsing parameters from the file.)

Which leaves the following.

  label

So in summary the parameters most likely to need overriding are

  AutoCommit
  cnfdir
  cnf
  schema

Using defaults

As you would expect, there is a hierarchy for setting parameters that take effect for new connections.

0.

Class definition file (.pm)

1.

'use' params

2.

connector params

3.

dbh (connection-specific) params

Each level overlays its definitions over those of the level above so that the value in effect for a connection is the value in the latest level at the time the connection is created. This flexibility might be a bit confusing at first, but examples below should show that individual usage is very simple. It is expected that some users will use only class defaults, some will use only object defaults, some will use a combination, and some will use neither.

Class definition

The values in the class definition file are shown above ("Class/object parameters") and should stay static through subsequent released versions.

Use-time parameters

The calling code can override/set defaults upon use.

  #!/usr/bin/env perl
  use Mojar::Mysql::Connector (
    cnfdir => '/srv/myapp/cfg',
    cnf    => 'myuser_localhost',
    schema => 'Stats'
  );

That sets the class defaults for the remainder of that script or package, and for simple cases that is the only place your code needs to deal with connection parameters. When using a persistent multi-application environment (mod_perl, plack, hypnotoad, ...) bear in mind that class parameters are shared across the process (perl interpreter instance).

Connectors

Connectors are objects that you pack with your preferred connection parameters and then have ready to supply you with database connections. Their use is entirely optional, but their advantages include the following.

  use Mojar::Mysql::Connector;
  my $connector_source = Mojar::Mysql::Connector->new(
    cnfdir => '/srv/myapp/cfg',
    cnf => 'myuser_sourcehost',
    schema => 'Orders');
  my $connector_target = $connector_source->new(
    cnf => 'myuser_targethost',
    schema => 'Reports');

  while (...) {
    my $dbh_s = $connector_source->connect;
    my $dbh_t = $connector_target->connect;
    ...
    $dbh_s->disconnect;
    $dbh_t->disconnect;
  }

If on the other hand your code makes several connections to one db server and then all its connections are to a second db server, you can use just one connector and modify its params when appropriate.

  my $connector = Mojar::Mysql::Connector->new(cnf => 'myuser_source1');
  my $dbh = $connector->connect(schema => 'Preorders';
  ...
  $dbh->disconnect;
  $connector->cnf('myuser_source2');
  $dbh = $connector->connect;
  ...

You could of course achieve the same effect in that example using no connectors and overriding in the connect.

  my $dbh = Mojar::Mysql::Connector->connect(
    cnf => 'myuser_source1',
    schema => 'Preorders');
  ...
  $dbh->disconnect;
  $dbh = Mojar::Mysql::Connector->connect(
    cnf => 'myuser_source2',
    schema => 'Profiles');
  ...

DBH connection-specific parameters

The illustrations above have all shown persisting changes to the defaults at either the class or object level; the new defaults are in effect till the end of the package/script or till they are changed. You may also want to pass parameters that you do not want to persist, a common example being turning off autocommit.

  $dbh = Mojar::Mysql::Connector->connect(AutoCommit => 0);

or

  $dbh = $connector->connect(AutoCommit => 0);

AutoCommit is 0 for this connection, but defaults are unaffected.

Inheritance vs parameter overlay

The above illustrates a general principle of the interplay of inheritance and parameter overlay; when an object is created it inherits its base values from the entity it is created from and overlays on top of those any additional parameters it is passed. Exactly as you would expect, these additional parameters have no effect on the entity from which the object was created.

  $connector = Mojar::Mysql::Connector->new(label => 'readonly');
  $dbh = $connector->new(label => 'readwrite');
  say Mojar::Mysql::Connector->label;  # still undef
  say $connector->label;  # still 'readonly'

Class methods

new

  Mojar::Mysql::Connector->new(label => 'cache', cnf => 'myuser_localhost');

Constructor for a connector based on class defaults. Takes a (possibly empty) parameter hash. Returns a connector (Mojar::Mysql::Connector object) the defaults of which are those of the class overlaid with those passed to the constructor.

Defaults

  print Data::Dumper::Dumper(Mojar::Mysql::Connector->Defaults);

Provides access to the defaults hashref that holds the class defaults in order to help debugging. Each default has a getter/setter of the same name, but as described previously, it's fairly risky to change class defaults during runtime if you have other code sharing those defaults.

connect

 $dbh1 = Mojar::Mysql::Connector->connect(
   'DBI:mysql:test;host=localhost', 'admin', 's3cr3t', {});
 $dbh2 = Mojar::Mysql::Connector->connect(AutoCommit => 0);
 $dbh3 = Mojar::Mysql::Connector->connect;

Constructor for a connection (db handle). If the first element passed has prefix DBI: then it is a DSN string (the traditional route) and so is passed straight to DBI::connect ("DBI Class Methods" in DBI). Otherwise a DSN is first constructed. (The DSN series does not persist and is constructed fresh on each call to connect.)

dsn

  @dbi_args = Mojar::Mysql::Connector->dsn(
    cnf => 'myuser_localhost', schema => 'test');

A convenience method used internally by connect. Takes a (possibly empty) parameter hash. Returns a four-element array to pass to DBI-connect>, constructed from the default values of the constructing class overlaid with any additional parameters passed. Probably the only reason for you using this method is if you need to use DBI directly but want to avoid the inconvenience of constructing the parameters yourself.

  use DBI;
  use Mojar::Mysql::Connector (
    cnfdir => '/srv/myapp/cfg',
    cnf => 'myuser_localhost'
  );
  my $dbh = DBI->connect(
    Mojar::Mysql::Connector->dsn(schema => 'foo', AutoCommit => 0));

dsn_as_string

  Carp::carp(Mojar::Mysql::Connector->dsn_as_string(@dsn));

A convenience method used internally to chop up the four-element array (particularly the fourth element, the hash ref) into something more readable, eg for error reporting and debugging.

Object methods

new

  $connector->new(label => 'transaction', AutoCommit => 0);

Constructor for a connector based on an existing connector's defaults. Takes a (possibly empty) parameter hash. Returns a connector (Mojar::Mysql::Connector object) the defaults of which are those of the given connector overlaid with those passed to the constructor.

connect

  $dbh = $connector->connect(
    'DBI:mysql:test;host=localhost', 'admin', 's3cr3t', {});
  $dbh = $connector->connect(AutoCommit => 0);
  $dbh = $connector->connect;

Constructor for a connection (db handle). If the first element passed has prefix DBI: then it is a DSN string (the traditional route) and so is passed straight to DBI::connect ("DBI Class Methods" in DBI). Otherwise a DSN is first constructed. (The DSN series does not persist and is constructed fresh on each call to connect.)

Attributes

All connector parameters are implemented as attributes with exactly the same spelling. So for example you can

  $connector->RaiseError(undef);  # disable RaiseError
  $connector->mysql_enable_utf8(1);  # enable mysql_enable_utf8

These also function as class attributes, but as previously mentioned, safest to use only as getters rather than class setters.

Database handle methods

mysqld_version

  if ($dbh->mysqld_version =~ /^5.0/) {...}

Returns the version of the db server connected to; the version part of

  mysqld --version

thread_id

  $tmp_table_name = q{ConcurrencySafe_}. $dbh->thread_id;

Utility method to get the connection's thread identifier (unique on that db server at that point in time).

current_schema

  $schema_name = $dbh->current_schema;

The same string as given by

  SELECT DATABASE();

session_var

  my ($old) = $dbh->session_var(sql_mode => 'ANSI_QUOTES');
  ...
  $dbh->session_var(sql_mode => $old);

Getter/setter for session variables. To get a value, simply pass the variable's name.

  $value = $dbh->session_var('date_format');

In list context returns the old value and the new value; in scalar context returns the handle to facilitate chaining.

  $dbh->session_var(var1 => ...)
      ->session_var(var2 => ...);

disable_quotes

  my @ddl = $dbh->disable_quotes->selectrow_array(q{SHOW CREATE ...});

Disable optional quotes around identifiers. Currently only affects output of SHOW CREATE TABLE. If you have unsafe identifiers (eg spaces or keywords) then those will still be quoted. Lasts the lifetime of the connection.

enable_quotes

The inverse of disable_quotes.

disable_fk_checks

  $dbh->disable_fk_checks->do(q{DROP TABLE ...});

Disable foreign key checks. Lasts the lifetime of the connection.

enable_fk_checks

The inverse of disable_fk_checks.

schemata

  for my $schema (@{$dbh->schemata}) {...}

Returns a hashref of schema names, similar to

  SHOW DATABASES

but does not get fooled by lost+found.

tables_and_views

  foreach my $table ($dbh->tables_and_views) {...}

Returns a hashref of table and view names, similar to

  SHOW TABLES

See also "tables" in DBI.

real_tables

  for my $table (@{$dbh->real_tables}) {...}

Returns a hashref of real table names, similar to

  SHOW TABLES

but excluding views.

views

  for my $view (@{$dbh->views}) {...}

Returns a hashref of view names, similar to

  SHOW TABLES

but excluding real tables.

SUPPORT ^

Homepage

http://niczero.github.com/mojar-mysql

Wiki

http://github.com/niczero/mojar/wiki

RATIONALE ^

This class was first used in production in 2002. Before then, connecting to databases was ugly and annoying. Setting RaiseError upon every connect was clumsy and irritating. In development teams it was tricky checking that all code was using sensible parameters and awkward ensuring use of risky parameters (eg disable_fk_checks) was kept local. As use of this class spread, it had to be useful in persistent high performance applications as well as many small scripts and the occasional commandline. More recently I discovered the Joy of Mojolicious and employed Mojo::Base to remove unwanted complexity and eliminate a long-standing bug. The ensuing fun motivated an extensive rewrite, fixing broken documentation, improved the tests (thank you travis), and we have, finally, its public release. As noted below there are now quite a few smart alternatives out there but I'm still surprised how little support there is for keeping passwords out of your codebase and helping you manage multiple connections.

SEE ALSO ^

Coro::Mysql, AnyEvent::DBI, DBIx::Custom, DBIx::Connector.

COPYRIGHT AND LICENCE ^

Copyright (C) 2002--2013, Nic Sandfield.

This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.

syntax highlighting: