package DBIx::Class::Storage::DBI::mysql_repl;

use strict;
use warnings;

use DBIx::Class::Storage::DBI::mysql;
use base qw/Class::Accessor::Fast/;

__PACKAGE__->mk_accessors( qw/write_source/ );

=head1 NAME

DBIx::Class::Storage::DBI::mysql_repl - Replicated databases support for MySQL

=head1 SYNOPSIS

  # change storage_type in your schema class
    $schema->storage_type( '::DBI::mysql_repl' );
    $schema->connect_info( [
		     [ "dbi:mysql:database=test;hostname=master", "username", "password", { AutoCommit => 1 } ], # master
		     [ "dbi:mysql:database=test;hostname=slave1", "username", "password", {} ],                  # slave1
		     [ "dbi:mysql:database=test;hostname=slave2", "username", "password", {} ],                  # slave2
		     <...>
		    ] );

=head1 DESCRIPTION

This class implements replicated data store for MySQL. Currently you can define one master and numerous slave database connections. All write-type queries (INSERT, UPDATE, DELETE and even LAST_INSERT_ID) are routed to master database, all read-type queries (SELECTs) go to the slave database.

=cut

sub new {
    my $proto = shift;
    my $class = ref( $proto ) || $proto;
    my $self = {
	read_sources => [],
	read_iterator => 0,
    };

    bless( $self, $class );

    $self->write_source( DBIx::Class::Storage::DBI::mysql->new );

    return $self;
}

sub read_source {
    my $self = shift;

    ## RR iterator on read_sources
    if( ++$self->{read_iterator} >= @{$self->{read_sources}} ) {
	$self->{read_iterator} = 0;
    }

    return $self->{read_sources}->[$self->{read_iterator}];
}

sub connect_info {
    my( $self, $source_info ) = @_;

    $self->write_source()->connect_info( $source_info->[0] );
    foreach my $index ( 1..(@{$source_info}-1) ) {
	my $dbi = DBIx::Class::Storage::DBI::mysql->new;
	$dbi->connect_info( $source_info->[$index] );
	push( @{$self->{read_sources}}, $dbi );
    }
}

sub AUTOLOAD {
    my $self = shift;

    my ( $method ) = ( our $AUTOLOAD =~ /([^:]+)$/ );
    return if $method eq "DESTROY";

    if( $method =~ /^update|update_all|delete|delete_all|last_insert_id|create|find_or_create|update_or_create$/ ) {
	return $self->write_source()->$method( @_ );
    } else {
	return $self->read_source()->$method( @_ );
    }
}

=head1 AUTHORS

Norbert Csongradi <bert@cpan.org>
Peter Siklosi <einon@ahq.hu>

=head1 LICENSE

You may distribute this code under the same terms as Perl itself.

=cut

1;
