[jifty-devel] Jifty-DBI: patch proposal for a delete method for the
Collection class
Frederic BLANC
jifty-ml at blaf.org
Thu Oct 19 14:26:21 EDT 2006
Hello,
Here is a patch intended to add a delete method to the Jifty::DBI::Collection
class.
IMO, providing such a method will be more efficient than the answer given
to the "How do I delete all records from a table using a Model?" question
(http://jifty.org/view/HowDoI); by the way, the new answer would be:
my $system_user = CalLabCert::CurrentUser->superuser;
my $collection = CalLabCert::Model::DatFileCollection->new(
current_user => $system_user
);
$collection->unlimit();
# but we can use a limit(), as long it does not join tables.
$collection->delete();
Best regards,
Frederic BLANC
-------------- next part --------------
Index: Collection.pm
===================================================================
--- Collection.pm (revision 2030)
+++ Collection.pm (working copy)
@@ -1605,6 +1605,116 @@
);
}
+=head2 delete
+
+Delete this collection's records from the database. On failure return a
+Class::ReturnValue with the error. On success, return 1;
+
+This is an error to try to delete a joined Collection.
+
+This method has two hooks
+
+=over
+
+=item before_delete
+
+This method is called before the records deletion, if it exists. On
+failure it returns a L<Class::ReturnValue> with the error. On success
+it returns 1.
+
+If this method returns an error, it causes the records deletion to abort and
+return the return value from this hook.
+
+=item after_delete
+
+This method is called after deletion, with a reference to the return
+value from the delete operation.
+
+=back
+
+=cut
+
+sub delete {
+ my $self = shift;
+ if ( $self->can('before_delete') ) {
+ my $before_ret = $self->before_delete();
+ return $before_ret unless ($before_ret);
+ }
+ my $ret = $self->__delete;
+ $self->after_delete( \$ret ) if $self->can('after_delete');
+ return ($ret);
+}
+
+sub __delete {
+ my $self = shift;
+
+ # Collection must not be a joined Collection:
+ if ($self->_is_joined) {
+ my $ret = Class::ReturnValue->new();
+ my $message = "Records from joined Collection cannot be deleted";
+ $ret->as_array( 0, $message );
+ $ret->as_error(
+ errno => 6,
+ do_backtrace => 0,
+ message => $message
+ );
+ return $ret;
+ }
+
+ # Get the where clause.
+ my $where = $self->_bulk_where_clause;
+ unless (defined $where) {
+ # We have nothing to delete, but this is not an error:
+ return (1);
+ }
+
+ my $query_string = "DELETE FROM " . $self->table . $where;
+ my $return = $self->_handle->simple_query( $query_string );
+
+ $self->unlimit; # This collection cannot be used anymore: clear all.
+
+ if ( UNIVERSAL::isa( 'Class::ReturnValue', $return ) ) {
+ return ($return);
+ } else {
+ return (1);
+ }
+}
+
+# Constructs a where clause suitable for bulk operation (update, delete)
+# on the Collection object.
+# It return either the where clause (an empty string if the collection
+# represent the whole table content, or a string starting with 'WHERE') or
+# undef if the collection is empty and no data has to be deleted.
+sub _bulk_where_clause {
+ my $self = shift;
+
+ my $where = '';
+ if ($self->{'must_redo_search'}) {
+ # if the 'must_redo_search' flag is set, that means that no call
+ # to the add_record() method has occured yet, so we can use
+ # the restrictions to build the where clause if they exist:
+ $where = $self->_where_clause if $self->_is_limited;
+ } else {
+ # otherwise, we build the where clause using the items stored
+ # in the collection:
+ if (scalar @{$self->{items}} > 0) {
+ my $record_class = $self->record_class;
+ die "Jifty::DBI::Collection needs to be subclassed; " .
+ "override new_item\n"
+ unless $record_class;
+ my $pkey = $record_class->new()->primary_keys()->[0];
+
+ $where = ' WHERE ' . $pkey . ' IN(';
+ my @list = map { $_->id; } @{$self->{items}};
+ $where .= CORE::join(', ', @list);
+ $where .= ')';
+ } else { # We have nothing to delete.
+ return undef;
+ }
+ }
+ return $where;
+}
+
1;
__END__
More information about the jifty-devel
mailing list