2 # BioPerl module for Bio::DB::BioSQL::BaseDriver
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Hilmar Lapp <hlapp at gmx.net>
8 # Copyright Hilmar Lapp
10 # You may distribute this module under the same terms as perl itself
12 # (c) Hilmar Lapp, hlapp at gmx.net, 2002.
13 # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2002.
15 # You may distribute this module under the same terms as perl itself.
16 # Refer to the Perl Artistic License (see the license accompanying this
17 # software package, or see http://www.perl.com/language/misc/Artistic.html)
18 # for the terms under which you may use, modify, and redistribute this module.
20 # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
21 # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22 # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 # POD documentation - main docs before the code
28 Bio::DB::BioSQL::BaseDriver - DESCRIPTION of Object
32 This object contains the mapping of BioPerl classes to entities, as well as
33 the private methods that construct the INSERT, DELETE, UPDATE, and SELECT
40 User feedback is an integral part of the evolution of this and other
41 Bioperl modules. Send your comments and suggestions preferably to
42 the Bioperl mailing list. Your participation is much appreciated.
44 bioperl-l@bioperl.org - General discussion
45 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
49 Please direct usage questions or support issues to the mailing list:
51 I<bioperl-l@bioperl.org>
53 rather than to the module maintainer directly. Many experienced and
54 reponsive experts will be able look at the problem and quickly
55 address it. Please include a thorough description of the problem
56 with code and data examples if at all possible.
60 Report bugs to the Bioperl bug tracking system to help us keep track
61 of the bugs and their resolution. Bug reports can be submitted via
64 http://redmine.open-bio.org/projects/bioperl/
66 =head1 AUTHOR - Hilmar Lapp
68 Email hlapp at gmx.net
72 Additional contributors names and emails here
76 The rest of the documentation details each of the object methods.
77 Internal methods are usually preceded with a _
81 # Let the code begin...
83 package Bio
::DB
::BioSQL
::BaseDriver
;
87 # Object preamble - inherits from Bio::Root::Root
92 @ISA = qw(Bio::Root::Root Bio::DB::DBD);
95 # here goes our entire object-relational mapping
97 my %object_entity_map = (
98 "Bio::BioEntry" => "bioentry",
99 "Bio::PrimarySeqI" => "bioentry",
100 "Bio::DB::BioSQL::PrimarySeqAdaptor" => "bioentry",
101 "Bio::SeqI" => "bioentry",
102 "Bio::DB::BioSQL::SeqAdaptor" => "bioentry",
103 "Bio::IdentifiableI" => "bioentry",
104 "Bio::ClusterI" => "bioentry",
105 "Bio::DB::BioSQL::ClusterAdaptor" => "bioentry",
106 "Bio::DB::BioSQL::BiosequenceAdaptor" => "biosequence",
107 "Bio::SeqFeatureI" => "seqfeature",
108 "Bio::DB::BioSQL::SeqFeatureAdaptor" => "seqfeature",
109 "Bio::Species" => "taxon_name",
110 "Bio::DB::BioSQL::SpeciesAdaptor" => "taxon_name",
111 # TaxonNode is a hack: there is no such object, but we need it
112 # to distinguish between the node and the name table
113 "TaxonNode" => "taxon",
114 "Bio::LocationI" => "location",
115 "Bio::DB::BioSQL::LocationAdaptor" => "location",
116 "Bio::DB::BioSQL::BioNamespaceAdaptor" => "biodatabase",
117 "Bio::DB::Persistent::BioNamespace" => "biodatabase",
118 "Bio::Annotation::DBLink" => "dbxref",
119 "Bio::DB::BioSQL::DBLinkAdaptor" => "dbxref",
120 "Bio::Annotation::Comment" => "comment",
121 "Bio::DB::BioSQL::CommentAdaptor" => "comment",
122 "Bio::Annotation::Reference" => "reference",
123 "Bio::DB::BioSQL::ReferenceAdaptor" => "reference",
124 "Bio::Annotation::SimpleValue" => "term",
125 "Bio::DB::BioSQL::SimpleValueAdaptor" => "term",
126 "Bio::Annotation::OntologyTerm" => "term",
127 "Bio::Ontology::TermI" => "term",
128 "Bio::DB::BioSQL::TermAdaptor" => "term",
129 "Bio::Ontology::RelationshipI" => "term_relationship",
130 "Bio::DB::BioSQL::RelationshipAdaptor" => "term_relationship",
131 "Bio::Ontology::PathI" => "term_path",
132 "Bio::Ontology::Path" => "term_path",
133 "Bio::DB::BioSQL::PathAdaptor" => "term_path",
134 "Bio::Ontology::OntologyI" => "ontology",
135 "Bio::DB::BioSQL::OntologyAdaptor" => "ontology",
136 # TermSynonym is a hack - there is no such object
137 "TermSynonym" => "term_synonym",
139 my %association_entity_map = (
141 "dbxref" => "bioentry_dbxref",
142 "reference" => "bioentry_reference",
143 "term" => "bioentry_qualifier_value",
144 "bioentry" => { "term" => "bioentry_relationship", }
147 { "term" => { "term" => { "term" => "term_relationship", }, }, },
149 "term" => "seqfeature_qualifier_value",
150 "dbxref" => "seqfeature_dbxref",
151 "reference" => undef,
152 "seqfeature" => { "term" => "seqfeature_relationship", }
155 "bioentry" => "bioentry_dbxref",
156 "seqfeature" => "seqfeature_dbxref",
157 "term" => "dbxref_qualifier_value",
160 "bioentry" => "bioentry_reference",
161 "seqfeature" => undef,
164 "bioentry" => "bioentry_qualifier_value",
165 "dbxref" => "term_dbxref",
166 "seqfeature" => "seqfeature_qualifier_value",
168 "term" => { "ontology" => "term_relationship", },
169 "ontology" => { "term" => "term_relationship", }
171 "ontology" => { "term" => { "term" => "term_relationship", } }
174 my %slot_attribute_map = (
177 "namespace" => "name",
178 "authority" => "authority",
181 "classification" => undef,
182 "common_name" => undef,
183 "ncbi_taxid" => "ncbi_taxon_id",
184 "binomial" => "name",
186 # the following are hacks: there is no such thing on
187 # the object model. The sole reason they are here is so that you
188 # can set the physical column name of your taxon_name table.
189 # You MUST have these columns on the taxon node table, NOT the
191 "name_class" => "name_class",
192 "node_rank" => "node_rank",
193 "parent_taxon" => "parent_taxon_id",
196 "ncbi_taxid" => "ncbi_taxon_id",
197 # the following are hacks, see taxon_name mapping
198 "name_class" => "name_class",
199 "node_rank" => "node_rank",
200 "parent_taxon" => "parent_taxon_id",
203 "display_id" => "name",
204 "primary_id" => "identifier",
205 "accession_number" => "accession",
206 "desc" => "description",
207 "description" => "description",
208 "version" => "version",
209 "division" => "division",
210 "bionamespace" => "biodatabase_id",
211 "namespace" => "biodatabase_id",
212 # these are for context-sensitive FK name resolution
213 "object" => "object_bioentry_id",
214 "subject" => "subject_bioentry_id",
215 # parent and child are for backwards compatibility
216 "parent" => "object_bioentry_id",
217 "child" => "subject_bioentry_id",
219 "bioentry_relationship" => {
220 "object" => "object_bioentry_id",
221 "subject" => "subject_bioentry_id",
223 # parent and child are for backwards compatibility
224 "parent" => "object_bioentry_id",
225 "child" => "subject_bioentry_id",
228 "seq_version" => "version",
229 "length" => "length",
231 "alphabet" => "alphabet",
232 "primary_seq" => "bioentry_id",
233 # NOTE: change undef to the name of the CRC column to
234 # enable having CRC64s computed for sequences automatically,
235 # or set to undef to disable
239 "database" => "dbname",
240 "primary_id" => "accession",
241 "version" => "version",
242 "rank" => "=>{bioentry_dbxref,seqfeature_dbxref,term_dbxref}.rank",
244 "bioentry_dbxref" => { "rank" => "rank", },
245 "term_dbxref" => { "rank" => "rank", },
247 "authors" => "authors",
249 "location" => "location",
250 "medline" => "dbxref_id",
251 "pubmed" => "dbxref_id",
253 "start" => "=>bioentry_reference.start",
254 "end" => "=>bioentry_reference.end",
255 "rank" => "=>bioentry_reference.rank",
257 "bioentry_reference" => {
258 "start" => "start_pos",
263 "text" => "comment_text",
265 "Bio::DB::BioSQL::SeqFeatureAdaptor" => undef,
268 "identifier" => "identifier",
271 "is_obsolete" => "is_obsolete",
272 "definition" => "definition",
274 "=>{bioentry_qualifier_value,seqfeature_qualifier_value}.value",
276 "=>{bioentry_qualifier_value,seqfeature_qualifier_value}.rank",
277 "ontology" => "ontology_id",
278 # these are for context-sensitive FK name resolution
279 # term relationships:
280 "subject" => "subject_term_id",
281 "predicate" => "predicate_term_id",
282 "object" => "object_term_id",
284 "primary_tag" => "type_term_id",
285 "source_tag" => "source_term_id",
287 # term_synonym is more a hack - it doesn't correspond to an object
288 # in bioperl, but this does let you specify your column naming
290 "synonym" => "synonym",
293 "term_relationship" => {
294 "subject" => "subject_term_id",
295 "predicate" => "predicate_term_id",
296 "object" => "object_term_id",
297 "ontology" => "ontology_id",
300 "distance" => "distance",
301 "subject" => "subject_term_id",
302 "predicate" => "predicate_term_id",
303 "object" => "object_term_id",
304 "ontology" => "ontology_id",
308 "definition" => "definition",
310 "bioentry_qualifier_value" => {
315 "display_name" => "display_name",
317 "primary_tag" => "type_term_id",
318 "source_tag" => "source_term_id",
319 "entire_seq" => "bioentry_id",
321 # these are for context-sensitive FK name resolution
322 "object" => "object_seqfeature_id",
323 "subject" => "subject_seqfeature_id",
325 # parent and child are for backwards compatibility
326 "parent" => "parent_seqfeature_id",
327 "child" => "child_seqfeature_id",
329 "seqfeature_dbxref" => { "rank" => "rank", },
331 "start" => "start_pos",
333 "strand" => "strand",
336 "seqfeature_qualifier_value" => {
340 "seqfeature_relationship" => {
341 "object" => "object_seqfeature_id",
342 "subject" => "subject_seqfeature_id",
344 # parent and child are for backwards compatibility
345 "parent" => "parent_seqfeature_id",
346 "child" => "child_seqfeature_id",
349 my %dont_select_attrs = ( "biosequence.seq" => 1, );
354 Usage : my $obj = Bio::DB::BioSQL::BaseDriver->new();
355 Function: Builds a new Bio::DB::BioSQL::BaseDriver object
356 Returns : an instance of Bio::DB::BioSQL::BaseDriver
362 my ( $class, @args ) = @_;
364 my $self = $class->SUPER::new
(@args);
366 # copy the static mapping tables into our private hashs
367 # you may then change individual mappings in your derived adaptor driver
368 $self->objrel_map( \
%object_entity_map );
369 $self->slot_attribute_map( \
%slot_attribute_map );
370 $self->not_select_attrs( \
%dont_select_attrs );
371 $self->association_entity_map( \
%association_entity_map );
376 =head2 prepare_delete_sth
378 Title : prepare_delete_sth
380 Function: Creates a prepared statement with one placeholder variable
381 suitable to delete one row from the respective table the
384 The method may throw an exception, or the database handle
385 methods involved may throw an exception.
388 Returns : A DBI statement handle for a prepared statement with one placeholder
389 Args : The calling adaptor (basically, it needs to implement dbh()).
390 Optionally, additional arguments.
394 sub prepare_delete_sth
{
395 my ( $self, $adp ) = @_;
396 # default is a simple DELETE statement
398 # we need the table name and the name of the primary key
399 my $tbl = $self->table_name($adp);
400 my $pkname = $self->primary_key_name($tbl);
402 # straightforward SQL:
403 my $sql = "DELETE FROM $tbl WHERE $pkname = ?";
404 $adp->debug("preparing DELETE statement: $sql\n");
405 my $sth = $self->prepare( $adp->dbh(), $sql );
411 =head2 prepare_findbypk_sth
413 Title : prepare_findbypk_sth
415 Function: Prepares and returns a DBI statement handle with one placeholder for
416 the primary key. The statement is expected to return the primary key
417 as the first and then as many columns as
418 $adp->get_persistent_slots() returns, and in that order.
421 Returns : A DBI prepared statement handle with one placeholder
422 Args : The Bio::DB::BioSQL::BasePersistenceAdaptor derived object
423 (basically, it needs to implement dbh() and get_persistent_slots()).
424 A reference to an array of foreign key slots (class names).
428 sub prepare_findbypk_sth
{
429 my ( $self, $adp, $fkslots ) = @_;
431 # get table name and the primary key name
432 my $table = $self->table_name($adp);
433 my $pkname = $self->primary_key_name($table);
436 my @attrs = $self->_build_select_list( $adp, $fkslots );
438 # create the sql statement
440 = "SELECT " . join( ", ", @attrs ) . " FROM $table WHERE $pkname = ?";
441 $adp->debug("preparing PK select statement: $sql\n");
443 # prepare statement and return
444 return $self->prepare( $adp->dbh(), $sql );
447 =head2 prepare_findbyuk_sth
449 Title : prepare_findbyuk_sth
451 Function: Prepares and returns a DBI SELECT statement handle with as many
452 placeholders as necessary for the given unique key.
454 The statement is expected to return the primary key as the first and
455 then as many columns as $adp->get_persistent_slots() returns, and in
458 Returns : A DBI prepared statement handle with as many placeholders as
459 necessary for the given unique key
460 Args : The calling Bio::DB::BioSQL::BasePersistenceAdaptor derived object
461 (basically, it needs to implement dbh() and get_persistent_slots()).
462 A reference to a hash with the names of the object''s slots in the
463 unique key as keys and their values as values.
464 A reference to an array of foreign key objects or slots
465 (class names if slot).
469 sub prepare_findbyuk_sth
{
470 my ( $self, $adp, $ukval_h, $fkslots ) = @_;
472 # get the slots for which we need columns
473 my @slots = $adp->get_persistent_slots();
475 # get the slot/attribute map
476 my $table = $self->table_name($adp);
477 my $slotmap = $self->slot_attribute_map($table);
480 my @attrs = $self->_build_select_list( $adp, $fkslots );
482 # WHERE clause constraints
484 foreach ( keys %$ukval_h ) {
486 if ( exists( $slotmap->{$_} ) ) {
487 $col = $slotmap->{$_};
490 # try it as a foreign key
491 $col = $self->foreign_key_name($_);
493 push( @cattrs, $col || "NULL" );
495 $self->warn( "slot $_ is in unique key, but can't be mapped to "
496 . "an entity column: you won't find anything" );
500 # create the sql statement
503 . join( ", ", @attrs )
504 . " FROM $table WHERE "
505 . join( " AND ", map { "$_ = ?"; } @cattrs );
506 $adp->debug("preparing UK select statement: $sql\n");
508 # prepare statement and return
509 return $self->prepare( $adp->dbh(), $sql );
512 =head2 prepare_insert_association_sth
514 Title : prepare_insert_association_sth
516 Function: Prepares a DBI statement handle suitable for inserting the
517 association between the two entities that correspond to the
520 Returns : the DBI statement handle
521 Args : The calling adaptor.
522 Named parameters. Currently recognized are:
523 -objs a reference to an array of objects to be
524 associated with each other
525 -values a reference to a hash the keys of which are
526 column names and the values are values of
527 columns other than the ones for foreign keys to
528 the entities to be associated
529 -contexts optional; if given it denotes a reference
530 to an array of context keys (strings), which
531 allow the foreign key name to be determined
532 through the association map rather than through
533 foreign_key_name(). This may be necessary if
534 more than one object of the same type takes
535 part in the association. The array must be in
536 the same order as -objs, and have the same
537 number of elements. Put undef for objects
538 for which there are no multiple contexts.
540 Caveats: Make sure you *always* give the objects to be associated in the
545 sub prepare_insert_association_sth
{
546 my ( $self, $adp, @args ) = @_;
550 my ( $objs, $values, $contexts )
551 = $self->_rearrange( [qw(OBJS VALUES CONTEXTS)], @args );
553 # obtain column map for non-fk columns
554 my $table = $self->association_table_name($objs);
557 "no object-relational map for association between "
562 $_->isa("Bio::DB::PersistentObjectI")
570 my $columnmap = $self->slot_attribute_map($table);
575 # first, gather the foreign key names
577 while ( $i < @
$objs ) {
578 my $fktable = $self->table_name( $objs->[$i] );
581 "no object-relational map for class " . ref( $objs->[$i] ) );
583 if ( $contexts && $contexts->[$i] ) {
584 $attr = $columnmap->{ $contexts->[$i] };
586 $attr = $self->foreign_key_name( $objs->[$i] );
589 $self->throw( "unable to determine column for FK to class "
590 . ref( $objs->[$i] ) );
592 push( @attrs, $attr );
593 push( @plchldrs, "?" );
597 # now add the columns for values if any
599 foreach my $colkey ( keys %$values ) {
600 $self->throw("unmapped association column $colkey")
601 unless exists( $columnmap->{$colkey} );
602 $attr = $columnmap->{$colkey};
604 push( @attrs, $attr );
605 push( @plchldrs, "?" );
610 # construct SQL straightforwardly
612 = "INSERT INTO $table ("
613 . join( ", ", @attrs )
615 . join( ", ", @plchldrs ) . ")";
616 $adp->debug("preparing INSERT statement: $sql\n");
618 # prepare sth and return
619 return $self->prepare( $adp->dbh(), $sql );
622 =head2 prepare_delete_association_sth
624 Title : prepare_delete_association_sth
626 Function: Prepares a DBI statement handle suitable for deleting the
627 association between the two entities that correspond to the
630 Returns : the DBI statement handle
631 Args : The calling adaptor.
632 Named parameters. Currently recognized are:
633 -objs a reference to an array of objects the association
634 between which is to be deleted
635 -values a reference to a hash the keys of which are
636 column names and the values are values of
637 columns other than the ones for foreign keys to
638 the entities to be associated
639 -contexts optional; if given it denotes a reference
640 to an array of context keys (strings), which
641 allow the foreign key name to be determined
642 through the association map rather than through
643 foreign_key_name(). This may be necessary if
644 more than one object of the same type takes
645 part in the association. The array must be in
646 the same order as -objs, and have the same
647 number of elements. Put undef for objects
648 for which there are no multiple contexts.
650 Caveats: Make sure you *always* give the objects to be associated in the
655 sub prepare_delete_association_sth
{
656 my ( $self, $adp, @args ) = @_;
660 my ( $objs, $values, $contexts )
661 = $self->_rearrange( [qw(OBJS VALUES CONTEXTS)], @args );
663 # obtain column map for non-fk columns
664 my $table = $self->association_table_name($objs);
667 "no object-relational map for association between "
673 ?
( $_->isa("Bio::DB::PersistentObjectI")
682 my $columnmap = $self->slot_attribute_map($table);
686 # first, gather the foreign key names
688 while ( $i < @
$objs ) {
689 my $obj = $objs->[$i];
690 if ( ref($obj) && $obj->isa("Bio::DB::PersistentObjectI") ) {
691 my $fktable = $self->table_name($obj);
694 "no object-relational map for class " . ref($obj) );
696 if ( $contexts && $contexts->[$i] ) {
697 $attr = $columnmap->{ $contexts->[$i] };
699 $attr = $self->foreign_key_name($obj);
702 $self->throw( "unable to determine column for FK to class "
705 push( @attrs, $attr );
710 # now add the columns for values if any
712 foreach my $colkey ( keys %$values ) {
713 $self->throw("unmapped association column $colkey")
714 unless exists( $columnmap->{$colkey} );
715 $attr = $columnmap->{$colkey};
716 push( @attrs, $attr ) if $attr;
720 # construct SQL straightforwardly
721 my $sql = "DELETE FROM $table WHERE "
722 . join( " AND ", map { $_ . " = ?"; } @attrs );
723 $adp->debug("preparing DELETE ASSOC statement: $sql\n");
725 # prepare sth and return
726 return $self->prepare( $adp->dbh(), $sql );
729 =head2 prepare_delete_query_sth
731 Title : prepare_delete_query_sth
733 Function: Prepares a DBI statement handle suitable for deleting rows
734 from a table that match a number of attributes.
736 Returns : the DBI statement handle
737 Args : The calling adaptor.
739 Named parameters. Currently recognized are:
741 -fkobjs optional; a reference to an array of foreign
742 key objects by which to constrain; this is
743 complementary to -values
745 -contexts optional; if given it denotes a reference
746 to an array of context keys (strings), which
747 allow the foreign key name to be determined
748 through the association map rather than through
749 foreign_key_name(). This may be necessary if
750 an entity has more than one foreign key to the
751 same entity. The array must be in the same
752 order as -fkobjs, and have the same number of
753 elements. Put undef for objects for which there
754 are no multiple contexts.
756 -values optional; a reference to a hash the keys of
757 which are attribute names by which to constrain
762 sub prepare_delete_query_sth
{
763 my ( $self, $adp, @args ) = @_;
767 my ( $fkobjs, $values, $contexts )
768 = $self->_rearrange( [qw(FKOBJS VALUES CONTEXTS)], @args );
770 # obtain column map for attributes
771 my $table = $self->table_name($adp);
772 my $columnmap = $self->slot_attribute_map($table);
776 # add the query constraint columns for foreign key columns if any
777 if ( $fkobjs && @
$fkobjs ) {
778 foreach my $obj (@
$fkobjs) {
779 my $fktable = $self->table_name($obj);
781 $self->throw( "no object-relational map for class "
782 . ( ref($obj) ?
ref($obj) : $obj ) );
784 if ( $contexts && $contexts->[$i] ) {
785 $attr = $columnmap->{ $contexts->[$i] };
787 $attr = $self->foreign_key_name($obj);
790 $self->throw( "unable to determine column for FK to class "
791 . ( ref($obj) ?
ref($obj) : $obj ) );
793 push( @attrs, $attr );
797 # add any other query constraint columns
799 foreach my $colkey ( keys %$values ) {
800 $self->throw("unmapped association column $colkey")
801 unless exists( $columnmap->{$colkey} );
802 $attr = $columnmap->{$colkey};
803 push( @attrs, $attr ) if $attr;
807 # construct SQL straightforwardly
808 my $sql = "DELETE FROM $table";
810 $sql .= " WHERE " . join( " AND ", map { $_ . " = ?"; } @attrs );
812 $adp->debug("preparing DELETE QUERY statement: $sql\n");
814 # prepare sth and return
815 return $self->prepare( $adp->dbh(), $sql );
818 =head2 prepare_insert_sth
820 Title : prepare_insert_sth
822 Function: Prepares a DBI statement handles suitable for inserting
823 a row (as values of the slots of an object) into a table.
825 Returns : the DBI statement handle
826 Args : the calling adaptor (a Bio::DB::PersistenceAdaptorI object)
827 a reference to an array of object slot names
828 a reference to an array of foreign key objects (optional)
832 sub prepare_insert_sth
{
833 my ( $self, $adp, $slots, $fkobjs ) = @_;
835 # obtain table and object slot map
836 my $table = $self->table_name($adp);
837 my $slotmap = $self->slot_attribute_map($table);
838 $self->throw("no slot/attribute map for table $table") unless $slotmap;
840 # construct INSERT statement as straightforward SQL with placeholders
843 foreach my $slot (@
$slots) {
844 if ( ! exists( $slotmap->{$slot} ) ) {
845 $self->throw("no mapping for slot $slot in slot-attribute map");
848 # we don't add a column nor a placeholder for unmapped slots
849 if ( $slotmap->{$slot}
850 && ( substr( $slotmap->{$slot}, 0, 2 ) ne '=>' ) ) {
851 push( @attrs, $slotmap->{$slot} );
852 push( @plchlds, "?" );
859 my $fkattr = $self->foreign_key_name($_);
860 push( @attrs, $fkattr );
861 push( @plchlds, "?" );
867 . join( ", ", @attrs )
869 . join( ", ", @plchlds ) . ")";
870 $adp->debug("preparing INSERT statement: $sql\n");
871 return $self->prepare( $adp->dbh, $sql );
874 =head2 prepare_update_sth
876 Title : prepare_update_sth
878 Function: Prepares a DBI statement handle suitable for updating
879 a row in a table where the row is identified by its
882 Returns : the DBI statement handle
883 Args : the calling adaptor (a Bio::DB::PersistenceAdaptorI object)
884 a reference to an array of object slot names
885 a reference to an array of foreign key objects (optional)
889 sub prepare_update_sth
{
890 my ( $self, $adp, $slots, $fkobjs ) = @_;
892 # obtain the table name and corresponding slot map
893 my $table = $self->table_name($adp);
894 my $slotmap = $self->slot_attribute_map($table);
895 $self->throw("no slot/attribute map for table $table") unless $slotmap;
897 # construct UPDATE statement as straightforward SQL
899 foreach my $slot (@
$slots) {
900 if ( ! exists( $slotmap->{$slot} ) ) {
901 $self->throw("no mapping for slot $_ in slot-attribute map");
904 # we don't add a column nor a placeholder for unmapped slots
905 if ( $slotmap->{$slot}
906 && ( substr( $slotmap->{$slot}, 0, 2 ) ne '=>' ) ) {
907 push( @attrs, $slotmap->{$slot} );
914 my $fkattr = $self->foreign_key_name($_);
915 push( @attrs, $fkattr );
918 my $ifnull = $adp->dbcontext->dbi->ifnull_sqlfunc();
920 = "UPDATE $table SET "
921 . join( ", ", map { "$_ = $ifnull\(?,$_\)"; } @attrs )
923 . $self->primary_key_name($table) . " = ?";
924 $adp->debug("preparing UPDATE statement: $sql\n");
925 return $self->prepare( $adp->dbh(), $sql );
928 =head2 cascade_delete
930 Title : cascade_delete
932 Function: Removes all persistent objects dependent from the given persistent
933 object from the database (foreign key integrity).
935 This implementation assumes that the underlying schema and RDBMS
936 support cascading deletes, and hence does nothing other than
939 Returns : TRUE on success, and FALSE otherwise
940 Args : The DBContextI implementing object for the database.
941 The object for which the dependent rows shall be deleted.
942 Optionally, additional (named) arguments.
948 # our default assumption is that the RDBMS does support cascading deletes
954 Title : insert_object
958 Returns : The primary key of the newly inserted record.
959 Args : A Bio::DB::BioSQL::BasePersistenceAdaptor derived object
960 (basically, it needs to implement dbh(), sth($key, $sth),
961 dbcontext(), and get_persistent_slots()).
962 The object to be inserted.
963 A reference to an array of foreign key objects; if any of those
964 foreign key values is NULL (some foreign keys may be nullable),
965 then give the class name.
970 my ( $self, $adp, $obj, $fkobjs ) = @_;
972 # obtain the object's slots to be serialized
973 my @slots = $adp->get_persistent_slots($obj);
975 # get the INSERT statement
977 my $cache_key = 'INSERT ' . ref($obj) . ' ' . join( ';', @slots );
979 = $self->get_sth( $adp, $obj, $fkobjs, $cache_key, 'insert_object' );
981 # we need the slot map regardless of whether we need to construct the
982 # SQL or not, because we need to know which slots do not map to a column
983 # (indicated by them being mapped to undef)
984 my $table = $self->table_name($adp);
985 my $slotmap = $self->slot_attribute_map($table);
986 $self->throw("no slot/attribute map for table $table") unless $slotmap;
988 # we'll need the db handle in any case
989 my $dbh = $adp->dbh();
991 # if not cached, create SQL and prepare statement
993 $sth = $self->prepare_insert_sth( $adp, \
@slots, $fkobjs );
996 $adp->sth( $cache_key, $sth );
998 # and give interceptors a chance to do their work
999 $sth = $self->get_sth( $adp, $obj, $fkobjs, $cache_key,
1003 # the implementation here is a post-insert primary-key retrieval, so
1004 # just go ahead and bind the attributes, no a-priori pk retrieval
1005 my $slotvals = $adp->get_persistent_slot_values( $obj, $fkobjs );
1006 if ( @
$slotvals != @slots ) {
1007 $self->throw( "number of slots must equal the number of values "
1009 . join( ";", @slots )
1011 . join( "\";\"", @
$slotvals )
1014 my $i = 0; # slots and slot values index
1015 my $j = 1; # column index
1016 while ( $i < @slots ) {
1017 if ( $slotmap->{ $slots[$i] }
1018 && ( substr( $slotmap->{ $slots[$i] }, 0, 2 ) ne '=>' ) ) {
1019 if ( $adp->verbose > 0 ) {
1021 substr( ref($adp), rindex( ref($adp), "::" ) + 2 )
1023 . "binding column $j to \"",
1028 $self->bind_param( $sth, $j, $slotvals->[$i] );
1034 # bind foreign key values
1036 foreach my $o (@
$fkobjs) {
1038 # If it's an object, the value to bind is the primary key.
1039 # Otherwise bind undef.
1040 my $fk = $o && ref($o) ?
$o->primary_key() : undef;
1041 if ( $adp->verbose > 0 ) {
1043 substr( ref($adp), rindex( ref($adp), "::" ) + 2 )
1045 . "binding column $j to \"",
1049 ?
( ref($o) ?
ref( $o->obj() ) : $o )
1055 $self->bind_param( $sth, $j, $fk );
1061 my $rv = $sth->execute();
1064 # Note: $rv may be 0E0 (evaluates to TRUE as a string) to indicate
1065 # success, but zero rows affected, which means no row was inserted.
1066 # This may be (hopefully will be) due to an RDBMS having internally
1067 # (by means of triggers [Oracle, Pg] or rules [Pg]) encapsulated and
1068 # caught the already-exists condition.
1069 if ( $rv && ( $rv != 0 ) ) {
1071 # get the primary key that was just inserted
1072 $pk = $adp->dbcontext()->dbi()
1073 ->last_id_value( $dbh, $self->sequence_name($table) );
1074 } elsif ( ! $rv ) { # note this is *not* equivalent to $rv == 0 !
1075 # the statement failed
1076 $self->report_execute_failure(
1089 =head2 update_object
1091 Title : update_object
1095 Returns : The number of updated rows
1096 Args : A Bio::DB::BioSQL::BasePersistenceAdaptor derived object
1097 (basically, it needs to implement dbh(), sth($key, $sth),
1098 dbcontext(), and get_persistent_slots()).
1099 The object to be updated.
1100 A reference to an array of foreign key objects; if any of those
1101 foreign key values is NULL (some foreign keys may be nullable),
1102 then give the class name.
1107 my ( $self, $adp, $obj, $fkobjs ) = @_;
1109 # obtain the object's slots to be serialized
1110 my @slots = $adp->get_persistent_slots($obj);
1112 # get the UPDATE statement
1114 my $cache_key = 'UPDATE ' . ref($adp) . ' ' . join( ';', @slots );
1116 = $self->get_sth( $adp, $obj, $fkobjs, $cache_key, 'update_object' );
1118 # we need the slot map regardless of whether we need to construct the
1119 # SQL or not, because we need to know which slots do not map to a column
1120 # (indicated by them being mapped to undef)
1121 my $table = $self->table_name($adp);
1122 my $slotmap = $self->slot_attribute_map($table);
1123 $self->throw("no slot/attribute map for table $table") unless $slotmap;
1125 # if not cached, create SQL and prepare statement
1127 $sth = $self->prepare_update_sth( $adp, \
@slots, $fkobjs );
1130 $adp->sth( $cache_key, $sth );
1132 # and give interceptors a chance to do their work
1133 $sth = $self->get_sth( $adp, $obj, $fkobjs, $cache_key,
1137 # bind paramater values
1138 my $slotvals = $adp->get_persistent_slot_values( $obj, $fkobjs );
1139 if ( @
$slotvals != @slots ) {
1140 $self->throw("number of slots must equal the number of values");
1142 my $i = 0; # slots and slot values index
1143 my $j = 1; # column index
1144 while ( $i < @slots ) {
1145 if ( $slotmap->{ $slots[$i] }
1146 && ( substr( $slotmap->{ $slots[$i] }, 0, 2 ) ne '=>' ) ) {
1147 if ( $adp->verbose > 0 ) {
1150 "%s::update: binding column %d to \"%s\"(%s)\n",
1151 substr( ref($adp), rindex( ref($adp), "::" ) + 2 ),
1153 $slotvals->[$i] || '',
1158 $self->bind_param( $sth, $j, $slotvals->[$i] );
1164 # bind foreign key values
1166 foreach my $o (@
$fkobjs) {
1168 # If it's an object, the value to bind is the primary key. If it's
1169 # numeric, the value is the number. Otherwise bind undef.
1171 = ref($o) ?
$o->primary_key()
1172 : $o =~ /^\d+$/ ?
$o
1174 if ( $adp->verbose > 0 ) {
1176 substr( ref($adp), rindex( ref($adp), "::" ) + 2 )
1178 . "binding column $j to \"$fk\" (FK to "
1179 . $self->table_name($o)
1182 $self->bind_param( $sth, $j, $fk );
1187 # bind the primary key (which is in the WHERE clause and hence the last)
1188 $self->bind_param( $sth, $j, $obj->primary_key() );
1191 my $rv = $sth->execute();
1193 $self->report_execute_failure(
1210 Function: Retrieves the (prepared) statement handle to bind
1211 parameters for and to execute for the given operation.
1213 By default this will use the supplied key to retrieve the
1214 statement from the cache.
1216 This method is here to provide an opportunity for
1217 inheriting drivers to intercept the cached statement
1218 retrieval in order to on-the-fly redirect the statement
1219 execution to use a different statement than it would have
1222 This method may return undef if for instance there is no
1223 appropriate statement handle in the cache. Returning undef
1224 will trigger the calling method to construct a statement
1228 Returns : a prepared statement handle if one is exists for the query,
1230 Args : - the calling adaptor (a Bio::DB::BioSQL::BasePersistenceAdaptor
1232 - the object for the persistence operation
1233 - a reference to an array of foreign key objects; if any of
1234 those foreign key values is NULL then the class name
1235 - the key to the cache of the adaptor
1236 - the operation requesting a cache key (a scalar basically
1237 representing the name of the method)
1242 my ( $self, $adp, $obj, $fkobjs, $key, $op ) = @_;
1244 return $adp->sth($key);
1247 =head2 translate_query
1249 Title : translate_query
1251 Function: Translates the given query as represented by the query object
1252 from objects and class names and slot names to tables and column
1255 Returns : An object of the same class as the input query, but representing
1256 the translated query, and also with the SELECT fields properly set
1257 to facilitate object construction.
1258 Args : The calling adaptor.
1259 The query as a Bio::DB::Query::BioQuery or derived object.
1260 A reference to an array of foreign key objects.
1264 sub translate_query
{
1265 my ( $self, $adp, $query, $fkobjs ) = @_;
1267 # the query object can itself translate the datacollections and
1268 # slot names to column names (all it needs is a obj-rel mapper, which
1271 my $tquery = $query->translate_query( $self, \
%entitymap );
1273 # build the SELECT list
1274 my @selattrs = $self->_build_select_list( $adp, $fkobjs, \
%entitymap );
1276 # set as the SELECT elements of the query
1277 $tquery->selectelts( \
@selattrs );
1283 =head2 _build_select_list
1285 Title : _build_select_list
1287 Function: Builds and returns the select list for an object query. The list
1288 contains those columns, in the right order, that are necessary to
1289 populate the object.
1291 Returns : An array of strings (column names, not prefixed)
1292 Args : The calling persistence adaptor.
1293 A reference to an array of foreign key entities (objects, class
1294 names, or adaptors) the object must attach.
1295 A reference to a hash table mapping entity names to aliases (if
1296 omitted, aliases will not be used, and SELECT columns can only be
1301 sub _build_select_list
{
1302 my ( $self, $adp, $fkobjs, $entitymap ) = @_;
1304 # get the persistent slots
1305 my @slots = $adp->get_persistent_slots();
1307 # get the slot/attribute map
1308 my $table = $self->table_name($adp);
1309 my $slotmap = $self->slot_attribute_map();
1311 # get the map of columns excluded from SELECTs
1312 my $dont_select_attrs = $self->not_select_attrs();
1314 # default the entity-alias map if not provided
1315 if ( ! $entitymap ) {
1317 $entitymap->{$table} = [$table];
1320 # Alias for the table. We'll use the first one if the table is in the
1321 # FROM list with different aliases. Also note that the alias may come
1322 # with context, which we need to strip off.
1323 my ($alias) = split( /::/, $entitymap->{$table}->[0] );
1325 # get the primary key name
1326 my $pkname = $self->primary_key_name($table);
1329 my @attrs = ( $alias . "." . $pkname );
1331 $self->throw("no mapping for slot $_ in slot-attribute map")
1332 if ! exists( $slotmap->{$table}->{$_} );
1333 my $attr = $slotmap->{$table}->{$_};
1336 # is this attribute actually mapped to one or more other tables?
1337 if ( $attr && ( substr( $attr, 0, 2 ) eq '=>' ) ) {
1339 # yes, figure out to which attribute
1340 ( $tbl, $attr ) = split( /\./, substr( $attr, 2 ) );
1342 # is this mapped to multiple tables?
1343 if ( $tbl =~ /^\{(.*)\}$/ ) {
1345 # yes, figure out which one we have in the entity map
1346 foreach ( split( /[,\s]+/, $1 ) ) {
1348 # we just grab the first one
1349 if ( $entitymap->{$_} ) {
1355 $attr = $slotmap->{$tbl}->{$attr};
1358 || ( ! $entitymap->{$tbl} )
1359 || $dont_select_attrs->{ $tbl . "." . $attr } ) {
1360 push( @attrs, "NULL" );
1363 # same caveats as for the alias of the 'main' table
1364 my ($tblalias) = split( /::/, $entitymap->{$tbl}->[0] );
1365 push( @attrs, $tblalias . "." . $attr );
1369 # add foreign key attributes
1371 foreach (@
$fkobjs) {
1372 my $fkattr = $self->foreign_key_name($_);
1373 $self->throw("no mapping for foreign key to $_") unless $fkattr;
1374 push( @attrs, $alias . "." . $fkattr );
1384 Function: Obtain the name of the table in the relational schema
1385 corresponding to the given class name, object, or
1386 persistence adaptor.
1388 This implementation uses a object-relational hash map keyed
1389 by class to obtain the table name.
1392 Returns : the name of the table (a string), or undef if the table cannot be
1394 Args : The referenced object, class name, or the persistence
1400 my ( $self, $obj ) = @_;
1402 # if this is an array ref, the caller is asking for an association table
1403 if ( ref($obj) && ( ref($obj) eq "ARRAY" ) ) {
1404 return $self->association_table_name($obj);
1408 my $objrel_map = $self->objrel_map();
1409 my $tbl = $objrel_map->{ ref($obj) || $obj };
1412 # if not, and it's an object
1415 # if it's a persistent object, see whether the adaptor is mapped
1416 if ( $obj->isa("Bio::DB::PersistentObjectI") ) {
1417 $tbl = $objrel_map->{ ref( $obj->adaptor() ) };
1420 # if still no success, and it's not an adaptor, see which key it
1422 if ( ! ( $tbl || $obj->isa("Bio::DB::PersistenceAdaptorI") ) ) {
1423 my (@classes) = grep { $obj->isa($_); } keys %$objrel_map;
1426 = &_order_classes_by_inheritance
( $obj, @classes );
1427 $tbl = $objrel_map->{ $classes[0] };
1432 # it's not an object
1434 # look up by `last name' only, provided that maps uniquely
1435 my @class = grep { /(^|::)$obj$/; } keys %$objrel_map;
1436 $tbl = $objrel_map->{ $class[0] } if ( @class == 1 );
1439 # We may have a context appended. Strip the last component
1440 # and try to start over.
1442 # Well, would be nice if we could do that. However, currently
1443 # context is appended with a '::' separator, so we can't tell
1444 # right away whether we'd be stripping off context or the module
1445 # from the path. In the absence of a method to determine what is
1446 # context and what is not, we can't go this route.
1448 #@class = split(/::/, $obj);
1450 #$tbl = $self->table_name(join('::', @class)) if @class;
1457 sub _order_classes_by_inheritance
{
1458 my ( $obj, @classes ) = @_;
1459 my $class = ref($obj) || $obj;
1462 # recursion termination condition: an array of one or less elements
1464 return @classes if @classes <= 1;
1466 # if there is a class equal to the class by which to order, that one
1468 my ($i) = grep { $classes[$_] eq $class; } ( 0 .. @classes - 1 );
1469 if ( defined($i) ) {
1470 splice( @classes, $i, 1 );
1471 push( @sorted, $class );
1474 # try to sort the rest
1475 my $aryname = "${class}::ISA"; # this is a soft reference
1476 # hence, allow soft refs
1478 my @ancestors = @
$aryname;
1480 # and disallow again
1483 # now loop over all ancestors in the order they are in the list of
1484 # ancestors to sort the array
1485 foreach my $ancestor (@ancestors) {
1486 my @res = &_order_classes_by_inheritance
( $ancestor, @classes );
1489 # remove those that are sorted and add to the list of sorted
1490 push( @sorted, @res );
1491 for ( $i = 0; $i < @res; $i++ ) {
1492 @classes = grep { $_ ne $res[$i]; } @classes;
1495 last unless @classes > 0;
1500 =head2 association_table_name
1502 Title : association_table_name
1504 Function: Obtain the name of the table in the relational schema
1505 corresponding to the association of entities as represented
1506 by their corresponding class names, objects, or persistence
1509 This implementation will use table_name() and the map
1510 returned by association_entity_map().
1512 This method will throw an exception if the association is
1513 not mapped (not to be confused with the association being
1517 Returns : the name of the table (a string, or undef if the association is not
1518 supported by the schema)
1519 Args : A reference to an array of objects, class names, or persistence
1520 adaptors. The array may freely mix types.
1524 sub association_table_name
{
1525 my ( $self, $objs ) = @_;
1529 my $assocmap = $self->association_entity_map();
1531 # descend the tree as we encounter the objects
1532 foreach my $obj (@
$objs) {
1533 $tbl = $self->table_name($obj);
1534 $assocmap = defined($tbl) ?
$assocmap->{$tbl} : $tbl;
1535 last if ( ! ref($assocmap) );
1539 if ( ref($assocmap) ) {
1541 "association table for classes (" . join(
1545 ?
( $_->isa("Bio::DB::PersistentObjectI")
1555 # ended at a scalar (supposedly the table name)
1559 =head2 primary_key_name
1561 Title : primary_key_name
1563 Function: Obtain the name of the primary key attribute for the given table in
1564 the relational schema.
1566 This implementation just appends _id to the table name,
1567 which yields correct results for at least the MySQL version
1568 of the BioSQL schema. Override it for your own schema if
1572 Returns : The name of the primary key (a string)
1573 Args : The name of the table (a string)
1577 sub primary_key_name
{
1578 my ( $self, $table ) = @_;
1580 return $table . "_id";
1583 =head2 foreign_key_name
1585 Title : foreign_key_name
1587 Function: Obtain the foreign key name for referencing an object, as
1588 represented by object, class name, or the persistence adaptor.
1590 Returns : the name of the foreign key (a string)
1591 Args : The referenced object, class name, or the persistence adaptor for
1596 sub foreign_key_name
{
1597 my ( $self, $obj ) = @_;
1600 # if the object is a persistent object and has the foreign_key_slot value
1601 # set, we start from there
1603 && $obj->isa("Bio::DB::PersistentObjectI")
1604 && $obj->foreign_key_slot() ) {
1605 $obj = $obj->foreign_key_slot();
1608 # default is to get the primary key of the respective table
1609 $table = $self->table_name($obj);
1611 $fk = $self->_build_foreign_key_name($table);
1612 } elsif ( ! ref($obj) ) {
1614 # If the object or class name didn't map to a table it may be due
1615 # to a context being provided as a slot of a class. To try this,
1616 # remove the last component, see whether the rest maps to a table,
1617 # and if so, look up the slot in its attribute map.
1618 my @comps = split( /::/, $obj );
1619 my $slot = pop(@comps);
1620 $table = $self->table_name( join( "::", @comps ) );
1622 my $slotmap = $self->slot_attribute_map($table);
1624 $fk = $slotmap->{$slot};
1631 =head2 _build_foreign_key_name
1633 Title : _build_foreign_key_name
1635 Function: Build the column name for a foreign key to the given table.
1637 The default implementation here retrieves the primary key
1638 for the given table.
1640 This is called by foreign_key_name() once it has determined
1641 the table name. If a particular driver wants to build the
1642 foreign key name in a specific or generally different way
1643 than the default implementation here, this is the method to
1644 override (unless you also want to change the way the table
1645 is determined; in that case you would override
1646 foreign_key_name()).
1649 Returns : The name of the foreign key column as a string
1650 Args : The table name as a string
1654 sub _build_foreign_key_name
{
1658 return $self->primary_key_name($table);
1661 =head2 sequence_name
1663 Title : sequence_name
1665 Function: Returns the name of the primary key generator (SQL sequence)
1666 for the given table.
1668 The value returned is passed as the second argument to the
1669 L<Bio::DB:DBI>::last_id_value as implemented by the
1670 driver. Because the parameter is not required irregardless
1671 of driver, it is perfectly legal for this method to return
1672 undef. If the L<Bio::DB::DBI> driver does need this
1673 parameter, this method should be overridden by the matching
1676 The default we assume here is we dont need this value.
1679 Returns : the name of the sequence (a string)
1680 Args : The name of the table.
1692 Function: Get/set the object-relational map from .
1694 Returns : A reference to a hash map where object interfaces are the keys
1695 Args : Optional, on set a reference to the respective hash map
1700 my ( $self, $value ) = @_;
1703 $self->{'_objrel_map'} = $value;
1705 return $self->{'_objrel_map'};
1708 =head2 slot_attribute_map
1710 Title : slot_attribute_map
1712 Function: Get/set the mapping for each entity from object slot names
1716 Returns : A reference to a hash map with entity names being the keys,
1717 if no key (entity name, object, or adaptor) was
1718 provided. Otherwise, a hash reference with the slot names
1719 being keys to their corresponding column names.
1721 Args : Optionally, the object, adaptor, or entity for which to
1724 Optionally, on set a reference to a hash map satisfying the
1725 features of the returned value.
1729 sub slot_attribute_map
{
1730 my ( $self, $tablekey, $map ) = @_;
1734 # this might actually be the overall map on set
1735 if ( ( ref($tablekey) eq "HASH" ) && ( ! $map ) ) {
1738 $self->{'_slot_attr_map'} = $map;
1741 # make sure the hash exists before we query it with a key
1742 if ( ! exists( $self->{'_slot_attr_map'} ) ) {
1743 $self->{'_slot_attr_map'} = {};
1746 # see whether we need to transform it into an entity name
1747 if ( ref($tablekey) ) {
1748 $tablekey = $self->table_name($tablekey);
1751 # set/get the individual map
1753 $self->{'_slot_attr_map'}->{$tablekey} = $map;
1755 $map = $self->{'_slot_attr_map'}->{$tablekey};
1760 # return the overall map
1761 $map = $self->{'_slot_attr_map'};
1766 =head2 not_select_attrs
1768 Title : not_select_attrs
1769 Usage : $obj->not_select_attrs($newval)
1770 Function: Get/set a map of all columns that should not be included in
1773 Returns : value of not_select_attrs (a reference to a hash map)
1774 Args : new value (a reference to a hash map, optional)
1778 sub not_select_attrs
{
1779 my ( $self, $value ) = @_;
1780 if ( defined $value ) {
1781 $self->{'not_select_attrs'} = $value;
1783 return $self->{'not_select_attrs'};
1786 =head2 association_entity_map
1788 Title : association_entity_map
1789 Usage : $obj->association_entity_map($newval)
1790 Function: Get/set the association entity map. The map is an anonymous
1791 hash with entities that participate in associations being
1792 keys. The values are hash refs themselves, with the other
1793 participating entity being the key, and the value being
1794 either the name of the respective association entity, or
1795 another hash ref with the same structure if more entities
1796 participate in the association.
1798 The hash map must be commutative. I.e., the association
1799 entity must be locatable irregardless with which of the
1800 participating entities one starts.
1803 Returns : value of association_entity_map (a hash ref of hash refs)
1804 Args : new value (a hash ref of hash refs, optional)
1808 sub association_entity_map
{
1809 my ( $self, $value ) = @_;
1810 if ( defined $value ) {
1811 $self->{'association_entity_map'} = $value;
1813 return $self->{'association_entity_map'};
1816 =head1 DBI calls for possible interception
1818 These will usually delegate straightforward DBI calls on the supplied
1819 handle, but can also be used by an inheriting adaptor driver to
1820 intercept the call and add additional parameters, for example a hash
1821 reference with named parameters.
1829 Function: Commits the current transaction, if the underlying driver
1830 supports transactions.
1833 Args : The database connection handle for which to commit.
1838 my ( $self, $dbh ) = @_;
1839 return $dbh->commit();
1846 Function: Triggers a rollback of the current transaction, if the
1847 underlying driver supports transactions.
1850 Args : The database connection for which to rollback.
1855 my ( $self, $dbh ) = @_;
1856 return $dbh->rollback();
1863 Function: Binds a parameter value to a prepared statement.
1865 The reason this method is here is to give RDBMS-specific
1866 drivers a chance to intercept the parameter binding and
1867 perform additional actions, or add additional parameters to
1868 the call, like data type. Certain drivers need to be helped
1869 for certain types, for example DBD::Oracle for LOB
1873 Returns : the return value of the DBI::bind_param() call
1874 Args : the DBI statement handle to bind to
1875 the index of the column
1877 additional arguments to be passed to the sth->bind_param call
1882 my ( $self, $sth, $i, $val, @bindargs ) = @_;
1884 return $sth->bind_param( $i, $val, @bindargs );
1891 Function: Prepares a SQL statement and returns a statement handle.
1893 The reason this method is here is the same as for
1897 Returns : the return value of the DBI::prepare() call
1898 Args : the DBI database handle for preparing the statement
1899 the SQL statement to prepare (a scalar)
1900 additional arguments to be passed to the dbh->prepare call
1905 my ( $self, $dbh, $sql, @args ) = @_;
1907 return $dbh->prepare( $sql, @args );
1910 =head1 Utility methods
1914 =head2 report_execute_failure
1916 Title : report_execute_failure
1918 Function: Report the failure to execute a SQL statement.
1920 The reporting by default uses warn() but may be requested
1925 Args : Named paramaters. Currently recognized are
1926 -sth the statement handle whose execution failed
1927 -adaptor the calling adaptor
1928 (a Bio::DB::PersistenceAdaptorI object)
1929 -op the type of operation that failed ('insert',
1931 -vals a reference to an array of values that were bound
1932 -fkobjs a reference to an array of foreign key objects
1933 that were bound (optional)
1934 -report_func the name of the method to call for reporting
1935 the message (optional, default is 'warn')
1939 sub report_execute_failure
{
1941 my ( $sth, $adp, $op, $slotvals, $fkobjs, $reportfunc )
1942 = $self->_rearrange(
1954 $reportfunc = "warn" unless $reportfunc;
1957 . " (driver) failed, values were (\""
1958 . join( "\",\"", @
$slotvals ) . "\")";
1962 map { $_ && ref($_) ?
$_->primary_key() : "<NULL>"; } @
$fkobjs )
1965 $self->$reportfunc( "$msg\n" . $sth->errstr );