DJabberd-RosterStorage-SQLite

 view release on metacpan or  search on metacpan

lib/DJabberd/RosterStorage/SQLite.pm  view on Meta::CPAN

        return;
    }

    $dbh->begin_work or
        $logger->logdie("Failed to begin work");

    my $fail = sub {
        my $reason = shift;
        die "Failing to addupdate: $reason";
        $dbh->rollback;
        $cb->error($reason);
        return;
    };

    my $exist_row = $dbh->selectrow_hashref("SELECT * FROM roster WHERE userid=? AND contactid=?",
                                            undef, $userid, $contactid);


    my %in_group;  # groupname -> 1

    if ($exist_row) {
        my @groups = $self->_groups_of_contactid($userid, $contactid);
        my %to_del; # groupname -> groupid
        foreach my $g (@groups) {
            $in_group{$g->[1]} = 1;
            $to_del  {$g->[1]} = $g->[0];
        }
        foreach my $gname ($ritem->groups) {
            delete $to_del{$gname};
        }
        if (my $in = join(",", values %to_del)) {
            $dbh->do("DELETE FROM groupitem WHERE groupid IN ($in) AND contactid=?",
                     undef, $contactid);
        }

        # by default, don't change subscription, unless we're being called
        # via set_roster_item.
        my $sub_value = "subscription";
        if ($_respect_subscription) {
            $sub_value = $ritem->subscription->as_bitmask;
            $logger->debug(" sub_value = $sub_value");
        } else {
            # but let's set our subscription in $ritem (since it comes to
            # us as 'none') because we have to pass it back with the real
            # value.
            $ritem->set_subscription(DJabberd::Subscription->from_bitmask($exist_row->{subscription}));
        }

        my $sql  = "UPDATE roster SET name=?, subscription=$sub_value WHERE userid=? AND contactid=?";
        my @args = ($ritem->name, $userid, $contactid);
        $dbh->do($sql, undef, @args);
    } else {
        $dbh->do("INSERT INTO roster (userid, contactid, name, subscription) ".
                 "VALUES (?,?,?,?)", undef,
                 $userid, $contactid, $ritem->name, $ritem->subscription->as_bitmask)
    }

    # add to groups
    foreach my $gname ($ritem->groups) {
        next if $in_group{$gname};  # already in this group, skip
        my $gid = $self->_groupid_alloc($userid, $gname);
        $dbh->do("INSERT OR IGNORE INTO groupitem (groupid, contactid) VALUES (?,?)",
                 undef, $gid, $contactid);
    }

    $dbh->commit
        or return $fail->();

    $cb->done($ritem);
}

# returns ([groupid, groupname], ...)
sub _groups_of_contactid {
    my ($self, $userid, $contactid) = @_;
    my @ret;
    my $sql = qq{
        SELECT rg.groupid, rg.name
            FROM   rostergroup rg, groupitem gi
            WHERE  rg.userid=? AND gi.groupid=rg.groupid AND gi.contactid=?
        };
    my $sth = $self->{dbh}->prepare($sql);
    $sth->execute($userid, $contactid);
    while (my ($gid, $name) = $sth->fetchrow_array) {
        push @ret, [$gid, $name];
    }
    return @ret;
}

sub delete_roster_item {
    my ($self, $cb, $jid, $ritem) = @_;
    $logger->debug("delete roster item!");

    my $dbh  = $self->{dbh};

    my $userid    = $self->_jidid_alloc($jid);
    my $contactid = $self->_jidid_alloc($ritem->jid);

    unless ($userid && $contactid) {
        $cb->error("no userid/contactid in delete");
        return;
    }

    $dbh->begin_work;

    my $fail = sub {
        $dbh->rollback;
        $cb->error;
        return;
    };

    my @groups = $self->_groups_of_contactid($userid, $contactid);

    if (my $in = join(",", map { $_->[0] } @groups)) {
        $dbh->do("DELETE FROM groupitem WHERE groupid IN ($in) AND contactid=?",
                 undef, $contactid);
    }

    $dbh->do("DELETE FROM roster WHERE userid=? AND contactid=?",
             undef, $userid, $contactid)
        or return $fail->();

    $dbh->commit or $fail->();

    $cb->done;
}

sub load_roster_item {
    my ($self, $jid, $contact_jid, $cb) = @_;

    my $dbh  = $self->{dbh};

    my $userid    = $self->_jidid_alloc($jid);
    my $contactid = $self->_jidid_alloc($contact_jid);
    unless ($userid && $contactid) {
        $cb->error("no userid/contactid in load");
        return;
    }

    my $row = $dbh->selectrow_hashref("SELECT name, subscription FROM roster ".
                                      "WHERE userid=? AND contactid=?",
                                      undef, $userid, $contactid);
    unless ($row) {
        $cb->set(undef);
        return;



( run in 1.585 second using v1.01-cache-2.11-cpan-5735350b133 )