Initial Commit
This commit is contained in:
665
database/perl/vendor/lib/DBD/File/Developers.pod
vendored
Normal file
665
database/perl/vendor/lib/DBD/File/Developers.pod
vendored
Normal file
@@ -0,0 +1,665 @@
|
||||
=head1 NAME
|
||||
|
||||
DBD::File::Developers - Developers documentation for DBD::File
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package DBD::myDriver;
|
||||
|
||||
use base qw( DBD::File );
|
||||
|
||||
sub driver
|
||||
{
|
||||
...
|
||||
my $drh = $proto->SUPER::driver ($attr);
|
||||
...
|
||||
return $drh->{class};
|
||||
}
|
||||
|
||||
sub CLONE { ... }
|
||||
|
||||
package DBD::myDriver::dr;
|
||||
|
||||
@ISA = qw( DBD::File::dr );
|
||||
|
||||
sub data_sources { ... }
|
||||
...
|
||||
|
||||
package DBD::myDriver::db;
|
||||
|
||||
@ISA = qw( DBD::File::db );
|
||||
|
||||
sub init_valid_attributes { ... }
|
||||
sub init_default_attributes { ... }
|
||||
sub set_versions { ... }
|
||||
sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... }
|
||||
sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... }
|
||||
sub get_myd_versions { ... }
|
||||
|
||||
package DBD::myDriver::st;
|
||||
|
||||
@ISA = qw( DBD::File::st );
|
||||
|
||||
sub FETCH { ... }
|
||||
sub STORE { ... }
|
||||
|
||||
package DBD::myDriver::Statement;
|
||||
|
||||
@ISA = qw( DBD::File::Statement );
|
||||
|
||||
package DBD::myDriver::Table;
|
||||
|
||||
@ISA = qw( DBD::File::Table );
|
||||
|
||||
my %reset_on_modify = (
|
||||
myd_abc => "myd_foo",
|
||||
myd_mno => "myd_bar",
|
||||
);
|
||||
__PACKAGE__->register_reset_on_modify (\%reset_on_modify);
|
||||
my %compat_map = (
|
||||
abc => 'foo_abc',
|
||||
xyz => 'foo_xyz',
|
||||
);
|
||||
__PACKAGE__->register_compat_map (\%compat_map);
|
||||
|
||||
sub bootstrap_table_meta { ... }
|
||||
sub init_table_meta { ... }
|
||||
sub table_meta_attr_changed { ... }
|
||||
sub open_data { ... }
|
||||
|
||||
sub fetch_row { ... }
|
||||
sub push_row { ... }
|
||||
sub push_names { ... }
|
||||
|
||||
# optimize the SQL engine by add one or more of
|
||||
sub update_current_row { ... }
|
||||
# or
|
||||
sub update_specific_row { ... }
|
||||
# or
|
||||
sub update_one_row { ... }
|
||||
# or
|
||||
sub insert_new_row { ... }
|
||||
# or
|
||||
sub delete_current_row { ... }
|
||||
# or
|
||||
sub delete_one_row { ... }
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This document describes how DBD developers can write DBD::File based DBI
|
||||
drivers. It supplements L<DBI::DBD> and L<DBI::DBD::SqlEngine::Developers>,
|
||||
which you should read first.
|
||||
|
||||
=head1 CLASSES
|
||||
|
||||
Each DBI driver must provide a package global C<driver> method and three
|
||||
DBI related classes:
|
||||
|
||||
=over 4
|
||||
|
||||
=item DBD::File::dr
|
||||
|
||||
Driver package, contains the methods DBI calls indirectly via DBI
|
||||
interface:
|
||||
|
||||
DBI->connect ('DBI:DBM:', undef, undef, {})
|
||||
|
||||
# invokes
|
||||
package DBD::DBM::dr;
|
||||
@DBD::DBM::dr::ISA = qw( DBD::File::dr );
|
||||
|
||||
sub connect ($$;$$$)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
Similar for C<< data_sources >> and C<< disconnect_all >>.
|
||||
|
||||
Pure Perl DBI drivers derived from DBD::File do not usually need to
|
||||
override any of the methods provided through the DBD::XXX::dr package
|
||||
however if you need additional initialization in the connect method
|
||||
you may need to.
|
||||
|
||||
=item DBD::File::db
|
||||
|
||||
Contains the methods which are called through DBI database handles
|
||||
(C<< $dbh >>). e.g.,
|
||||
|
||||
$sth = $dbh->prepare ("select * from foo");
|
||||
# returns the f_encoding setting for table foo
|
||||
$dbh->csv_get_meta ("foo", "f_encoding");
|
||||
|
||||
DBD::File provides the typical methods required here. Developers who
|
||||
write DBI drivers based on DBD::File need to override the methods C<<
|
||||
set_versions >> and C<< init_valid_attributes >>.
|
||||
|
||||
=item DBD::File::st
|
||||
|
||||
Contains the methods to deal with prepared statement handles. e.g.,
|
||||
|
||||
$sth->execute () or die $sth->errstr;
|
||||
|
||||
=back
|
||||
|
||||
=head2 DBD::File
|
||||
|
||||
This is the main package containing the routines to initialize
|
||||
DBD::File based DBI drivers. Primarily the C<< DBD::File::driver >>
|
||||
method is invoked, either directly from DBI when the driver is
|
||||
initialized or from the derived class.
|
||||
|
||||
package DBD::DBM;
|
||||
|
||||
use base qw( DBD::File );
|
||||
|
||||
sub driver
|
||||
{
|
||||
my ($class, $attr) = @_;
|
||||
...
|
||||
my $drh = $class->SUPER::driver ($attr);
|
||||
...
|
||||
return $drh;
|
||||
}
|
||||
|
||||
It is not necessary to implement your own driver method as long as
|
||||
additional initialization (e.g. installing more private driver
|
||||
methods) is not required. You do not need to call C<< setup_driver >>
|
||||
as DBD::File takes care of it.
|
||||
|
||||
=head2 DBD::File::dr
|
||||
|
||||
The driver package contains the methods DBI calls indirectly via the DBI
|
||||
interface (see L<DBI/DBI Class Methods>).
|
||||
|
||||
DBD::File based DBI drivers usually do not need to implement anything here,
|
||||
it is enough to do the basic initialization:
|
||||
|
||||
package DBD:XXX::dr;
|
||||
|
||||
@DBD::XXX::dr::ISA = qw (DBD::File::dr);
|
||||
$DBD::XXX::dr::imp_data_size = 0;
|
||||
$DBD::XXX::dr::data_sources_attr = undef;
|
||||
$DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann";
|
||||
|
||||
=head2 DBD::File::db
|
||||
|
||||
This package defines the database methods, which are called via the DBI
|
||||
database handle C<< $dbh >>.
|
||||
|
||||
Methods provided by DBD::File:
|
||||
|
||||
=over 4
|
||||
|
||||
=item ping
|
||||
|
||||
Simply returns the content of the C<< Active >> attribute. Override
|
||||
when your driver needs more complicated actions here.
|
||||
|
||||
=item prepare
|
||||
|
||||
Prepares a new SQL statement to execute. Returns a statement handle,
|
||||
C<< $sth >> - instance of the DBD:XXX::st. It is neither required nor
|
||||
recommended to override this method.
|
||||
|
||||
=item FETCH
|
||||
|
||||
Fetches an attribute of a DBI database object. Private handle attributes
|
||||
must have a prefix (this is mandatory). If a requested attribute is
|
||||
detected as a private attribute without a valid prefix, the driver prefix
|
||||
(written as C<$drv_prefix>) is added.
|
||||
|
||||
The driver prefix is extracted from the attribute name and verified against
|
||||
C<< $dbh->{$drv_prefix . "valid_attrs"} >> (when it exists). If the
|
||||
requested attribute value is not listed as a valid attribute, this method
|
||||
croaks. If the attribute is valid and readonly (listed in C<< $dbh->{
|
||||
$drv_prefix . "readonly_attrs" } >> when it exists), a real copy of the
|
||||
attribute value is returned. So it's not possible to modify
|
||||
C<f_valid_attrs> from outside of DBD::File::db or a derived class.
|
||||
|
||||
=item STORE
|
||||
|
||||
Stores a database private attribute. Private handle attributes must have a
|
||||
prefix (this is mandatory). If a requested attribute is detected as a private
|
||||
attribute without a valid prefix, the driver prefix (written as
|
||||
C<$drv_prefix>) is added. If the database handle has an attribute
|
||||
C<${drv_prefix}_valid_attrs> - for attribute names which are not listed in
|
||||
that hash, this method croaks. If the database handle has an attribute
|
||||
C<${drv_prefix}_readonly_attrs>, only attributes which are not listed there
|
||||
can be stored (once they are initialized). Trying to overwrite such an
|
||||
immutable attribute forces this method to croak.
|
||||
|
||||
An example of a valid attributes list can be found in
|
||||
C<< DBD::File::db::init_valid_attributes >>.
|
||||
|
||||
=item set_versions
|
||||
|
||||
This method sets the attribute C<f_version> with the version of DBD::File.
|
||||
|
||||
This method is called at the begin of the C<connect ()> phase.
|
||||
|
||||
When overriding this method, do not forget to invoke the superior one.
|
||||
|
||||
=item init_valid_attributes
|
||||
|
||||
This method is called after the database handle is instantiated as the
|
||||
first attribute initialization.
|
||||
|
||||
C<< DBD::File::db::init_valid_attributes >> initializes the attributes
|
||||
C<f_valid_attrs> and C<f_readonly_attrs>.
|
||||
|
||||
When overriding this method, do not forget to invoke the superior one,
|
||||
preferably before doing anything else. Compatibility table attribute
|
||||
access must be initialized here to allow DBD::File to instantiate the
|
||||
map tie:
|
||||
|
||||
# for DBD::CSV
|
||||
$dbh->{csv_meta} = "csv_tables";
|
||||
# for DBD::DBM
|
||||
$dbh->{dbm_meta} = "dbm_tables";
|
||||
# for DBD::AnyData
|
||||
$dbh->{ad_meta} = "ad_tables";
|
||||
|
||||
=item init_default_attributes
|
||||
|
||||
This method is called after the database handle is instantiated to
|
||||
initialize the default attributes.
|
||||
|
||||
C<< DBD::File::db::init_default_attributes >> initializes the attributes
|
||||
C<f_dir>, C<f_meta>, C<f_meta_map>, C<f_version>.
|
||||
|
||||
When the derived implementor class provides the attribute to validate
|
||||
attributes (e.g. C<< $dbh->{dbm_valid_attrs} = {...}; >>) or the attribute
|
||||
containing the immutable attributes (e.g.
|
||||
C<< $dbh->{dbm_readonly_attrs} = {...}; >>), the attributes
|
||||
C<drv_valid_attrs>, C<drv_readonly_attrs>, C<drv_version> and C<drv_meta>
|
||||
are added (when available) to the list of valid and immutable attributes
|
||||
(where C<drv_> is interpreted as the driver prefix).
|
||||
|
||||
If C<drv_meta> is set, an attribute with the name in C<drv_meta> is
|
||||
initialized providing restricted read/write access to the meta data of the
|
||||
tables using C<DBD::File::TieTables> in the first (table) level and
|
||||
C<DBD::File::TieMeta> for the meta attribute level. C<DBD::File::TieTables>
|
||||
uses C<DBD::DRV::Table::get_table_meta> to initialize the second level
|
||||
tied hash on FETCH/STORE. The C<DBD::File::TieMeta> class uses
|
||||
C<DBD::DRV::Table::get_table_meta_attr> to FETCH attribute values and
|
||||
C<DBD::DRV::Table::set_table_meta_attr> to STORE attribute values. This
|
||||
allows it to map meta attributes for compatibility reasons.
|
||||
|
||||
=item get_single_table_meta
|
||||
|
||||
=item get_file_meta
|
||||
|
||||
Retrieve an attribute from a table's meta information. The method
|
||||
signature is C<< get_file_meta ($dbh, $table, $attr) >>. This method
|
||||
is called by the injected db handle method C<< ${drv_prefix}get_meta >>.
|
||||
|
||||
While get_file_meta allows C<$table> or C<$attr> to be a list of tables or
|
||||
attributes to retrieve, get_single_table_meta allows only one table name
|
||||
and only one attribute name. A table name of C<'.'> (single dot) is
|
||||
interpreted as the default table and this will retrieve the appropriate
|
||||
attribute globally from the dbh. This has the same restrictions as
|
||||
C<< $dbh->{$attrib} >>.
|
||||
|
||||
get_file_meta allows C<'+'> and C<'*'> as wildcards for table names and
|
||||
C<$table> being a regular expression matching against the table names
|
||||
(evaluated without the default table). The table name C<'*'> is
|
||||
I<all currently known tables, including the default one>. The table
|
||||
name C<'+'> is I<all table names which conform to
|
||||
ANSI file name restrictions> (/^[_A-Za-z0-9]+$/).
|
||||
|
||||
The table meta information is retrieved using the get_table_meta and
|
||||
get_table_meta_attr methods of the table class of the implementation.
|
||||
|
||||
=item set_single_table_meta
|
||||
|
||||
=item set_file_meta
|
||||
|
||||
Sets an attribute in a table's meta information. The method signature is
|
||||
C<< set_file_meta ($dbh, $table, $attr, $value) >>. This method is called
|
||||
by the injected db handle method C<< ${drv_prefix}set_meta >>.
|
||||
|
||||
While set_file_meta allows C<$table> to be a list of tables and C<$attr>
|
||||
to be a hash of several attributes to set, set_single_table_meta allows
|
||||
only one table name and only one attribute name/value pair.
|
||||
|
||||
The wildcard characters for the table name are the same as for
|
||||
get_file_meta.
|
||||
|
||||
The table meta information is updated using the get_table_meta and
|
||||
set_table_meta_attr methods of the table class of the implementation.
|
||||
|
||||
=item clear_file_meta
|
||||
|
||||
Clears all meta information cached about a table. The method signature is
|
||||
C<< clear_file_meta ($dbh, $table) >>. This method is called
|
||||
by the injected db handle method C<< ${drv_prefix}clear_meta >>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 DBD::File::st
|
||||
|
||||
Contains the methods to deal with prepared statement handles:
|
||||
|
||||
=over 4
|
||||
|
||||
=item FETCH
|
||||
|
||||
Fetches statement handle attributes. Supported attributes (for full overview
|
||||
see L<DBI/Statement Handle Attributes>) are C<NAME>, C<TYPE>, C<PRECISION>
|
||||
and C<NULLABLE> in case that SQL::Statement is used as SQL execution engine
|
||||
and a statement is successful prepared. When SQL::Statement has additional
|
||||
information about a table, those information are returned. Otherwise, the
|
||||
same defaults as in L<DBI::DBD::SqlEngine> are used.
|
||||
|
||||
This method usually requires extending in a derived implementation.
|
||||
See L<DBD::CSV> or L<DBD::DBM> for some example.
|
||||
|
||||
=back
|
||||
|
||||
=head2 DBD::File::TableSource::FileSystem
|
||||
|
||||
Provides data sources and table information on database driver and database
|
||||
handle level.
|
||||
|
||||
package DBD::File::TableSource::FileSystem;
|
||||
|
||||
sub data_sources ($;$)
|
||||
{
|
||||
my ($class, $drh, $attrs) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
sub avail_tables
|
||||
{
|
||||
my ($class, $drh) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
The C<data_sources> method is called when the user invokes any of the
|
||||
following:
|
||||
|
||||
@ary = DBI->data_sources ($driver);
|
||||
@ary = DBI->data_sources ($driver, \%attr);
|
||||
|
||||
@ary = $dbh->data_sources ();
|
||||
@ary = $dbh->data_sources (\%attr);
|
||||
|
||||
The C<avail_tables> method is called when the user invokes any of the
|
||||
following:
|
||||
|
||||
@names = $dbh->tables ($catalog, $schema, $table, $type);
|
||||
|
||||
$sth = $dbh->table_info ($catalog, $schema, $table, $type);
|
||||
$sth = $dbh->table_info ($catalog, $schema, $table, $type, \%attr);
|
||||
|
||||
$dbh->func ("list_tables");
|
||||
|
||||
Every time where an C<\%attr> argument can be specified, this C<\%attr>
|
||||
object's C<sql_table_source> attribute is preferred over the C<$dbh>
|
||||
attribute or the driver default.
|
||||
|
||||
=head2 DBD::File::DataSource::Stream
|
||||
|
||||
package DBD::File::DataSource::Stream;
|
||||
|
||||
@DBD::File::DataSource::Stream::ISA = 'DBI::DBD::SqlEngine::DataSource';
|
||||
|
||||
sub complete_table_name
|
||||
{
|
||||
my ($self, $meta, $file, $respect_case) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
Clears all meta attributes identifying a file: C<f_fqfn>, C<f_fqbn> and
|
||||
C<f_fqln>. The table name is set according to C<$respect_case> and
|
||||
C<< $meta->{sql_identifier_case} >> (SQL_IC_LOWER, SQL_IC_UPPER).
|
||||
|
||||
package DBD::File::DataSource::Stream;
|
||||
|
||||
sub apply_encoding
|
||||
{
|
||||
my ($self, $meta, $fn) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
Applies the encoding from I<meta information> (C<< $meta->{f_encoding} >>)
|
||||
to the file handled opened in C<open_data>.
|
||||
|
||||
package DBD::File::DataSource::Stream;
|
||||
|
||||
sub open_data
|
||||
{
|
||||
my ($self, $meta, $attrs, $flags) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
Opens (C<dup (2)>) the file handle provided in C<< $meta->{f_file} >>.
|
||||
|
||||
package DBD::File::DataSource::Stream;
|
||||
|
||||
sub can_flock { ... }
|
||||
|
||||
Returns whether C<flock (2)> is available or not (avoids retesting in
|
||||
subclasses).
|
||||
|
||||
=head2 DBD::File::DataSource::File
|
||||
|
||||
package DBD::File::DataSource::File;
|
||||
|
||||
sub complete_table_name ($$;$)
|
||||
{
|
||||
my ($self, $meta, $table, $respect_case) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
The method C<complete_table_name> tries to map a filename to the associated
|
||||
table name. It is called with a partially filled meta structure for the
|
||||
resulting table containing at least the following attributes:
|
||||
C<< f_ext >>, C<< f_dir >>, C<< f_lockfile >> and C<< sql_identifier_case >>.
|
||||
|
||||
If a file/table map can be found then this method sets the C<< f_fqfn
|
||||
>>, C<< f_fqbn >>, C<< f_fqln >> and C<< table_name >> attributes in
|
||||
the meta structure. If a map cannot be found the table name will be
|
||||
undef.
|
||||
|
||||
package DBD::File::DataSource::File;
|
||||
|
||||
sub open_data ($)
|
||||
{
|
||||
my ($self, $meta, $attrs, $flags) = @_;
|
||||
...
|
||||
}
|
||||
|
||||
Depending on the attributes set in the table's meta data, the
|
||||
following steps are performed. Unless C<< f_dontopen >> is set to a
|
||||
true value, C<< f_fqfn >> must contain the full qualified file name
|
||||
for the table to work on (file2table ensures this). The encoding in
|
||||
C<< f_encoding >> is applied if set and the file is opened. If
|
||||
C<<f_fqln >> (full qualified lock name) is set, this file is opened,
|
||||
too. Depending on the value in C<< f_lock >>, the appropriate lock is
|
||||
set on the opened data file or lock file.
|
||||
|
||||
=head2 DBD::File::Statement
|
||||
|
||||
Derives from DBI::SQL::Nano::Statement to provide following method:
|
||||
|
||||
=over 4
|
||||
|
||||
=item open_table
|
||||
|
||||
Implements the open_table method required by L<SQL::Statement> and
|
||||
L<DBI::SQL::Nano>. All the work for opening the file(s) belonging to the
|
||||
table is handled and parametrized in DBD::File::Table. Unless you intend
|
||||
to add anything to the following implementation, an empty DBD::XXX::Statement
|
||||
package satisfies DBD::File.
|
||||
|
||||
sub open_table ($$$$$)
|
||||
{
|
||||
my ($self, $data, $table, $createMode, $lockMode) = @_;
|
||||
|
||||
my $class = ref $self;
|
||||
$class =~ s/::Statement/::Table/;
|
||||
|
||||
my $flags = {
|
||||
createMode => $createMode,
|
||||
lockMode => $lockMode,
|
||||
};
|
||||
$self->{command} eq "DROP" and $flags->{dropMode} = 1;
|
||||
|
||||
return $class->new ($data, { table => $table }, $flags);
|
||||
} # open_table
|
||||
|
||||
=back
|
||||
|
||||
=head2 DBD::File::Table
|
||||
|
||||
Derives from DBI::SQL::Nano::Table and provides physical file access for
|
||||
the table data which are stored in the files.
|
||||
|
||||
=over 4
|
||||
|
||||
=item bootstrap_table_meta
|
||||
|
||||
Initializes a table meta structure. Can be safely overridden in a
|
||||
derived class, as long as the C<< SUPER >> method is called at the end
|
||||
of the overridden method.
|
||||
|
||||
It copies the following attributes from the database into the table meta data
|
||||
C<< f_dir >>, C<< f_ext >>, C<< f_encoding >>, C<< f_lock >>, C<< f_schema >>
|
||||
and C<< f_lockfile >> and makes them sticky to the table.
|
||||
|
||||
This method should be called before you attempt to map between file
|
||||
name and table name to ensure the correct directory, extension etc. are
|
||||
used.
|
||||
|
||||
=item init_table_meta
|
||||
|
||||
Initializes more attributes of the table meta data - usually more
|
||||
expensive ones (e.g. those which require class instantiations) - when
|
||||
the file name and the table name could mapped.
|
||||
|
||||
=item get_table_meta
|
||||
|
||||
Returns the table meta data. If there are none for the required
|
||||
table, a new one is initialized. When it fails, nothing is
|
||||
returned. On success, the name of the table and the meta data
|
||||
structure is returned.
|
||||
|
||||
=item get_table_meta_attr
|
||||
|
||||
Returns a single attribute from the table meta data. If the attribute
|
||||
name appears in C<%compat_map>, the attribute name is updated from
|
||||
there.
|
||||
|
||||
=item set_table_meta_attr
|
||||
|
||||
Sets a single attribute in the table meta data. If the attribute
|
||||
name appears in C<%compat_map>, the attribute name is updated from
|
||||
there.
|
||||
|
||||
=item table_meta_attr_changed
|
||||
|
||||
Called when an attribute of the meta data is modified.
|
||||
|
||||
If the modified attribute requires to reset a calculated attribute, the
|
||||
calculated attribute is reset (deleted from meta data structure) and
|
||||
the I<initialized> flag is removed, too. The decision is made based on
|
||||
C<%register_reset_on_modify>.
|
||||
|
||||
=item register_reset_on_modify
|
||||
|
||||
Allows C<set_table_meta_attr> to reset meta attributes when special
|
||||
attributes are modified. For DBD::File, modifying one of C<f_file>, C<f_dir>,
|
||||
C<f_ext> or C<f_lockfile> will reset C<f_fqfn>. DBD::DBM extends the
|
||||
list for C<dbm_type> and C<dbm_mldbm> to reset the value of C<dbm_tietype>.
|
||||
|
||||
If your DBD has calculated values in the meta data area, then call
|
||||
C<register_reset_on_modify>:
|
||||
|
||||
my %reset_on_modify = (xxx_foo => "xxx_bar");
|
||||
__PACKAGE__->register_reset_on_modify (\%reset_on_modify);
|
||||
|
||||
=item register_compat_map
|
||||
|
||||
Allows C<get_table_meta_attr> and C<set_table_meta_attr> to update the
|
||||
attribute name to the current favored one:
|
||||
|
||||
# from DBD::DBM
|
||||
my %compat_map = (dbm_ext => "f_ext");
|
||||
__PACKAGE__->register_compat_map (\%compat_map);
|
||||
|
||||
=item open_file
|
||||
|
||||
Called to open the table's data file.
|
||||
|
||||
Depending on the attributes set in the table's meta data, the
|
||||
following steps are performed. Unless C<< f_dontopen >> is set to a
|
||||
true value, C<< f_fqfn >> must contain the full qualified file name
|
||||
for the table to work on (file2table ensures this). The encoding in
|
||||
C<< f_encoding >> is applied if set and the file is opened. If
|
||||
C<<f_fqln >> (full qualified lock name) is set, this file is opened,
|
||||
too. Depending on the value in C<< f_lock >>, the appropriate lock is
|
||||
set on the opened data file or lock file.
|
||||
|
||||
After this is done, a derived class might add more steps in an overridden
|
||||
C<< open_file >> method.
|
||||
|
||||
=item new
|
||||
|
||||
Instantiates the table. This is done in 3 steps:
|
||||
|
||||
1. get the table meta data
|
||||
2. open the data file
|
||||
3. bless the table data structure using inherited constructor new
|
||||
|
||||
It is not recommended to override the constructor of the table class.
|
||||
Find a reasonable place to add you extensions in one of the above four
|
||||
methods.
|
||||
|
||||
=item drop
|
||||
|
||||
Implements the abstract table method for the C<< DROP >>
|
||||
command. Discards table meta data after all files belonging to the
|
||||
table are closed and unlinked.
|
||||
|
||||
Overriding this method might be reasonable in very rare cases.
|
||||
|
||||
=item seek
|
||||
|
||||
Implements the abstract table method used when accessing the table from the
|
||||
engine. C<< seek >> is called every time the engine uses dumb algorithms
|
||||
for iterating over the table content.
|
||||
|
||||
=item truncate
|
||||
|
||||
Implements the abstract table method used when dumb table algorithms
|
||||
for C<< UPDATE >> or C<< DELETE >> need to truncate the table storage
|
||||
after the last written row.
|
||||
|
||||
=back
|
||||
|
||||
You should consult the documentation of C<< SQL::Eval::Table >> (see
|
||||
L<SQL::Eval>) to get more information about the abstract methods of the
|
||||
table's base class you have to override and a description of the table
|
||||
meta information expected by the SQL engines.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
The module DBD::File is currently maintained by
|
||||
|
||||
H.Merijn Brand < h.m.brand at xs4all.nl > and
|
||||
Jens Rehsack < rehsack at googlemail.com >
|
||||
|
||||
The original author is Jochen Wiedmann.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2010-2013 by H.Merijn Brand & Jens Rehsack
|
||||
|
||||
All rights reserved.
|
||||
|
||||
You may freely distribute and/or modify this module under the terms of
|
||||
either the GNU General Public License (GPL) or the Artistic License, as
|
||||
specified in the Perl README file.
|
||||
|
||||
=cut
|
||||
191
database/perl/vendor/lib/DBD/File/HowTo.pod
vendored
Normal file
191
database/perl/vendor/lib/DBD/File/HowTo.pod
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
=head1 NAME
|
||||
|
||||
DBD::File::HowTo - Guide to create DBD::File based driver
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
perldoc DBD::File::HowTo
|
||||
perldoc DBI
|
||||
perldoc DBI::DBD
|
||||
perldoc DBD::File::Developers
|
||||
perldoc DBI::DBD::SqlEngine::Developers
|
||||
perldoc DBI::DBD::SqlEngine
|
||||
perldoc SQL::Eval
|
||||
perldoc DBI::DBD::SqlEngine::HowTo
|
||||
perldoc SQL::Statement::Embed
|
||||
perldoc DBD::File
|
||||
perldoc DBD::File::HowTo
|
||||
perldoc DBD::File::Developers
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This document provides a step-by-step guide, how to create a new
|
||||
C<DBD::File> based DBD. It expects that you carefully read the L<DBI>
|
||||
documentation and that you're familiar with L<DBI::DBD> and had read and
|
||||
understood L<DBD::ExampleP>.
|
||||
|
||||
This document addresses experienced developers who are really sure that
|
||||
they need to invest time when writing a new DBI Driver. Writing a DBI
|
||||
Driver is neither a weekend project nor an easy job for hobby coders
|
||||
after work. Expect one or two man-month of time for the first start.
|
||||
|
||||
Those who are still reading, should be able to sing the rules of
|
||||
L<DBI::DBD/CREATING A NEW DRIVER>.
|
||||
|
||||
Of course, DBD::File is a DBI::DBD::SqlEngine and you surely read
|
||||
L<DBI::DBD::SqlEngine::HowTo> before continuing here.
|
||||
|
||||
=head1 CREATING DRIVER CLASSES
|
||||
|
||||
Do you have an entry in DBI's DBD registry? For this guide, a prefix of
|
||||
C<foo_> is assumed.
|
||||
|
||||
=head2 Sample Skeleton
|
||||
|
||||
package DBD::Foo;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use vars qw(@ISA $VERSION);
|
||||
use base qw(DBD::File);
|
||||
|
||||
use DBI ();
|
||||
|
||||
$VERSION = "0.001";
|
||||
|
||||
package DBD::Foo::dr;
|
||||
|
||||
use vars qw(@ISA $imp_data_size);
|
||||
|
||||
@ISA = qw(DBD::File::dr);
|
||||
$imp_data_size = 0;
|
||||
|
||||
package DBD::Foo::db;
|
||||
|
||||
use vars qw(@ISA $imp_data_size);
|
||||
|
||||
@ISA = qw(DBD::File::db);
|
||||
$imp_data_size = 0;
|
||||
|
||||
package DBD::Foo::st;
|
||||
|
||||
use vars qw(@ISA $imp_data_size);
|
||||
|
||||
@ISA = qw(DBD::File::st);
|
||||
$imp_data_size = 0;
|
||||
|
||||
package DBD::Foo::Statement;
|
||||
|
||||
use vars qw(@ISA);
|
||||
|
||||
@ISA = qw(DBD::File::Statement);
|
||||
|
||||
package DBD::Foo::Table;
|
||||
|
||||
use vars qw(@ISA);
|
||||
|
||||
@ISA = qw(DBD::File::Table);
|
||||
|
||||
1;
|
||||
|
||||
Tiny, eh? And all you have now is a DBD named foo which will be 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 Start over
|
||||
|
||||
Based on L<DBI::DBD::SqlEngine::HowTo>, we're now having a driver which
|
||||
could do basic things. Of course, it should now derive from DBD::File
|
||||
instead of DBI::DBD::SqlEngine, shouldn't it?
|
||||
|
||||
DBD::File extends DBI::DBD::SqlEngine to deal with any kind of files.
|
||||
In principle, the only extensions required are to the table class:
|
||||
|
||||
package DBD::Foo::Table;
|
||||
|
||||
sub bootstrap_table_meta
|
||||
{
|
||||
my ( $self, $dbh, $meta, $table ) = @_;
|
||||
|
||||
# initialize all $meta attributes which might be relevant for
|
||||
# file2table
|
||||
|
||||
return $self->SUPER::bootstrap_table_meta($dbh, $meta, $table);
|
||||
}
|
||||
|
||||
sub init_table_meta
|
||||
{
|
||||
my ( $self, $dbh, $meta, $table ) = @_;
|
||||
|
||||
# called after $meta contains the results from file2table
|
||||
# initialize all missing $meta attributes
|
||||
|
||||
$self->SUPER::init_table_meta( $dbh, $meta, $table );
|
||||
}
|
||||
|
||||
In case C<DBD::File::Table::open_file> doesn't open the files as the driver
|
||||
needs that, override it!
|
||||
|
||||
sub open_file
|
||||
{
|
||||
my ( $self, $meta, $attrs, $flags ) = @_;
|
||||
# ensure that $meta->{f_dontopen} is set
|
||||
$self->SUPER::open_file( $meta, $attrs, $flags );
|
||||
# now do what ever needs to be done
|
||||
}
|
||||
|
||||
Combined with the methods implemented using the L<SQL::Statement::Embed>
|
||||
guide, the table is full working and you could try a start over.
|
||||
|
||||
=head2 User comfort
|
||||
|
||||
C<DBD::File> since C<0.39> consolidates all persistent meta data of a table
|
||||
into a single structure stored in C<< $dbh->{f_meta} >>. With C<DBD::File>
|
||||
version C<0.41> and C<DBI::DBD::SqlEngine> version C<0.05>, this
|
||||
consolidation moves to L<DBI::DBD::SqlEngine>. It's still the
|
||||
C<< $dbh->{$drv_prefix . "_meta"} >> attribute which cares, so what you
|
||||
learned at this place before, is still valid.
|
||||
|
||||
sub init_valid_attributes
|
||||
{
|
||||
my $dbh = $_[0];
|
||||
|
||||
$dbh->SUPER::init_valid_attributes ();
|
||||
|
||||
$dbh->{foo_valid_attrs} = { ... };
|
||||
$dbh->{foo_readonly_attrs} = { ... };
|
||||
|
||||
$dbh->{foo_meta} = "foo_tables";
|
||||
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
See updates at L<DBI::DBD::SqlEngine::HowTo/User comfort>.
|
||||
|
||||
=head2 Testing
|
||||
|
||||
Now you should have your own DBD::File based driver. Was easy, wasn't it?
|
||||
But does it work well? Prove it by writing tests and remember to use
|
||||
dbd_edit_mm_attribs from L<DBI::DBD> to ensure testing even rare cases.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
This guide is written by Jens Rehsack. DBD::File is written by Jochen
|
||||
Wiedmann and Jeff Zucker.
|
||||
|
||||
The module DBD::File is currently maintained by
|
||||
|
||||
H.Merijn Brand < h.m.brand at xs4all.nl > and
|
||||
Jens Rehsack < rehsack at googlemail.com >
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack
|
||||
|
||||
All rights reserved.
|
||||
|
||||
You may freely distribute and/or modify this module under the terms of
|
||||
either the GNU General Public License (GPL) or the Artistic License, as
|
||||
specified in the Perl README file.
|
||||
|
||||
=cut
|
||||
176
database/perl/vendor/lib/DBD/File/Roadmap.pod
vendored
Normal file
176
database/perl/vendor/lib/DBD/File/Roadmap.pod
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
=head1 NAME
|
||||
|
||||
DBD::File::Roadmap - Planned Enhancements for DBD::File and pure Perl DBD's
|
||||
|
||||
Jens Rehsack - May 2010
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
This document gives a high level overview of the future of the DBD::File DBI
|
||||
driver and groundwork for pure Perl DBI drivers.
|
||||
|
||||
The planned enhancements cover features, testing, performance, reliability,
|
||||
extensibility and more.
|
||||
|
||||
=head1 CHANGES AND ENHANCEMENTS
|
||||
|
||||
=head2 Features
|
||||
|
||||
There are some features missing we would like to add, but there is
|
||||
no time plan:
|
||||
|
||||
=over 4
|
||||
|
||||
=item LOCK TABLE
|
||||
|
||||
The newly implemented internal common table meta storage area would allow
|
||||
us to implement LOCK TABLE support based on file system C<flock ()>
|
||||
support.
|
||||
|
||||
=item Transaction support
|
||||
|
||||
While DBD::AnyData recommends explicitly committing by importing and
|
||||
exporting tables, DBD::File might be enhanced in a future version to allow
|
||||
transparent transactions using the temporary tables of SQL::Statement as
|
||||
shadow (dirty) tables.
|
||||
|
||||
Transaction support will heavily rely on lock table support.
|
||||
|
||||
=item Data Dictionary Persistence
|
||||
|
||||
SQL::Statement provides dictionary information when a "CREATE TABLE ..."
|
||||
statement is executed. This dictionary is preserved for some statement
|
||||
handle attribute fetches (as C<NULLABLE> or C<PRECISION>).
|
||||
|
||||
It is planned to extend DBD::File to support data dictionaries to work
|
||||
on the tables in it. It is not planned to support one table in different
|
||||
dictionaries, but you can have several dictionaries in one directory.
|
||||
|
||||
=item SQL Engine selecting on connect
|
||||
|
||||
Currently the SQL engine selected is chosen during the loading of the module
|
||||
L<DBI::SQL::Nano>. Ideally end users should be able to select the engine
|
||||
used in C<< DBI->connect () >> with a special DBD::File attribute.
|
||||
|
||||
=back
|
||||
|
||||
Other points of view to the planned features (and more features for the
|
||||
SQL::Statement engine) are shown in L<SQL::Statement::Roadmap>.
|
||||
|
||||
=head2 Testing
|
||||
|
||||
DBD::File and the dependent DBD::DBM requires a lot more automated tests
|
||||
covering API stability and compatibility with optional modules
|
||||
like SQL::Statement.
|
||||
|
||||
=head2 Performance
|
||||
|
||||
Several arguments for support of features like indexes on columns
|
||||
and cursors are made for DBD::CSV (which is a DBD::File based driver,
|
||||
too). Similar arguments could be made for DBD::DBM, DBD::AnyData,
|
||||
DBD::RAM or DBD::PO etc.
|
||||
|
||||
To improve the performance of the underlying SQL engines, a clean
|
||||
re-implementation seems to be required. Currently both engines are
|
||||
prematurely optimized and therefore it is not trivial to provide
|
||||
further optimization without the risk of breaking existing features.
|
||||
|
||||
Join the DBI developers IRC channel at L<irc://irc.perl.org/dbi> to
|
||||
participate or post to the DBI Developers Mailing List.
|
||||
|
||||
=head2 Reliability
|
||||
|
||||
DBD::File currently lacks the following points:
|
||||
|
||||
=over 4
|
||||
|
||||
=item duplicate table names
|
||||
|
||||
It is currently possible to access a table quoted with a relative path
|
||||
(a) and additionally using an absolute path (b). If (a) and (b) are
|
||||
the same file that is not recognized (except for
|
||||
flock protection handled by the Operating System) and two independent
|
||||
tables are handled.
|
||||
|
||||
=item invalid table names
|
||||
|
||||
The current implementation does not prevent someone choosing a
|
||||
directory name as a physical file name for the table to open.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Extensibility
|
||||
|
||||
I (Jens Rehsack) have some (partially for example only) DBD's in mind:
|
||||
|
||||
=over 4
|
||||
|
||||
=item DBD::Sys
|
||||
|
||||
Derive DBD::Sys from a common code base shared with DBD::File which handles
|
||||
all the emulation DBI needs (as getinfo, SQL engine handling, ...)
|
||||
|
||||
=item DBD::Dir
|
||||
|
||||
Provide a DBD::File derived to work with fixed table definitions through the
|
||||
file system to demonstrate how DBI / Pure Perl DBDs could handle databases
|
||||
with hierarchical structures.
|
||||
|
||||
=item DBD::Join
|
||||
|
||||
Provide a DBI driver which is able to manage multiple connections to other
|
||||
Databases (as DBD::Multiplex), but allow them to point to different data
|
||||
sources and allow joins between the tables of them:
|
||||
|
||||
# Example
|
||||
# Let table 'lsof' being a table in DBD::Sys giving a list of open files using lsof utility
|
||||
# Let table 'dir' being a atable from DBD::Dir
|
||||
$sth = $dbh->prepare( "select * from dir,lsof where path='/documents' and dir.entry = lsof.filename" )
|
||||
$sth->execute(); # gives all open files in '/documents'
|
||||
...
|
||||
|
||||
# Let table 'filesys' a DBD::Sys table of known file systems on current host
|
||||
# Let table 'applications' a table of your Configuration Management Database
|
||||
# where current applications (relocatable, with mountpoints for filesystems)
|
||||
# are stored
|
||||
$sth = dbh->prepare( "select * from applications,filesys where " .
|
||||
"application.mountpoint = filesys.mountpoint and ".
|
||||
"filesys.mounted is true" );
|
||||
$sth->execute(); # gives all currently mounted applications on this host
|
||||
|
||||
=back
|
||||
|
||||
=head1 PRIORITIES
|
||||
|
||||
Our priorities are focused on current issues. Initially many new test
|
||||
cases for DBD::File and DBD::DBM should be added to the DBI test
|
||||
suite. After that some additional documentation on how to use the
|
||||
DBD::File API will be provided.
|
||||
|
||||
Any additional priorities will come later and can be modified by (paying)
|
||||
users.
|
||||
|
||||
=head1 RESOURCES AND CONTRIBUTIONS
|
||||
|
||||
See L<http://dbi.perl.org/contributing> for I<how you can help>.
|
||||
|
||||
If your company has benefited from DBI, please consider if
|
||||
it could make a donation to The Perl Foundation "DBI Development"
|
||||
fund at L<http://dbi.perl.org/donate> to secure future development.
|
||||
|
||||
Alternatively, if your company would benefit from a specific new
|
||||
DBI feature, please consider sponsoring it's development through
|
||||
the options listed in the section "Commercial Support from the Author"
|
||||
on L<http://dbi.perl.org/support/>.
|
||||
|
||||
Using such targeted financing allows you to contribute to DBI
|
||||
development and rapidly get something specific and directly valuable
|
||||
to you in return.
|
||||
|
||||
My company also offers annual support contracts for the DBI, which
|
||||
provide another way to support the DBI and get something specific
|
||||
in return. Contact me for details.
|
||||
|
||||
Thank you.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user