.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Gantry::Docs::DBConn 3"
.TH Gantry::Docs::DBConn 3 "2008-01-18" "perl v5.8.8" "User Contributed Perl Documentation"
.SH "Name"
.IX Header "Name"
Gantry::Docs::DBConn \- how database connection info flows through Gantry
.SH "Intro"
.IX Header "Intro"
One of the problems with separating models from the rest of any application
is how to inform the model of the database connection information. This
document explains how that information makes its way to the model.
.PP
This document does not apply to DBIx::Class, which has a cleaner way
of moving this information from conf to code. See
Gantry::Plugins::DBIxClassConn for how Gantry works with dbic.
.SH "Environments (a.k.a. Engines)"
.IX Header "Environments (a.k.a. Engines)"
Gantry supports plugable engines. Currently there are engines for \s-1CGI\s0
and mod_perl versions 1.3, and 2.0. Further, many gantry apps have
scripts which also want to use the models. There is now a comprehensive
solution for all of these.
.Sh "Scripts"
.IX Subsection "Scripts"
The simplest environment is the script. A script has essentially three
choices for where to obtain connection information: (1) hard
coded in the script, (2) taken from the command line, (3) taken from
a config file (which could be an apache conf).
.PP
Where the information comes from matters not to the gantry. Once you know
where your information will come from, you have two options for passing it
to the model.
.PP
If the information is known at compile time (i.e. it is hard coded), you
may simply say:
.PP
.Vb 5
\& use Gantry::Utils::DBConnHelper::Script {
\& dbconn => 'dbi:Pg:dbname=some_db;host=127.0.0.1',
\& dbuser => 'someone',
\& dbpass => 'super_secret',
\& };
.Ve
.PP
Note that the dbconn key must have the full dsn needed by the \s-1DBI\s0's connect
method. This is true for all environments.
.PP
If you must calculate the information do the above in two steps:
.PP
.Vb 1
\& use Gantry::Utils::DBConnHelper::Script;
.Ve
.PP
.Vb 1
\& # pull in your information from command line or conf file
.Ve
.PP
.Vb 7
\& Gantry::Utils::DBConnHelper::Script->set_db_conn_info(
\& {
\& dbconn => $dsn,
\& dbuser => $dbuser,
\& dbpass => $dbpass,
\& }
\& );
.Ve
.PP
Note that in both cases you should pass a hash reference.
.PP
If you need to access models which inherit from Gantry::Utils::AuthCDBI
(or one of its authentications cousins), you need to also call
set_auth_db_conn_info on Gantry::Utils::DBConnHelper::Script.
That call is the same as the one for set_db_conn_info, except that
the hash keys are auth_dbconn, auth_dbuser, and auth_dbpass.
.Sh "mod_perl"
.IX Subsection "mod_perl"
Gantry is ready to help you with connection information. The normal approach
is to use PerlSetVars in your httpd.conf:
.PP
.Vb 4
\&
\& PerlSetVar dbconn dbi:Pg:dbname=some_db;host=127.0.0.1
\& PerlSetVar dbuser someone
\& PerlSetVar dbpass super_secret
.Ve
.PP
.Vb 4
\& PerlSetVar auth_dbconn dbi:Pg:dbname=auth_db;host=127.0.0.1
\& PerlSetVar auth_dbuser auth_user
\& PerlSetVar auth_dbpass double_super_secret
\&
.Ve
.Sh "\s-1CGI\s0"
.IX Subsection "CGI"
Note that gantry does user authentication, but only in the mod_perl
environment at present. Even so, some of your models may inherit
from an auth utils module. In that case, you need to provide the auth
values below.
.PP
Gantry also helps \s-1CGI\s0 scripts. Simply include the dbconn, dbuser, and
dbpass keys (and their auth counterparts, if needed) in the config section
of the hash you pass to Gantry::Engine::CGI\->new:
.PP
.Vb 11
\& my $cgi = Gantry::Engine::CGI->new( {
\& locations => {
\& '/' => 'App::Base',
\& # ...
\& },
\& config => {
\& # ...
\& dbconn => 'dbi:Pg:dbname=some_db;host=127.0.0.1',
\& dbuser => 'someone',
\& dbpass => 'super_secret',
\& }
.Ve
.SH "Internals"
.IX Header "Internals"
So, how does the data flow? Of course, it depends slightly on the environment.
Each has its own source of data and therefore its own scheme. But they all
conform to a single \s-1API\s0 described here.
.PP
Let's start at the other end. When any gantry model wants to use a database,
it calls db_Main. That method is responsible for returning a working dbh.
Here is the db_Main from Gantry::Utils::CDBI (the others look strikingly
similar):
.PP
.Vb 2
\& sub db_Main {
\& my $dbh;
.Ve
.PP
.Vb 1
\& my $helper = Gantry::Utils::DBConnHelper->get_subclass();
.Ve
.PP
.Vb 1
\& $dbh = $helper->get_dbh();
.Ve
.PP
.Vb 2
\& if ( not $dbh ) {
\& my $conn_info = $helper->get_conn_info();
.Ve
.PP
.Vb 1
\& $db_options->{AutoCommit} = 0;
.Ve
.PP
.Vb 8
\& $dbh = DBI->connect_cached(
\& $conn_info->{ 'dbconn' },
\& $conn_info->{ 'dbuser' },
\& $conn_info->{ 'dbpass' },
\& $db_options
\& );
\& $helper->set_dbh( $dbh );
\& }
.Ve
.PP
.Vb 1
\& return $dbh;
.Ve
.PP
.Vb 1
\& } # end db_Main
.Ve
.PP
So, there is a base class Gantry::Utils::DBConnHelper which can return
the subclass which assists the current model. That subclass responds
to get_dbh with a cached handle if one is available (or undef if not).
If the handle is true, it is returned directly. Otherwise, the if
block asks the helper for the connection info as a hash reference.
Then it uses that to connect to the database. Finally, it gives the
helper subclass the newly minted connection handle for caching.
.PP
This completely separates the concerns of the modules. The model knows
how to connect to a database, but relies completely on the helper to
know what database connection info to supply \s-1AND\s0 for caching of connections,
enabling each environment to cache in the most resonable way.
.Sh "Gantry::Util::DBConnHelper"
.IX Subsection "Gantry::Util::DBConnHelper"
The base class for all helpers is Gantry::Util::DBConnHelper. It is mostly
a documentation module. It does have an import method so scripts with
hard coded connection info can save a statement. Further, it has two class
accessors: get_subclass and set_subclass. The former is called by the
model, so it will know which class is actually providing the connection
info for and caching of handles. The later is called by the subclasses
of Gantry::Util::DBConnHelper.
.Sh "Subclasses of Gantry::Util::DBConnHelper"
.IX Subsection "Subclasses of Gantry::Util::DBConnHelper"
The easiest way to understand the subclasses of the connection helper is to
see an example. The simplest example is the script helper. I'll show
just the regular connection routines (since auth works the same with
\&'auth_' in front of 'db' in all variable names and hash keys).
.PP
.Vb 2
\& package Gantry::Utils::DBConnHelper::Script;
\& use strict; use warnings;
.Ve
.PP
.Vb 1
\& use base 'Gantry::Utils::DBConnHelper';
.Ve
.PP
.Vb 3
\& Gantry::Utils::DBConnHelper->set_subclass(
\& 'Gantry::Utils::DBConnHelper::Script'
\& );
.Ve
.PP
.Vb 2
\& my $dbh;
\& my $conn_info;
.Ve
.PP
.Vb 3
\& sub get_dbh {
\& return $dbh;
\& }
.Ve
.PP
.Vb 4
\& sub set_dbh {
\& my $class = shift;
\& $dbh = shift;
\& }
.Ve
.PP
.Vb 3
\& sub get_conn_info {
\& return $conn_info;
\& }
.Ve
.PP
.Vb 4
\& sub set_conn_info {
\& my $class = shift;
\& $conn_info = shift;
\& }
.Ve
.PP
.Vb 1
\& 1;
.Ve
.PP
At the top of the script we see that the module's full name is
Gantry::Utils::DBConnHelper::Script and that it inherits from
Gantry::Utils::DBConnHelper.
.PP
The first thing it should do is register with the base class. There
can only be one connection helper in a given environment, so
it calls the class method set_subclass with its own name. Now the
base module will tell db_Main that this is the subclass with the info
and cache.
.PP
The remainder of the script implements the simplest possible scheme
for storing connection information and cached database handles.
.PP
Remember that scripts call set_conn_info directly (Gantry::Engine::CGI
does this in its constructor) or supply the info in a hash reference
parameter to use. The other methods are called by db_Main as needed.
.PP
The other helpers work similarly with two differences. Obviously,
they use different caching schemes (mod_perl helpers use pnotes).
But, set_conn_info is also handled differently. Here's where they
are:
.PP
.Vb 6
\& engine type where set_conn_info is called
\& -----------------------------------------------------------
\& scripts manually before database work begins
\& CGI Gantry::Engine::CGI->new
\& mod_perl not called, params are fished from dir_config
\& on every request
.Ve
.PP
So, the Gantry::Utils::DBConnHelper subclasses for mod_perl engines
fish their connection information directly from the set vars in
their get_conn_info methods.
.SH "Auth Differences"
.IX Header "Auth Differences"
If you use any model class which inherits from a module with Auth in
the name, you need to supply the auth_* parameters in PerlSetVars (for
mod_perl), as config hash keys (for \s-1CGI\s0), or in a call to set_auth_conn_info
(for self standing scripts).
.SH "Author"
.IX Header "Author"
Phil Crow