Documentation updates from omega, carbon
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Replication.pm
CommitLineData
f5d3a5de 1package DBIx::Class::Storage::DBI::Replication;
2
3use strict;
4use warnings;
5
6use DBIx::Class::Storage::DBI;
7use DBD::Multi;
8use base qw/Class::Accessor::Fast/;
9
10__PACKAGE__->mk_accessors( qw/read_source write_source/ );
11
12=head1 NAME
13
14DBIx::Class::Storage::DBI::Replication - EXPERIMENTAL Replicated database support
15
16=head1 SYNOPSIS
17
18 # change storage_type in your schema class
19 $schema->storage_type( '::DBI::Replication' );
20 $schema->connect_info( [
21 [ "dbi:mysql:database=test;hostname=master", "username", "password", { AutoCommit => 1 } ], # master
22 [ "dbi:mysql:database=test;hostname=slave1", "username", "password", { priority => 10 } ], # slave1
23 [ "dbi:mysql:database=test;hostname=slave2", "username", "password", { priority => 10 } ], # slave2
24 <...>,
25 { limit_dialect => 'LimitXY' } # If needed, see below
26 ] );
27
28=head1 DESCRIPTION
29
30Warning: This class is marked EXPERIMENTAL. It works for the authors but does
31not currently have automated tests so your mileage may vary.
32
0aff97c2 33This class implements replicated data store for DBI. Currently you can define
34one master and numerous slave database connections. All write-type queries
35(INSERT, UPDATE, DELETE and even LAST_INSERT_ID) are routed to master
36database, all read-type queries (SELECTs) go to the slave database.
f5d3a5de 37
0aff97c2 38For every slave database you can define a priority value, which controls data
39source usage pattern. It uses L<DBD::Multi>, so first the lower priority data
40sources used (if they have the same priority, the are used randomized), than
41if all low priority data sources fail, higher ones tried in order.
f5d3a5de 42
43=head1 CONFIGURATION
44
45=head2 Limit dialect
46
0aff97c2 47If you use LIMIT in your queries (effectively, if you use
48SQL::Abstract::Limit), do not forget to set up limit_dialect (perldoc
49SQL::Abstract::Limit) by passing it as an option in the (optional) hash
50reference to connect_info. DBIC can not set it up automatically, since it can
51not guess DBD::Multi connection types.
f5d3a5de 52
53=cut
54
55sub new {
56 my $proto = shift;
57 my $class = ref( $proto ) || $proto;
58 my $self = {};
59
60 bless( $self, $class );
61
62 $self->write_source( DBIx::Class::Storage::DBI->new );
63 $self->read_source( DBIx::Class::Storage::DBI->new );
64
65 return $self;
66}
67
68sub all_sources {
69 my $self = shift;
70
71 my @sources = ($self->read_source, $self->write_source);
72
73 return wantarray ? @sources : \@sources;
74}
75
76sub connect_info {
77 my( $self, $source_info ) = @_;
78
79 my( $info, $global_options, $options, @dsns );
80
81 $info = [ @$source_info ];
82
83 $global_options = ref $info->[-1] eq 'HASH' ? pop( @$info ) : {};
84 if( ref( $options = $info->[0]->[-1] ) eq 'HASH' ) {
85 # Local options present in dsn, merge them with global options
86 map { $global_options->{$_} = $options->{$_} } keys %$options;
87 pop @{$info->[0]};
88 }
89
0aff97c2 90 # We need to copy-pass $global_options, since connect_info clears it while
91 # processing options
9ac2605b 92 $self->write_source->connect_info( @{$info->[0]}, { %$global_options } );
f5d3a5de 93
9ac2605b 94 @dsns = map { ($_->[3]->{priority} || 10) => $_ } @{$info->[0]}[1..@{$info->[0]}-1];
f5d3a5de 95 $global_options->{dsns} = \@dsns;
96
97 $self->read_source->connect_info( [ 'dbi:Multi:', undef, undef, { %$global_options } ] );
98}
99
100sub select {
101 shift->read_source->select( @_ );
102}
103sub select_single {
104 shift->read_source->select_single( @_ );
105}
106sub throw_exception {
107 shift->read_source->throw_exception( @_ );
108}
109sub sql_maker {
110 shift->read_source->sql_maker( @_ );
111}
112sub columns_info_for {
113 shift->read_source->columns_info_for( @_ );
114}
115sub sqlt_type {
116 shift->read_source->sqlt_type( @_ );
117}
118sub create_ddl_dir {
119 shift->read_source->create_ddl_dir( @_ );
120}
121sub deployment_statements {
122 shift->read_source->deployment_statements( @_ );
123}
124sub datetime_parser {
125 shift->read_source->datetime_parser( @_ );
126}
127sub datetime_parser_type {
128 shift->read_source->datetime_parser_type( @_ );
129}
130sub build_datetime_parser {
131 shift->read_source->build_datetime_parser( @_ );
132}
133
9b21c682 134sub limit_dialect { $_->limit_dialect( @_ ) for( shift->all_sources ) }
135sub quote_char { $_->quote_char( @_ ) for( shift->all_sources ) }
136sub name_sep { $_->quote_char( @_ ) for( shift->all_sources ) }
137sub disconnect { $_->disconnect( @_ ) for( shift->all_sources ) }
138sub set_schema { $_->set_schema( @_ ) for( shift->all_sources ) }
139
f5d3a5de 140sub DESTROY {
141 my $self = shift;
142
143 undef $self->{write_source};
144 undef $self->{read_sources};
145}
146
147sub last_insert_id {
148 shift->write_source->last_insert_id( @_ );
149}
150sub insert {
151 shift->write_source->insert( @_ );
152}
153sub update {
154 shift->write_source->update( @_ );
155}
156sub update_all {
157 shift->write_source->update_all( @_ );
158}
159sub delete {
160 shift->write_source->delete( @_ );
161}
162sub delete_all {
163 shift->write_source->delete_all( @_ );
164}
165sub create {
166 shift->write_source->create( @_ );
167}
168sub find_or_create {
169 shift->write_source->find_or_create( @_ );
170}
171sub update_or_create {
172 shift->write_source->update_or_create( @_ );
173}
174sub connected {
175 shift->write_source->connected( @_ );
176}
177sub ensure_connected {
178 shift->write_source->ensure_connected( @_ );
179}
180sub dbh {
181 shift->write_source->dbh( @_ );
182}
183sub txn_begin {
184 shift->write_source->txn_begin( @_ );
185}
186sub txn_commit {
187 shift->write_source->txn_commit( @_ );
188}
189sub txn_rollback {
190 shift->write_source->txn_rollback( @_ );
191}
192sub sth {
193 shift->write_source->sth( @_ );
194}
195sub deploy {
196 shift->write_source->deploy( @_ );
197}
198
199
200sub debugfh { shift->_not_supported( 'debugfh' ) };
201sub debugcb { shift->_not_supported( 'debugcb' ) };
202
203sub _not_supported {
204 my( $self, $method ) = @_;
205
206 die "This Storage does not support $method method.";
207}
208
209=head1 SEE ALSO
210
211L<DBI::Class::Storage::DBI>, L<DBD::Multi>, L<DBI>
212
213=head1 AUTHOR
214
215Norbert Csongrádi <bert@cpan.org>
216
217Peter Siklósi <einon@einon.hu>
218
219=head1 LICENSE
220
221You may distribute this code under the same terms as Perl itself.
222
223=cut
224
2251;