1=head1 NAME
2
3DBIx::SQLEngine::Record::Table - Records accessed via a Schema::Table
4
5=head1 SYNOPSIS
6
7B<Setup:> Several ways to create a class.
8
9  my $sqldb = DBIx::SQLEngine->new( ... );
10
11  $class_name = $sqldb->record_class( $table_name );
12
13  $sqldb->record_class( $table_name, $class_name );
14
15  package My::Record;
16  use DBIx::SQLEngine::Record::Class '-isasubclass';
17  My::Record->table( $sqldb->table($table_name) );
18
19B<Basics:> Common operations on a record.
20
21  $record = $class_name->new_with_values(somefield => 'My Value');
22
23  print $record->get_values( 'somefield' );
24
25  $record->change_values( somefield => 'New Value' );
26
27B<Fetch:> Retrieve records by ID or other query.
28
29  $record = $class_name->select_record( $primary_key );
30
31  @records = $class_name->fetch_select(%clauses)->records;
32
33B<Modify:> Write changes to the data source.
34
35  $record->insert_record();
36
37  $record->update_record();
38
39  $record->delete_record();
40
41B<Schema:> Access to table and columns.
42
43  unless ( $class_name->table_exists ) {
44    $class_name->create_table( { name => 'id', type => 'int'} );
45  }
46
47
48=head1 DESCRIPTION
49
50DBIx::SQLEngine::Record::Table is a mixin class for database records in tables accessible via DBIx::SQLEngine.
51
52Don't use this module directly; instead, pass its name as a trait when you create a new record class. This package provides a multiply-composable collection of functionality for Record classes. It is combined with the base class and other traits by DBIx::SQLEngine::Record::Class.
53
54=cut
55
56########################################################################
57
58package DBIx::SQLEngine::Record::Table;
59
60use strict;
61use Carp;
62
63require DBIx::SQLEngine::Schema::Table;
64require DBIx::SQLEngine::RecordSet::Set;
65
66########################################################################
67
68########################################################################
69
70=head1 TABLE INTERFACE
71
72Each record class is associated with a table object. The table provides the
73DBI connection and SQL execution capabilities required to talk to the remote
74data storage.
75
76=head2 Table Accessor
77
78=over 4
79
80=item table()
81
82  $class_name->table() : $table
83  $class_name->table($table)
84
85Get and set our current DBIx::SQLEngine::Schema::Table. Required value.
86Establishes the table a specific class of record will be stored in.
87
88=item get_table()
89
90  $class_name->get_table() : $table or exception
91
92Returns the table, or throws an exception if it is not set.
93
94=back
95
96=cut
97
98use Class::MakeMethods (
99  'Template::ClassInherit:object' => [
100		  table => {class=>'DBIx::SQLEngine::Schema::Table'}
101  ],
102);
103
104sub get_table {
105  ($_[0])->table() or croak("No table set for record class '$_[0]'")
106}
107
108########################################################################
109
110=head2 Methods Delegated to Table
111
112These methods all call the same method on the associated table.
113
114=over 4
115
116=item detect_sqlengine()
117
118  $class_name->detect_sqlengine : $flag
119
120Detects whether the SQL database is avaialable by attempting to connect.
121
122=item table_exists()
123
124  $class_name->table_exists : $flag
125
126Detects whether the table has been created and has not been dropped.
127
128=item columnset()
129
130  $class_name->columnset () : $columnset
131
132Returns the current columnset, if any.
133
134=item fetch_one_value()
135
136  $class_name->fetch_one_value( %sql_clauses ) : $scalar
137
138Calls fetch_select, then returns the first value from the first row of results.
139
140=item count_rows()
141
142  $class_name->count_rows ( ) : $number
143  $class_name->count_rows ( $criteria ) : $number
144
145Return the number of rows in the table. If called with criteria, returns the number of matching rows.
146
147=back
148
149=cut
150
151use Class::MakeMethods (
152  'Standard::Universal:delegate' => [ [ qw(
153	detect_sqlengine
154	table_exists create_table drop_table
155	fetch_one_value count_rows
156	columnset column_primary_name
157    ) ] => { target=>'get_table' },
158  ],
159);
160
161########################################################################
162
163=head2 Table Delegation Methods
164
165The following methods are used internally to facilitate delegation to the table object.
166
167=over 4
168
169=item table_fetch_one_method()
170
171  $class->table_fetch_one_method( $method, @args );
172
173Calls the named method on the table and inflates the result with record_from_db_data.
174
175=item table_fetch_set_method()
176
177  $class->table_fetch_set_method( $method, @args );
178
179Calls the named method on the table and inflates the result with record_set_from_db_data.
180
181=item table_record_method()
182
183  $record->table_record_method( $method, @args );
184
185Calls the named method on the table, passing the record itself as the first argument.
186
187=back
188
189=cut
190
191sub table_fetch_one_method {
192  my $self = shift;
193  my $method = shift;
194  $self->record_from_db_data( $self->get_table()->$method( @_ ) )
195}
196
197sub table_fetch_set_method {
198  my $self = shift;
199  my $method = shift;
200  $self->record_set_from_db_data( scalar $self->get_table()->$method( @_ ) )
201}
202
203sub table_record_method {
204  my $self = shift;
205  my $method = shift;
206  ref($self) or croak("Can't call this object method on a record class");
207  $self->get_table()->$method( $self, @_ );
208}
209
210########################################################################
211
212=head2 Primary Keys
213
214=over 4
215
216=item primary_criteria()
217
218  $record->primary_criteria() : $hash_ref
219
220Returns a hash of key-value pairs which could be used to select this record by its primary key.
221
222=item primary_key_value()
223
224  $record->primary_key_value() : $id_value
225
226Returns the primary key value for this object.
227
228=back
229
230=cut
231
232sub primary_criteria {
233  (shift)->table_record_method('primary_criteria');
234}
235
236sub primary_key_value {
237  my $self = shift;
238
239  $self->{ $self->column_primary_name() }
240}
241
242########################################################################
243
244########################################################################
245
246=head1 FETCHING DATA (SQL DQL)
247
248=head2 Select to Retrieve Records
249
250=over 4
251
252=item fetch_select()
253
254  $class_name->fetch_select ( %select_clauses ) : $record_set
255
256Retrives records from the table using the provided SQL select clauses.
257
258Calls the corresponding SQLEngine method with the table name and the provided arguments. Each row hash is blessed into the record class before being wrapped in a RecordSet::Set object.
259
260=item fetch_one_record()
261
262  $sqldb->fetch_one_record( %select_clauses ) : $record_hash
263
264Retrives one record from the table using the provided SQL select clauses.
265
266Calls fetch_select, then returns only the first row of results. The row hash is blessed into the record class before being returned.
267
268=item visit_select()
269
270  $class_name->visit_select ( $sub_ref, %select_clauses ) : @results
271  $class_name->visit_select ( %select_clauses, $sub_ref ) : @results
272
273Calls the provided subroutine on each matching record as it is retrieved. Returns the accumulated results of each subroutine call (in list context).
274
275Each row hash is blessed into the record class before being the subroutine is called.
276
277=back
278
279=cut
280
281# $records = $record_class->fetch_select( %select_clauses );
282sub fetch_select {
283  (shift)->table_fetch_set_method('fetch_select', @_)
284}
285
286# $record = $record_class->fetch_one_record( %clauses );
287sub fetch_one_record {
288  (shift)->table_fetch_one_method('fetch_one_row', @_)
289}
290
291# @results = $record_class->visit_select( %select_clauses, $sub );
292# @results = $record_class->visit_select( $sub, %select_clauses );
293sub visit_select {
294  my $self = shift;
295  my $sub = ( ref($_[0]) ? shift : pop );
296  $self->get_table()->visit_select(@_,
297			      sub { $self->record_from_db_data($_[0]); &$sub })
298}
299
300########################################################################
301
302=head2 Selecting by Primary Key
303
304=over 4
305
306=item select_record()
307
308  $class_name->select_record ( $primary_key_value ) : $record_obj
309  $class_name->select_record ( \@compound_primary_key ) : $record_obj
310  $class_name->select_record ( \%hash_with_primary_key_value ) : $record_obj
311
312Fetches a single record by primary key.
313
314The row hash is blessed into the record class before being returned.
315
316=item select_records()
317
318  $class_name->select_records ( @primary_key_values_or_hashrefs ) : $record_set
319
320Fetches a set of one or more records by primary key.
321
322Each row hash is blessed into the record class before being wrapped in a RecordSet::Set object.
323
324=back
325
326=cut
327
328# $criteria = $record_class->criteria_for_primary_key( $id_value );
329# $criteria = $record_class->criteria_for_primary_key( \@compound_id );
330# $criteria = $record_class->criteria_for_primary_key( \%hash_with_pk );
331sub criteria_for_primary_key {
332  (shift)->get_table()->primary_criteria(@_)
333}
334
335# $record = $record_class->select_record( $id_value );
336# $record = $record_class->select_record( \@compound_id );
337# $record = $record_class->select_record( \%hash_with_pk );
338sub select_record {
339  my ( $self, $id ) = @_;
340  $self->fetch_one_record( where => $self->criteria_for_primary_key($id) )
341}
342
343# $records = $record_class->select_records( @ids_or_hashes );
344sub select_records {
345  my ( $self, @ids ) = @_;
346  $self->fetch_select( where => $self->criteria_for_primary_key(@ids) )
347}
348
349########################################################################
350
351########################################################################
352
353=head1 EDITING DATA (SQL DML)
354
355=head2 Insert to Add Records
356
357After constructing a record with one of the new_*() methods, you may save any changes by calling insert_record.
358
359=over 4
360
361=item insert_record()
362
363  $record_obj->insert_record() : $flag
364
365Adds the values from this record to the table. Returns the number of rows affected, which should be 1 unless there's an error.
366
367=back
368
369=cut
370
371# $record_obj->insert_record();
372sub insert_record {
373  (shift)->table_record_method('insert_row');
374}
375
376########################################################################
377
378=head2 Update to Change Records
379
380After retrieving a record with one of the fetch methods, you may save any changes by calling update_record.
381
382=over 4
383
384=item update_record()
385
386  $record_obj->update_record() : $record_count
387
388Attempts to update the record using its primary key as a unique identifier. Returns the number of rows affected, which should be 1 unless there's an error.
389
390=back
391
392=cut
393
394# $record_obj->update_record();
395sub update_record {
396  (shift)->table_record_method('update_row');
397}
398
399########################################################################
400
401=head2 Delete to Remove Records
402
403=over 4
404
405=item delete_record()
406
407  $record_obj->delete_record() : $record_count
408
409Delete this existing record based on its primary key. Returns the number of rows affected, which should be 1 unless there's an error.
410
411=back
412
413=cut
414
415# $record_obj->delete_record();
416sub delete_record {
417  (shift)->table_record_method('delete_row');
418}
419
420########################################################################
421
422########################################################################
423
424=head1 SEE ALSO
425
426For more about the Record classes, see L<DBIx::SQLEngine::Record::Class>.
427
428See L<DBIx::SQLEngine> for the overall interface and developer documentation.
429
430See L<DBIx::SQLEngine::Docs::ReadMe> for general information about
431this distribution, including installation and license information.
432
433=cut
434
435########################################################################
436
4371;
438