diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2012-06-06 16:41:29 +0000 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-09-26 13:46:50 +0000 |
commit | 7c48e67cf07ee41bfde7139a62bb232bd23a4a48 (patch) | |
tree | 6d7686b5075bd5cba253dabf2e6c302acb3a147c /lib/DBD/File | |
download | perl-dbi-tarball-7c48e67cf07ee41bfde7139a62bb232bd23a4a48.tar.gz |
Diffstat (limited to 'lib/DBD/File')
-rw-r--r-- | lib/DBD/File/Developers.pod | 556 | ||||
-rw-r--r-- | lib/DBD/File/HowTo.pod | 270 | ||||
-rw-r--r-- | lib/DBD/File/Roadmap.pod | 176 |
3 files changed, 1002 insertions, 0 deletions
diff --git a/lib/DBD/File/Developers.pod b/lib/DBD/File/Developers.pod new file mode 100644 index 0000000..a9bef85 --- /dev/null +++ b/lib/DBD/File/Developers.pod @@ -0,0 +1,556 @@ +=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_file { ... } + + 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::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 parameterized 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 file2table + +This method 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. + +=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 >>, +C<< f_lockfile >> and C<< sql_identifier_case >> 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 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 diff --git a/lib/DBD/File/HowTo.pod b/lib/DBD/File/HowTo.pod new file mode 100644 index 0000000..3d45257 --- /dev/null +++ b/lib/DBD/File/HowTo.pod @@ -0,0 +1,270 @@ +=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 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 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} >>. While DBD::File +provides only readonly access to this structure, modifications are still +allowed. + +Primarily DBD::File provides access via setters C<get_file_meta>, +C<set_file_meta> and C<clear_file_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_file_meta"); + +DBD::File will inject a method into your driver to increase the user +comfort to allow: + + # don't require extension for tables cars + $dbh->foo_set_meta ("cars", "f_ext", ".csv"); + +Better, but here and there users likes to do: + + # don't require extension for tables cars + $dbh->{foo_tables}->{cars}->{f_ext} = ".csv"; + +This interface is provided when derived DBD's define following in +C<init_valid_attributes> (please compare carefully with the example in +DBI::DBD::SqlEngine::HowTo): + + 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 + foo_meta => 1, # contains the public interface to modify table meta attributes + }; + $dbh->{foo_readonly_attrs} = { + foo_version => 1, # ensure no-one modifies the driver version + foo_valid_attrs => 1, # do not permit to add more valid attributes ... + foo_readonly_attrs => 1, # ... or make the immutable mutable + foo_manager => 1, # manager is set internally only + foo_meta => 1, # ensure public interface to modify table meta attributes are immutable + }; + + $dbh->{foo_meta} = "foo_tables"; + + return $dbh; + } + +This provides a tied hash in C<< $dbh->{foo_tables} >> and a tied hash for +each table's meta data in C<< $dbh->{foo_tables}->{$table_name} >>. +Modifications on the table meta attributes are done using the table +methods: + + sub get_table_meta_attr { ... } + sub set_table_meta_attr { ... } + +Both methods can adjust the attribute name for compatibility reasons, e.g. +when former versions of the DBD allowed different names to be used for the +same flag: + + my %compat_map = ( + abc => 'foo_abc', + xyz => 'foo_xyz', + ); + __PACKAGE__->register_compat_map( \%compat_map ); + +If any user modification on a meta attribute needs reinitialization of +the meta structure (in case of C<DBD::File> these are the attributes +C<f_file>, C<f_dir>, C<f_ext> and C<f_lockfile>), inform DBD::File by +doing + + my %reset_on_modify = ( + foo_xyz => "foo_bar", + foo_abc => "foo_bar", + ); + __PACKAGE__->register_reset_on_modify( \%reset_on_modify ); + +The next access to the table meta data will force DBD::File to re-do the +entire meta initialization process. + +Any further action which needs to be taken can handled in +C<table_meta_attr_changed>: + + sub table_meta_attr_changed + { + my ($class, $meta, $attrib, $value) = @_; + ... + $class->SUPER::table_meta_attr_changed ($meta, $attrib, $value); + } + +This is done before the new value is set in C<$meta>, so the attribute +changed handler can act depending on the old value. + +=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 diff --git a/lib/DBD/File/Roadmap.pod b/lib/DBD/File/Roadmap.pod new file mode 100644 index 0000000..804d759 --- /dev/null +++ b/lib/DBD/File/Roadmap.pod @@ -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 +reimplementation 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 focussed 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 |