DBD::Fi...velopers(3)
π NAME π
okay so this is DBD::File::Developers(3) from the User Contributed Perl Documentation, and it's literally the developer docs for DBD::File β yes bestie, the "how do I build my own DBD on top of this" page β¨
π¦ SYNOPSIS π¦
like here's the whole vibe of a driver built on DBD::File, no cap:
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 { ... }
π DESCRIPTION π
So this doc is the whole tutorial for how us DBD developers write DBD::File based DBI drivers π«Ά It's a supplement to DBI::DBD and DBI::DBD::SqlEngine::Developers β and fr fr, read those first, bestie, this one assumes you already did π
π CLASSES π
Every DBI driver has to bring a package-global driver method and three DBI related classes, periodt:
π
DBD::File::dr
This is the driver package β it's holding the methods that DBI calls indirectly through the DBI interface:
DBI->connect ('DBI:DBM:', undef, undef, {})
# invokes
package DBD::DBM::dr;
@DBD::DBM::dr::ISA = qw( DBD::File::dr );
sub connect ($$;$$$) {
...
}
Same energy applies for data_sources and disconnect_all β¨
Pure Perl DBI drivers derived from DBD::File usually do not need to override any of the methods you get through the DBD::XXX::dr package β but ngl, if you need extra initialization inside the connect method, you might have to π
π
DBD::File::db
This one holds the methods that get called through DBI database handles ($dbh), like:
$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 you need here. If you're writing a DBI driver based on DBD::File, you do need to override set_versions and init_valid_attributes πΈ
π
DBD::File::st
The methods for dealing with prepared statement handles live here, e.g.:
$sth->execute () or die $sth->errstr;
β DBD::File
Main character package energy. This is where the routines that initialize DBD::File based DBI drivers live. Mostly it's the DBD::File::driver method getting invoked β either straight 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;
}
You don't have to write your own driver method at all, as long as you don't need additional initialization (like installing more private driver methods). And you do not need to call setup_driver β DBD::File takes care of that for you, considerate queen π
β DBD::File::dr
The driver package here contains the methods DBI calls indirectly via the DBI interface (peep "DBI Class Methods" in DBI for that).
DBD::File based DBI drivers usually don't need to implement anything here β the basic initialization is enough, bestie:
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";
β DBD::File::db
This package defines the database methods, which get called via the DBI database handle $dbh.
Methods provided by DBD::File:
β¨ ping
Literally just returns the content of the Active attribute. Override it when your driver needs something more complicated happening here π
β¨ prepare
Prepares a new SQL statement to execute, and hands back a statement handle, $sth β an instance of the DBD:XXX::st. It is neither required nor recommended to override this method, so like, don't π
β¨ FETCH
Fetches an attribute of a DBI database object. Private handle attributes must have a prefix (this is mandatory, no skipping). If a requested attribute gets detected as a private attribute without a valid prefix, the driver prefix (written as $drv_prefix) is added.
The driver prefix gets extracted from the attribute name and verified against $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 $dbh->{ $drv_prefix . "readonly_attrs" } when it exists), a real copy of the attribute value is returned. So basically it's not possible to modify f_valid_attrs from outside of DBD::File::db or a derived class. locked down, as it should be π
β¨ STORE
Stores a database private attribute. Private handle attributes must have a prefix (again, mandatory!). If a requested attribute is detected as a private attribute without a valid prefix, the driver prefix (written as $drv_prefix) is added. If the database handle has an attribute ${drv_prefix}_valid_attrs β then for attribute names which are not listed in that hash, this method croaks π And if the database handle has an attribute ${drv_prefix}_readonly_attrs, only attributes which are not listed there can be stored (once they're initialized). Trying to overwrite such an immutable attribute forces this method to croak. so don't try it, it's giving forbidden π«
An example of a valid attributes list can be found in DBD::File::db::init_valid_attributes β¨
β¨ set_versions
Sets the attribute f_version with the version of DBD::File.
This method is called at the beginning of the connect () phase.
When you override this, do not forget to invoke the superior one. that's the rule, bestie π«Ά
β¨ init_valid_attributes
Called after the database handle is instantiated, as the very first attribute initialization.
DBD::File::db::init_valid_attributes initializes the attributes f_valid_attrs and f_readonly_attrs.
When overriding this one, don't forget to invoke the superior one β preferably before doing literally anything else. β¨
The compatibility table attribute access must be initialized here so DBD::File can 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";
β¨ init_default_attributes
Called after the database handle is instantiated, to initialize the default attributes.
DBD::File::db::init_default_attributes initializes the attributes f_dir, f_meta, f_meta_map, f_version.
When the derived implementor class provides the attribute to validate attributes (e.g. $dbh->{dbm_valid_attrs} = {...};) or the attribute containing the immutable attributes (e.g. $dbh->{dbm_readonly_attrs} = {...};), then the attributes drv_valid_attrs, drv_readonly_attrs, drv_version and drv_meta get added (when available) to the list of valid and immutable attributes β where drv_ is interpreted as the driver prefix π
If drv_meta is set, an attribute with the name in drv_meta is initialized, providing restricted read/write access to the meta data of the tables using DBD::File::TieTables in the first (table) level and DBD::File::TieMeta for the meta attribute level. DBD::File::TieTables uses DBD::DRV::Table::get_table_meta to initialize the second level tied hash on FETCH/STORE. The DBD::File::TieMeta class uses DBD::DRV::Table::get_table_meta_attr to FETCH attribute values and DBD::DRV::Table::set_table_meta_attr to STORE attribute values. And that's what allows it to map meta attributes for compatibility reasons π₯
β¨ get_single_table_meta / get_file_meta
Retrieve an attribute from a table's meta information. The method signature is get_file_meta ($dbh, $table, $attr). This method is called by the injected db handle method ${drv_prefix}get_meta. π«
Okay so while get_file_meta lets $table or $attr 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 . (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 $dbh->{$attrib}.
get_file_meta allows + and * as wildcards for table names, and $table being a regular expression matching against the table names (evaluated without the default table). The table name * is all currently known tables, including the default one. The table name + is 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.
β¨ set_single_table_meta / set_file_meta
Sets an attribute in a table's meta information. The method signature is set_file_meta ($dbh, $table, $attr, $value). This method is called by the injected db handle method ${drv_prefix}set_meta. π
okay so set_file_meta is the extrovert of the family β it lets $table be a whole list of tables and $attr be a hash carrying several attributes to set all at once. set_single_table_meta? she's the introvert π one table name, one attribute name, one value, that's it, that's the whole vibe.
the wildcard characters you're allowed to use for the table name are literally the same ones as for get_file_meta β¨ no secret extra rules, no surprises.
and the table meta info gets updated using the get_table_meta and set_table_meta_attr methods of the implementation's table class. that's the pipeline, bestie π«Ά
clear_file_metaβ nukes all the meta information that's been cached about a table. the signature is exactlyclear_file_meta ($dbh, $table). this one gets called by the injected db handle method${drv_prefix}clear_meta. it's giving spring cleaning π§Ήπ
π¦ DBD::File::st π¦
this package holds all the methods for dealing with prepared statement handles:
FETCH
grabs statement handle attributes. the supported ones β and for the full menu go peek at "Statement Handle Attributes" in DBI β are NAME, TYPE, PRECISION and NULLABLE, and that's whenever SQL::Statement is being used as the SQL execution engine and a statement got successfully prepared. if SQL::Statement has extra tea about a table, that tea gets served. otherwise you just get the same defaults as DBI::DBD::SqlEngine uses. no cap.
heads up though: this method usually needs extending in a derived implementation. go look at DBD::CSV or DBD::DBM for some example inspo π
π DBD::File::TableSource::FileSystem π
provides data sources and table information at the database driver level and the database handle level.
package DBD::File::TableSource::FileSystem;
sub data_sources ($;$) {
my ($class, $drh, $attrs) = @_;
...
}
sub avail_tables {
my ($class, $drh) = @_;
...
}
the data_sources method gets called when the user invokes any of these:
@ary = DBI->data_sources ($driver);
@ary = DBI->data_sources ($driver, \%attr);
@ary = $dbh->data_sources ();
@ary = $dbh->data_sources (\%attr);
and avail_tables gets called when the user invokes any of these:
@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");
oh and every single time there's a spot where a \%attr argument can be handed over, that \%attr object's sql_table_source attribute gets priority over the $dbh attribute and over the driver default π
observed. periodt.
π§ 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 the meta attributes that identify a file: f_fqfn, f_fqbn and f_fqln. then the table name gets set according to $respect_case and $meta->{sql_identifier_case} β that's SQL_IC_LOWER or SQL_IC_UPPER, pick your fighter β¨
package DBD::File::DataSource::Stream;
sub apply_encoding {
my ($self, $meta, $fn) = @_;
...
}
applies the encoding from the meta information β aka $meta->{f_encoding} β onto the file handle that got opened in open_data. cute πΈ
package DBD::File::DataSource::Stream;
sub open_data {
my ($self, $meta, $attrs, $flags) = @_;
...
}
opens β literally dup (2) β the file handle that was handed to you in $meta->{f_file} π«Ά
package DBD::File::DataSource::Stream;
sub can_flock { ... }
returns whether flock (2) is available or not (it does this so subclasses don't have to keep re-testing it over and over, no cap). π
π DBD::File::DataSource::File π
package DBD::File::DataSource::File;
sub complete_table_name ($$;$) {
my ($self, $meta, $table, $respect_case) = @_;
...
}
the complete_table_name method tries to map a filename onto the table name that goes with it. it gets called with a partially filled meta structure for the resulting table, and that structure contains at least these attributes: f_ext, f_dir, f_lockfile and sql_identifier_case. lowkey important.
if a file/table map can be found, then this method sets the f_fqfn, f_fqbn, f_fqln and table_name attributes over in the meta structure. and if a map can't be found? table name is undef. sorry bestie π
package DBD::File::DataSource::File;
sub open_data ($) {
my ($self, $meta, $attrs, $flags) = @_;
...
}
depending on which attributes are set in the table's meta data, these steps get performed. unless f_dontopen is set to a true value, f_fqfn must contain the full qualified file name for the table to work on (file2table makes sure of this, don't worry). the encoding in f_encoding gets applied if it's set, and then the file is opened. if f_fqln (full qualified lock name) is set, that file gets opened too. and depending on whatever value lives in f_lock, the appropriate lock gets set on the opened data file or on the lock file. iconic behaviour π
β DBD::File::Statement β
this one derives from DBI::SQL::Nano::Statement so it can provide the following method:
open_table
implements the open_table method that SQL::Statement and DBI::SQL::Nano require. all the actual work of opening the file(s) that belong to the table is handled and parametrized over in DBD::File::Table. and unless you're plotting to add something of your own to the implementation below, an empty DBD::XXX::Statement package fully satisfies DBD::File. like, genuinely nothing else needed π«Ά
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
π DBD::File::Table π
derives from DBI::SQL::Nano::Table, and it provides the physical file access for the table data that's chilling inside those files.
bootstrap_table_meta
initializes a table meta structure. you can safely override this in a derived class β just as long as the SUPER method gets called at the end of your overridden method, bestie, do not skip that step π
it copies these attributes from the database into the table meta data: f_dir, f_ext, f_encoding, f_lock, f_schema and f_lockfile, and it makes them sticky to the table.
this method should be called before you even attempt to map between file name and table name, so that the correct directory, extension etc. actually get used. order matters π
init_table_meta
initializes more attributes of the table meta data β usually the more expensive ones (think the ones that require class instantiations) β for when the file name and the table name managed to get mapped to each other β¨
get_table_meta
returns the table meta data. if there's none for the table you asked about, a fresh one gets initialized. if that fails, nothing comes back. on success you get the name of the table and the meta data structure handed to you. two for one, slay π
get_table_meta_attr
returns a single attribute out of the table meta data. if that attribute name shows up in %compat_map, the attribute name gets updated from there. iykyk.
set_table_meta_attr
sets a single attribute in the table meta data. same deal as above: if the attribute name appears in %compat_map, the attribute name gets updated from there too.
table_meta_attr_changed
called whenever an attribute of the meta data gets modified.
if the attribute that just changed requires a calculated attribute to be reset, then that calculated attribute gets reset (deleted straight out of the meta data structure) and the initialized flag gets removed along with it. the decision on whether to do that is made based on %register_reset_on_modify.
register_reset_on_modify
lets set_table_meta_attr reset meta attributes whenever special attributes get modified. for DBD::File, modifying any one of f_file, f_dir, f_ext or f_lockfile will reset f_fqfn. and DBD::DBM extends that list with dbm_type and dbm_mldbm so the value of dbm_tietype gets reset too.
so if your DBD has calculated values sitting around in the meta data area, then call register_reset_on_modify:
my %reset_on_modify = (xxx_foo => "xxx_bar");
__PACKAGE__->register_reset_on_modify (\%reset_on_modify);
register_compat_map
lets get_table_meta_attr and set_table_meta_attr update the attribute name to whichever one is the currently favored one:
# from DBD::DBM
my %compat_map = (dbm_ext => "f_ext");
__PACKAGE__->register_compat_map (\%compat_map);
open_file
called to open the table's data file.
depending on the attributes set in the table's meta data, these steps get performed. unless f_dontopen is set to a true value, f_fqfn must contain the full qualified file name for the table to work on (file2table ensures this). the encoding in f_encoding gets applied if set, and then the file gets opened. if f_fqln (full qualified lock name) is set, that file gets opened too. and depending on the value in f_lock, the appropriate lock gets set on the opened data file or on the lock file.
once all that's done, a derived class can always tack on more steps inside an overridden open_file method. go off β¨
new
instantiates the table. this happens in 3 steps:
- get the table meta data
- open the data file
- bless the table data structure using the inherited constructor
new
and honestly? it is not recommended to override the constructor of the table class. find a reasonable place to add your extensions among those methods above instead, bestie. trust π
drop
implements the abstract table method for the DROP command. it discards table meta data after all the files belonging to the table are closed and unlinked.
overriding this method might be reasonable in very rare cases. like, very rare. π«Ά
seek
implements the abstract table method that's used when the engine accesses the table. seek gets called every single time the engine uses its dumb algorithms for iterating over the table content. no shame, we all have our dumb iteration days π
truncate
implements the abstract table method used when those same dumb table algorithms for UPDATE or DELETE need to truncate the table storage after the last written row. bye bye extra rows π
you should go consult the documentation of SQL::Eval::Table (see SQL::Eval) to get more info about the abstract methods of the table's base class that you have to override, plus a description of the table meta information that the SQL engines expect. required reading, fr fr π
π AUTHOR π
the module DBD::File is currently maintained by
H.Merijn Brand < perl5 at tux.freedom.nl > and Jens Rehsack < rehsack at googlemail.com >
the original author is Jochen Wiedmann.
we love an origin story πΈ
π COPYRIGHT AND LICENSE π
okay bestie, legal era, but make it cute π
- Copyright (C) 2010-2026 by H.Merijn Brand & Jens Rehsack β that's a whole sixteen years of maintaining this thing, mother behavior honestly π
All rights reserved. yes, the whole "all rights reserved" moment, we're doing it, it's giving formal but we move π
πΈ so what can you actually do with it πΈ
You may freely distribute and/or modify this module under the terms of either:
- the GNU General Public License (GPL) π§
- the Artistic License π¨
...as specified in the Perl README file. that's it, that's the assignment, pick your fave, they're literally both on the menu π«Ά
ngl the "as specified in the Perl README file" part is doing the heavy lifting here β that's where the actual receipts live, so go read it, iykyk πβ¨
periodt. that's the whole license section. go forth and distribute responsibly bestie π
and that's a wrap on this whole page fr fr π¦ β it came to you via perl v5.42.3, dated 2026-10-19, filed under DBD::Fi...velopers(3). slay, stay iconic, and hydrate π πβ¨
π¦ where this page comes from
- fedora 43: perl-DBI 1.656-1.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- fedora 44: perl-DBI 1.656-1.fc44 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms