Database-Join

 view release on metacpan or  search on metacpan

lib/Database/Join.pm  view on Meta::CPAN

	return $self->{_schema_cache} if $self->{_schema_cache};

	# Hash slice assignment (@merged{keys} = values) is O(M) per database;
	# the previous (%merged = (%merged, %s)) pattern was O(N×M) per iteration,
	# totalling O(N²×M) over all databases for the same result.
	my %merged;
	for my $i (0 .. $#{ $self->{_dbs} }) {
		my $s        = $self->{_dbs}[$i]->schema() // {};
		my $local_jc = $self->{_join_map}{$i};
		if ($local_jc && $local_jc ne $self->{_join_col}) {
			for my $col (keys %{$s}) {
				$merged{$col} = $s->{$col} unless $col eq $local_jc;
			}
		} else {
			@merged{keys %{$s}} = values %{$s};
		}
	}

	delete @merged{keys %{ $self->{_removed_cols} }}
		if %{ $self->{_removed_cols} };

	$self->{_schema_cache} = \%merged;
	return $self->{_schema_cache};
}

=head2 updated

=head3 SYNOPSIS

    my $ts = $join->updated();

=head3 DESCRIPTION

Returns the Unix timestamp of the most recent modification across all
component databases.  This is the maximum of all individual C<updated()>
return values.

Use this to implement simple cache-invalidation logic: if C<updated()>
has advanced since your last snapshot, re-query.

=head3 API SPECIFICATION

=head4 Input

    None.

=head4 Output

    Unix timestamp (positive integer).

=head3 EXAMPLE

    my $last_modified = $join->updated();
    if ($last_modified > $my_cache_timestamp) {
        $my_cache = $join->selectall_arrayref();
        $my_cache_timestamp = $last_modified;
    }

=cut

sub updated {
	my ($self) = @_;
	return max(map { $_->updated() } @{ $self->{_dbs} });
}

=head2 set_logger

=head3 SYNOPSIS

    $join->set_logger($log);

=head3 DESCRIPTION

Attaches a new logger object to the join and propagates it to every component
database.  The logger is used for diagnostic output by all component databases.

=head3 API SPECIFICATION

=head4 Input

    $log    Positional: a logger object (required).
            Must support whatever interface Database::Abstraction expects.

=head4 Output

    Returns C<$self> for method chaining.

=head3 EXAMPLE

    # Log::Any is used here as an example; any object that implements
    # debug() and info() (or whichever methods your component databases
    # call internally) works equally well.
    use Log::Any qw($log);

    my $join = Database::Join->new(databases => [$db1, $db2], join_column => 'entry');
    $join->set_logger($log);
    # $log is now used by $join and by $db1 and $db2

=cut

sub set_logger {
	my ($self, $logger) = @_;

	croak 'Usage: set_logger($logger)' unless defined $logger;

	$self->{_logger} = $logger;
	$_->set_logger($logger) for @{ $self->{_dbs} };

	return $self;
}

=head2 add_database

=head3 SYNOPSIS

    # Positional: database object as first argument
    $join->add_database($db);

    # Named: equivalent to the above
    $join->add_database(database => $db);



( run in 1.933 second using v1.01-cache-2.11-cpan-6736b670a1e )