App-CamelPKI

 view release on metacpan or  search on metacpan

lib/App/CamelPKI/CADB.pm  view on Meta::CPAN


=cut

sub debug_statements : Restricted {
    my ($class, $debugsub) = @_;
    our $debugsub = $debugsub;
}

=head1 App::CamelPKI::CADB::Cursor

This class models a read only SQL cursor equivalent; instancies may be
constructed using L</search>.

An attentive reader will probably understand that's a fairly trivial
derivation of the L<DBIx::Class> API; However there is no reason to
return directly an instance of I<DBIx::Class> in L</search> because
it will violate the encapsulation of I<App::CamelPKI::CADB>. Consequence
could be a induced coupling (it should be impossible to refactor the
scheme without breaking the whole calling code), and worse, a 
privilege escape leading to a security breach (because it's also
possible to write with a I<DBIx::Class> cursor).

=cut

package App::CamelPKI::CADB::Cursor;

=begin internals

=head2 _new($realcursor, $infos_resultset)

Constructor. $realcursor is an instance of
L<DBIx::Class::ResultSet> coming from
L</App::CamelPKI::CADB::_Schema::Certificate> which represents all certificates
to be enumerated; $infos_resultset is an instance of
L<DBIx::Class::ResultSet> coming from L</App::CamelPKI::CADB::_Schema::CertInfos>
which represents the B<totality> of B<CertInfos> in database, and it's the
job of I<App::CamelPKI::CADB::Cursor> to restrict this search to what it is
interresting.

=cut

sub _new {
    my ($class, $cursor, $infos_resultset) = @_;
    return bless {
                      index => 0,
                      cursor => $cursor,
                      infos_set => $infos_resultset,
                     }, $class;
}

=head2 _fetch_certificates()

Execute the SQL request that rocks, grab in one shot all certificates
and their revocation informations, and cache them in $self->{certs}
which become a list of objects form the
L</App::CamelPKI::CADB::_Schema::Certificate>.

Rationale for this 'slurpy' behavior: SQLite does not appreciate to have
a statement in progress when you close the connection (symptom: 
C<cannot commit transaction - SQL statements in progress(1)>). That's 
why we cannot use the "streaming" mode of DBIx::Class without a complex
system of statement caching in one time, I'm just too lazy to implement
right now...

=cut

sub _fetch_certificates {
    my ($self) = @_;
    return if $self->{certs};
    $self->{certs} = [];
    $self->{cursor}->reset;
    while(my $row = $self->{cursor}->next) {
        push (@{$self->{certs}}, $row);
    }
    return;
}

=head2 _fetch_infos()

Functions as L</_fetch_certificates> (which is called before each operation
of this method), grab in one shot all nominative informations about
certificates, and cache them in $self->{infos} in the form of a reference
to a list of same length as @{$self->{certs}} and ordored the same way,
which contains as many multi-valued hash tables to store informations
as passed by L</add> at the time of the respective certificates insertion.

=cut

sub _fetch_infos {
    my ($self) = @_;
    return if $self->{infos};
    $self->_fetch_certificates;

    my %infos;

    # FIXME: we could repeat the $self->{cursor} SQL instead.
    # This could helps to play too much DBI placeholders...
    my $infocursor = $self->{infos_set}->search
        ({ certid => { in => [ map { $_->certid } @{$self->{certs}} ] }});
    $infocursor->reset;
    while(my $info = $infocursor->next) {
        push(@{$infos{$info->certid}->{$info->key}},
             $info->val);
    }

    $self->{infos} = [ map { ($infos{$_->certid} || {}) }
                       @{$self->{certs}} ];
    return;
}

=head2 _current()

Returns the tuple object currently under the cursor.

=cut

sub _current {
    my ($self) = @_;
    $self->_fetch_certificates;
    return $self->{certs}->[$self->{index}];
}



( run in 2.305 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )