[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