DBI
view release on metacpan or search on metacpan
lib/DBI/DBD/SqlEngine/HowTo.pod view on Meta::CPAN
our @ISA = qw(DBI::DBD::SqlEngine::Table);
1;
Tiny, eh? And all you have now is a DBD named foo which will is able to
deal with temporary tables, as long as you use L<SQL::Statement>. In
L<DBI::SQL::Nano> environments, this DBD can do nothing.
=head2 Deal with own attributes
Before we start doing usable stuff with our DBI driver, we need to think
about what we want to do and how we want to do it.
Do we need tunable knobs accessible by users? Do we need status
information? All this is handled in attributes of the database handles (be
careful when your DBD is running "behind" a L<DBD::Gofer> proxy).
How come the attributes into the DBD and how are they fetchable by the
user? Good question, but you should know because you've read the L<DBI>
documentation.
C<DBI::DBD::SqlEngine::db::FETCH> and C<DBI::DBD::SqlEngine::db::STORE>
taking care for you - all they need to know is which attribute names
are valid and mutable or immutable. Tell them by adding
C<init_valid_attributes> to your db class:
sub init_valid_attributes
{
my $dbh = $_[0];
$dbh->SUPER::init_valid_attributes ();
$dbh->{foo_valid_attrs} = {
foo_version => 1, # contains version of this driver
foo_valid_attrs => 1, # contains the valid attributes of foo drivers
foo_readonly_attrs => 1, # contains immutable attributes of foo drivers
foo_bar => 1, # contains the bar attribute
foo_baz => 1, # contains the baz attribute
foo_manager => 1, # contains the manager of the driver instance
foo_manager_type => 1, # contains the manager class of the driver instance
};
$dbh->{foo_readonly_attrs} = {
foo_version => 1, # ensure no-one modifies the driver version
foo_valid_attrs => 1, # do not permit one to add more valid attributes ...
foo_readonly_attrs => 1, # ... or make the immutable mutable
foo_manager => 1, # manager is set internally only
};
return $dbh;
}
Woooho - but now the user cannot assign new managers? This is intended,
overwrite C<STORE> to handle it!
sub STORE ($$$)
{
my ( $dbh, $attrib, $value ) = @_;
$dbh->SUPER::STORE( $attrib, $value );
# we're still alive, so no exception is thrown ...
# by DBI::DBD::SqlEngine::db::STORE
if ( $attrib eq "foo_manager_type" )
{
$dbh->{foo_manager} = $dbh->{foo_manager_type}->new();
# ... probably correct some states based on the new
# foo_manager_type - see DBD::Sys for an example
}
}
But ... my driver runs without a manager until someone first assignes
a C<foo_manager_type>. Well, no - there're two places where you can
initialize defaults:
sub init_default_attributes
{
my ($dbh, $phase) = @_;
$dbh->SUPER::init_default_attributes($phase);
if( 0 == $phase )
{
# init all attributes which have no knowledge about
# user settings from DSN or the attribute hash
$dbh->{foo_manager_type} = "DBD::Foo::Manager";
}
elsif( 1 == $phase )
{
# init phase with more knowledge from DSN or attribute
# hash
$dbh->{foo_manager} = $dbh->{foo_manager_type}->new();
}
return $dbh;
}
So far we can prevent the users to use our database driver as data
storage for anything and everything. We care only about the real important
stuff for peace on earth and alike attributes. But in fact, the driver
still can't do anything. It can do less than nothing - meanwhile it's
not a stupid storage area anymore.
=head2 User comfort
C<DBI::DBD::SqlEngine> since C<0.05> consolidates all persistent meta data
of a table into a single structure stored in C<< $dbh->{sql_meta} >>. While
DBI::DBD::SqlEngine provides only readonly access to this structure,
modifications are still allowed.
Primarily DBI::DBD::SqlEngine provides access via the setters
C<new_sql_engine_meta>, C<get_sql_engine_meta>, C<get_single_table_meta>,
C<set_single_table_meta>, C<set_sql_engine_meta> and C<clear_sql_engine_meta>.
Those methods are easily accessible by the users via the C<< $dbh->func () >>
interface provided by DBI. Well, many users don't feel comfortize when calling
# don't require extension for tables cars
$dbh->func ("cars", "f_ext", ".csv", "set_sql_engine_meta");
DBI::DBD::SqlEngine will inject a method into your driver to increase the
user comfort to allow:
( run in 1.175 second using v1.01-cache-2.11-cpan-39bf76dae61 )