Anansi-DatabaseComponent

 view release on metacpan or  search on metacpan

lib/Anansi/DatabaseComponent.pm  view on Meta::CPAN

package Anansi::DatabaseComponent;


=head1 NAME

Anansi::DatabaseComponent - A manager template for database drivers.

=head1 SYNOPSIS

    package Anansi::Database::Example;

    use base qw(Anansi::DatabaseComponent);

    sub connect {
        my ($self, $channel, %parameters) = @_;
        return $self->SUPER::connect(
            undef,
            INPUT => [
                'some text',
                {
                    NAME => 'someParameter',
                }, {
                    INPUT => [
                        'more text',
                        {
                            NAME => 'anotherParameter',
                        },
                        'yet more text',
                    ]
                }, {
                    DEFAULT => 'abc',
                    NAME => 'yetAnotherParameter',
                },
            ],
            (%parameters),
        );
    }

    sub validate {
        my ($self, $channel, %parameters) = @_;
        $parameters{DRIVER} = 'Example';
        return Anansi::DatabaseComponent::validate(undef, %parameters);
    }

    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'AUTOCOMMIT' => 'Anansi::DatabaseComponent::autocommit');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'COMMIT' => 'Anansi::DatabaseComponent::commit');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'CONNECT' => 'connect');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'DISCONNECT' => 'Anansi::DatabaseComponent::disconnect');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'FINISH' => 'Anansi::DatabaseComponent::finish');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'HANDLE' => 'Anansi::DatabaseComponent::handle');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'PREPARE' => 'Anansi::DatabaseComponent::prepare');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'ROLLBACK' => 'Anansi::DatabaseComponent::rollback');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'STATEMENT' => 'Anansi::DatabaseComponent::statement');
    Anansi::DatabaseComponent::addChannel('Anansi::Database::Example', 'VALIDATE_AS_APPROPRIATE' => 'validate'); 

    1;

    package main;

    use Anansi::Database;

    my $database = Anansi::Database->new();
    my $component = $database->addComponent(undef,
        DRIVER => 'Example',
    );
    if(defined($component)) {
        if($database->connect(
            undef,
            $component,
            someParameter => 'some data',
            anotherParameter => 'more data',
            yetAnotherParameter => 'further data',
        )) {
            my $result = $database->statement(
                undef,
                $component,

lib/Anansi/DatabaseComponent.pm  view on Meta::CPAN



=head3 using

See L<Anansi::Class::using|Anansi::Class/"using"> for details.

=cut


=head2 Anansi::Component

See L<Anansi::Component|Anansi::Component> for details.  A parent module of L<Anansi::DatabaseComponent|Anansi::DatabaseComponent>.

=cut


=head3 Anansi::Class

See L<Anansi::Class|Anansi::Class> for details.  A parent module of L<Anansi::Component|Anansi::Component>.

=cut


=head3 addChannel

See L<Anansi::Component::addChannel|Anansi::Component/"addChannel"> for details.  Overridden by L<Anansi::DatabaseComponent::addChannel|Anansi::DatabaseComponent/"addChannel">.

=cut


=head3 channel

See L<Anansi::Component::channel|Anansi::Component/"channel"> for details.

=cut


=head3 componentManagers

See L<Anansi::Component::componentManagers|Anansi::Component/"componentManagers"> for details.

=cut


=head3 removeChannel

See L<Anansi::Component::removeChannel|Anansi::Component/"removeChannel"> for details.  Overridden by L<Anansi::DatabaseComponent::removeChannel|Anansi::DatabaseComponent/"removeChannel">.

=cut


=head2 addChannel

Overrides L<Anansi::Component::addChannel|Anansi::Component/"addChannel">.

=cut


sub addChannel {
    my ($self, %parameters) = @_;
    return $self->SUPER::addChannel((%parameters));
}


=head2 autoCommit

    if(1 == Anansi::DatabaseComponent::autocommit($OBJECT, undef));

    if(1 == Anansi::DatabaseComponent::channel($OBJECT, 'AUTOCOMMIT'));

    if(1 == $OBJECT->autocommit(undef));

    if(1 == $OBJECT->channel('AUTOCOMMIT'));

=over 4

=item self I<(Blessed Hash, Required)>

An object of this namespace.

=item channel I<(String, Required)>

The abstract identifier of a subroutine.

=item parameters I<(Hash, Optional)>

Named parameters.

=back

Attempts to perform a database autocommit.  Returns B<1> I<(one)> on success and
B<0> I<(zero)> on failure.

=cut


sub autocommit {
    my ($self, $channel, %parameters) = @_;
    return 0 if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i);
    my $autocommit;
    eval {
        $autocommit = $self->{HANDLE}->autocommit();
        1;
    } or do {
        return 0;
    };
    return 0 if(!defined($autocommit));
    return 0 if(ref($autocommit) !~ /^$/);
    return 0 if($autocommit !~ /^[\+\-]?\d+$/);
    return 1 if($autocommit);
    return 0;
}

Anansi::DatabaseComponent::addChannel('Anansi::DatabaseComponent', 'AUTOCOMMIT' => 'autocommit');


=head2 bind

    if(Anansi::DatabaseComponent::bind($OBJECT,
        HANDLE => $HANDLE,
        INPUT => [

lib/Anansi/DatabaseComponent.pm  view on Meta::CPAN

required to fulfill the SQL statement when called as a namespace method or B<1>
I<(one)> when called through a channel on success and B<0> I<(zero)> on failure.

=cut


sub prepare {
    my ($self, $channel, %parameters) = @_;
    return 0 if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i);
    $self->{STATEMENTS} = {} if(!defined($self->{STATEMENTS}));
    return 0 if(!defined($parameters{STATEMENT}));
    return 0 if(ref($parameters{STATEMENT}) !~ /^$/);
    if(!defined(${$self->{STATEMENTS}}{$parameters{STATEMENT}})) {
        return 0 if(!defined($parameters{SQL}));
        return 0 if(ref($parameters{SQL}) !~ /^$/);
        $parameters{SQL} =~ s/^\s*(.*)|(.*)\s*$/$1/g;
        my $questionMarks = $parameters{SQL};
        my $questionMarks = $questionMarks =~ s/\?/$1/sg;
        if(0 == $questionMarks) {
            return 0 if(defined($parameters{INPUT}));
        } elsif(!defined($parameters{INPUT})) {
            return 0;
        } elsif(ref($parameters{INPUT}) !~ /^ARRAY$/i) {
            return 0;
        } elsif(scalar(@{$parameters{INPUT}}) != $questionMarks) {
            return 0;
        } else {
            return 0 if(!$self->binding((@{$parameters{INPUT}})));
        }
        my $handle;
        eval {
            $handle = $self->{HANDLE}->prepare($parameters{SQL});
            1;
        } or do {
            $self->rollback();
            return 0;
        };
        my %statement = (
            HANDLE => $handle,
            SQL => $parameters{SQL},
        );
        $statement{INPUT} = $parameters{INPUT} if(defined($parameters{INPUT}));
        ${$self->{STATEMENTS}}{$parameters{STATEMENT}} = \%statement;
    }
    return 1 if(defined($channel));
    return ${$self->{STATEMENTS}}{$parameters{STATEMENT}};
}

Anansi::DatabaseComponent::addChannel('Anansi::DatabaseComponent', 'PREPARE' => 'prepare');


=head2 removeChannel

Overrides L<Anansi::Component::removeChannel|Anansi::Component/"removeChannel">.

=cut


sub removeChannel {
    my ($self, %parameters) = @_;
    return $self->SUPER::removeChannel((%parameters));
}


=head2 rollback

    if(1 == Anansi::DatabaseComponent::rollback($OBJECT, undef));

    if(1 == Anansi::DatabaseComponent::channel($OBJECT, 'ROLLBACK'));

    if(1 == $OBJECT->rollback(undef));

    if(1 == $OBJECT->channel('ROLLBACK'));

=over 4

=item self I<(Blessed Hash, Required)>

Either an object or a string of this namespace.

=item channel I<(String, Required)>

The abstract identifier of a subroutine.

=item parameters I<(Hash, Optional)>

Named parameters.

=back

Attempts to undo all of the database changes since the last database I<commit>.
Returns B<1> I<(one)> on success and B<0> I<(zero)> on failure.

=cut


sub rollback {
    my ($self, $channel, %parameters) = @_;
    return 0 if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i);
    return 0 if($self->autocommit());
    my $rollback;
    eval {
        $rollback = $self->{HANDLE}->rollback();
        1;
    } or do {
        return 0;
    };
    return 0 if(!defined($rollback));
    return 0 if(ref($rollback) !~ /^$/);
    return 0 if($rollback !~ /^[\+\-]?\d+$/);
    return 1 if($rollback);
    return 0;
}

Anansi::DatabaseComponent::addChannel('Anansi::DatabaseComponent', 'ROLLBACK' => 'rollback');


=begin comment

################################################################################



( run in 1.576 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )