pod tweaking for line wrappings
[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
f5d3a5de 92 $self->write_source->connect_info( [ @{$info->[0]}, { %$global_options } ] );
93
94 @dsns = map { ($_->[3]->{priority} || 10) => $_ } @{$info}[1..@$info-1];
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
134sub limit_dialect {
135 my $self = shift;
136 $self->$_->limit_dialect( @_ ) for( $self->all_sources );
137}
138sub quote_char {
139 my $self = shift;
140 $self->$_->quote_char( @_ ) for( $self->all_sources );
141}
142sub name_sep {
143 my $self = shift;
144 $self->$_->quote_char( @_ ) for( $self->all_sources );
145}
146sub disconnect {
147 my $self = shift;
148 $self->$_->disconnect( @_ ) for( $self->all_sources );
149}
150sub DESTROY {
151 my $self = shift;
152
153 undef $self->{write_source};
154 undef $self->{read_sources};
155}
156
157sub last_insert_id {
158 shift->write_source->last_insert_id( @_ );
159}
160sub insert {
161 shift->write_source->insert( @_ );
162}
163sub update {
164 shift->write_source->update( @_ );
165}
166sub update_all {
167 shift->write_source->update_all( @_ );
168}
169sub delete {
170 shift->write_source->delete( @_ );
171}
172sub delete_all {
173 shift->write_source->delete_all( @_ );
174}
175sub create {
176 shift->write_source->create( @_ );
177}
178sub find_or_create {
179 shift->write_source->find_or_create( @_ );
180}
181sub update_or_create {
182 shift->write_source->update_or_create( @_ );
183}
184sub connected {
185 shift->write_source->connected( @_ );
186}
187sub ensure_connected {
188 shift->write_source->ensure_connected( @_ );
189}
190sub dbh {
191 shift->write_source->dbh( @_ );
192}
193sub txn_begin {
194 shift->write_source->txn_begin( @_ );
195}
196sub txn_commit {
197 shift->write_source->txn_commit( @_ );
198}
199sub txn_rollback {
200 shift->write_source->txn_rollback( @_ );
201}
202sub sth {
203 shift->write_source->sth( @_ );
204}
205sub deploy {
206 shift->write_source->deploy( @_ );
207}
208
209
210sub debugfh { shift->_not_supported( 'debugfh' ) };
211sub debugcb { shift->_not_supported( 'debugcb' ) };
212
213sub _not_supported {
214 my( $self, $method ) = @_;
215
216 die "This Storage does not support $method method.";
217}
218
219=head1 SEE ALSO
220
221L<DBI::Class::Storage::DBI>, L<DBD::Multi>, L<DBI>
222
223=head1 AUTHOR
224
225Norbert Csongrádi <bert@cpan.org>
226
227Peter Siklósi <einon@einon.hu>
228
229=head1 LICENSE
230
231You may distribute this code under the same terms as Perl itself.
232
233=cut
234
2351;