1DBIx::SearchBuilder::ReUcsoerrd(C3o)ntributed Perl DocumDeBnItxa:t:iSoenarchBuilder::Record(3)
2
3
4
6 DBIx::SearchBuilder::Record - Superclass for records loaded by
7 SearchBuilder
8
10 package MyRecord;
11 use base qw/DBIx::SearchBuilder::Record/;
12
13 sub _Init {
14 my $self = shift;
15 my $DBIxHandle =
16 shift; # A DBIx::SearchBuilder::Handle::foo object for your database
17
18 $self->_Handle($DBIxHandle);
19 $self->Table("Users");
20 }
21
22 # Tell Record what the primary keys are
23 sub _PrimaryKeys {
24 return ['id'];
25 }
26
27 # Preferred and most efficient way to specify fields attributes in a derived
28 # class, used by the autoloader to construct Attrib and SetAttrib methods.
29
30 # read: calling $Object->Foo will return the value of this record's Foo column
31 # write: calling $Object->SetFoo with a single value will set Foo's value in
32 # both the loaded object and the database
33 sub _ClassAccessible {
34 {
35 Tofu => { 'read' => 1, 'write' => 1 },
36 Maz => { 'auto' => 1, },
37 Roo => { 'read' => 1, 'auto' => 1, 'public' => 1, },
38 };
39 }
40
41 # A subroutine to check a user's password without returning the current value
42 # For security purposes, we didn't expose the Password method above
43 sub IsPassword {
44 my $self = shift;
45 my $try = shift;
46
47 # note two __s in __Value. Subclasses may muck with _Value, but
48 # they should never touch __Value
49
50 if ( $try eq $self->__Value('Password') ) {
51 return (1);
52 }
53 else {
54 return (undef);
55 }
56 }
57
58 # Override DBIx::SearchBuilder::Create to do some checking on create
59 sub Create {
60 my $self = shift;
61 my %fields = (
62 UserId => undef,
63 Password => 'default', #Set a default password
64 @_
65 );
66
67 # Make sure a userid is specified
68 unless ( $fields{'UserId'} ) {
69 die "No userid specified.";
70 }
71
72 # Get DBIx::SearchBuilder::Record->Create to do the real work
73 return (
74 $self->SUPER::Create(
75 UserId => $fields{'UserId'},
76 Password => $fields{'Password'},
77 Created => time
78 )
79 );
80 }
81
83 DBIx::SearchBuilder::Record is designed to work with
84 DBIx::SearchBuilder.
85
86 What is it trying to do.
87 DBIx::SearchBuilder::Record abstracts the agony of writing the common
88 and generally simple SQL statements needed to serialize and De-
89 serialize an object to the database. In a traditional system, you
90 would define various methods on your object 'create', 'find', 'modify',
91 and 'delete' being the most common. In each method you would have a
92 SQL statement like:
93
94 select * from table where value='blah';
95
96 If you wanted to control what data a user could modify, you would have
97 to do some special magic to make accessors do the right thing. Etc.
98 The problem with this approach is that in a majority of the cases, the
99 SQL is incredibly simple and the code from one method/object to the
100 next was basically the same.
101
102 <trumpets>
103
104 Enter, DBIx::SearchBuilder::Record.
105
106 With Record, you can in the simple case, remove all of that code and
107 replace it by defining two methods and inheriting some code. It's
108 pretty simple, and incredibly powerful. For more complex cases, you
109 can do more complicated things by overriding certain methods. Let's
110 stick with the simple case for now.
111
112 The two methods in question are "_Init" and "_ClassAccessible". All
113 they really do are define some values and send you on your way. As you
114 might have guessed the '_' means that these are private methods. They
115 will get called by your record object's constructor.
116
117 '_Init'
118 Defines what table we are talking about, and set a variable to
119 store the database handle.
120
121 '_ClassAccessible
122 Defines what operations may be performed on various data selected
123 from the database. For example you can define fields to be
124 mutable, or immutable, there are a few other options but I don't
125 understand what they do at this time.
126
127 And really, that's it. So let's have some sample code.
128
129 An Annotated Example
130 The example code below makes the following assumptions:
131
132 • The database is 'postgres',
133
134 • The host is 'reason',
135
136 • The login name is 'mhat',
137
138 • The database is called 'example',
139
140 • The table is called 'simple',
141
142 • The table looks like so:
143
144 id integer not NULL, primary_key(id),
145 foo varchar(10),
146 bar varchar(10)
147
148 First, let's define our record class in a new module named "Simple.pm".
149
150 000: package Simple;
151 001: use DBIx::SearchBuilder::Record;
152 002: @ISA = (DBIx::SearchBuilder::Record);
153
154 This should be pretty obvious, name the package, import ::Record and
155 then define ourself as a subclass of ::Record.
156
157 003:
158 004: sub _Init {
159 005: my $this = shift;
160 006: my $handle = shift;
161 007:
162 008: $this->_Handle($handle);
163 009: $this->Table("Simple");
164 010:
165 011: return ($this);
166 012: }
167
168 Here we set our handle and table name, while its not obvious so far,
169 we'll see later that $handle (line: 006) gets passed via ::Record::new
170 when a new instance is created. That's actually an important concept:
171 the DB handle is not bound to a single object but rather, it is shared
172 across objects.
173
174 013:
175 014: sub _ClassAccessible {
176 015: {
177 016: Foo => { 'read' => 1 },
178 017: Bar => { 'read' => 1, 'write' => 1 },
179 018: Id => { 'read' => 1 }
180 019: };
181 020: }
182
183 What's happening might be obvious, but just in case this method is
184 going to return a reference to a hash. That hash is where our columns
185 are defined, as well as what type of operations are acceptable.
186
187 021:
188 022: 1;
189
190 Like all perl modules, this needs to end with a true value.
191
192 Now, on to the code that will actually *do* something with this object.
193 This code would be placed in your Perl script.
194
195 000: use DBIx::SearchBuilder::Handle;
196 001: use Simple;
197
198 Use two packages, the first is where I get the DB handle from, the
199 latter is the object I just created.
200
201 002:
202 003: my $handle = DBIx::SearchBuilder::Handle->new();
203 004: $handle->Connect( 'Driver' => 'Pg',
204 005: 'Database' => 'test',
205 006: 'Host' => 'reason',
206 007: 'User' => 'mhat',
207 008: 'Password' => '');
208
209 Creates a new DBIx::SearchBuilder::Handle, and then connects to the
210 database using that handle. Pretty straight forward, the password ''
211 is what I use when there is no password. I could probably leave it
212 blank, but I find it to be more clear to define it.
213
214 009:
215 010: my $s = Simple->new($handle);
216 011:
217 012: $s->LoadById(1);
218
219 LoadById is one of four 'LoadBy' methods, as the name suggests it
220 searches for an row in the database that has id='0'. ::SearchBuilder
221 has, what I think is a bug, in that it current requires there to be an
222 id field. More reasonably it also assumes that the id field is unique.
223 LoadById($id) will do undefined things if there is >1 row with the same
224 id.
225
226 In addition to LoadById, we also have:
227
228 LoadByCol
229 Takes two arguments, a column name and a value. Again, it will do
230 undefined things if you use non-unique things.
231
232 LoadByCols
233 Takes a hash of columns=>values and returns the *first* to match.
234 First is probably lossy across databases vendors.
235
236 LoadFromHash
237 Populates this record with data from a DBIx::SearchBuilder. I'm
238 currently assuming that DBIx::SearchBuilder is what we use in cases
239 where we expect > 1 record. More on this later.
240
241 Now that we have a populated object, we should do something with it!
242 ::Record automagically generates accessos and mutators for us, so all
243 we need to do is call the methods. Accessors are named <Field>(), and
244 Mutators are named Set<Field>($). On to the example, just appending
245 this to the code from the last example.
246
247 013:
248 014: print "ID : ", $s->Id(), "\n";
249 015: print "Foo : ", $s->Foo(), "\n";
250 016: print "Bar : ", $s->Bar(), "\n";
251
252 That's all you have to to get the data. Now to change the data!
253
254 017:
255 018: $s->SetBar('NewBar');
256
257 Pretty simple! That's really all there is to it. Set<Field>($) returns
258 a boolean and a string describing the problem. Let's look at an
259 example of what will happen if we try to set a 'Id' which we previously
260 defined as read only.
261
262 019: my ($res, $str) = $s->SetId('2');
263 020: if (! $res) {
264 021: ## Print the error!
265 022: print "$str\n";
266 023: }
267
268 The output will be:
269
270 >> Immutable field
271
272 Currently Set<Field> updates the data in the database as soon as you
273 call it. In the future I hope to extend ::Record to better support
274 transactional operations, such that updates will only happen when "you"
275 say so.
276
277 Finally, adding a removing records from the database. ::Record
278 provides a Create method which simply takes a hash of key=>value pairs.
279 The keys exactly map to database fields.
280
281 023: ## Get a new record object.
282 024: $s1 = Simple->new($handle);
283 025: $s1->Create('Id' => 4,
284 026: 'Foo' => 'Foooooo',
285 027: 'Bar' => 'Barrrrr');
286
287 Poof! A new row in the database has been created! Now let's delete the
288 object!
289
290 028:
291 029: $s1 = undef;
292 030: $s1 = Simple->new($handle);
293 031: $s1->LoadById(4);
294 032: $s1->Delete();
295
296 And it's gone.
297
298 For simple use, that's more or less all there is to it. In the future,
299 we hope to expand this how-to to discuss using container classes,
300 overloading, etc.
301
303 Each method has a lower case alias; '_' is used to separate words. For
304 example, the method "_PrimaryKeys" has the alias "_primary_keys".
305
307 new
308 Instantiate a new record object.
309
310 id
311 Returns this row's primary key.
312
313 primary_keys
314 PrimaryKeys
315 Return a hash of the values of our primary keys for this function.
316
317 _Accessible KEY MODE
318 Private method.
319
320 Returns undef unless "KEY" is accessible in "MODE" otherwise returns
321 "MODE" value
322
323 _PrimaryKeys
324 Return our primary keys. (Subclasses should override this, but our
325 default is that we have one primary key, named 'id'.)
326
327 _ClassAccessible
328 An older way to specify fields attributes in a derived class. (The
329 current preferred method is by overriding "Schema"; if you do this and
330 don't override "_ClassAccessible", the module will generate an
331 appropriate "_ClassAccessible" based on your "Schema".)
332
333 Here's an example declaration:
334
335 sub _ClassAccessible {
336 {
337 Tofu => { 'read'=>1, 'write'=>1 },
338 Maz => { 'auto'=>1, },
339 Roo => { 'read'=>1, 'auto'=>1, 'public'=>1, },
340 };
341 }
342
343 ReadableAttributes
344 Returns an array of the attributes of this class defined as "read" => 1
345 in this class' _ClassAccessible datastructure
346
347 WritableAttributes
348 Returns an array of the attributes of this class defined as "write" =>
349 1 in this class' _ClassAccessible datastructure
350
351 __Value
352 Takes a field name and returns that field's value. Subclasses should
353 never override __Value.
354
355 _Value
356 _Value takes a single column name and returns that column's value for
357 this row. Subclasses can override _Value to insert custom access
358 control.
359
360 _Set
361 _Set takes a single column name and a single unquoted value. It
362 updates both the in-memory value of this column and the in-database
363 copy. Subclasses can override _Set to insert custom access control.
364
365 _Canonicalize PARAMHASH
366 This routine massages an input value (VALUE) for FIELD into something
367 that's going to be acceptable.
368
369 Takes
370
371 FIELD
372 VALUE
373 FUNCTION
374
375 Takes:
376
377 FIELD
378 VALUE
379 FUNCTION
380
381 Returns a replacement VALUE.
382
383 _Validate FIELD VALUE
384 Validate that VALUE will be an acceptable value for FIELD.
385
386 Currently, this routine does nothing whatsoever.
387
388 If it succeeds (which is always the case right now), returns true.
389 Otherwise returns false.
390
391 TruncateValue KEY VALUE
392 Truncate a value that's about to be set so that it will fit inside the
393 database' s idea of how big the column is.
394
395 (Actually, it looks at SearchBuilder's concept of the database, not
396 directly into the db).
397
398 _Object
399 _Object takes a single column name and an array reference. It creates
400 new object instance of class specified in _ClassAccessable structure
401 and calls LoadById on recently created object with the current column
402 value as argument. It uses the array reference as the object
403 constructor's arguments. Subclasses can override _Object to insert
404 custom access control or define default constructor arguments.
405
406 Note that if you are using a "Schema" with a "REFERENCES" field, this
407 is unnecessary: the method to access the column's value will
408 automatically turn it into the appropriate object.
409
410 Load
411 Takes a single argument, $id. Calls LoadById to retrieve the row whose
412 primary key is $id
413
414 LoadByCol
415 Takes two arguments, a column and a value. The column can be any table
416 column which contains unique values. Behavior when using a non-unique
417 value is undefined
418
419 LoadByCols
420 Takes a hash of columns and values. Loads the first record that matches
421 all keys.
422
423 The hash's keys are the columns to look at.
424
425 The hash's values are either: scalar values to look for OR has
426 references which contain 'operator' and 'value'
427
428 LoadById
429 Loads a record by its primary key. Your record class must define a
430 single primary key column.
431
432 LoadByPrimaryKeys
433 Like LoadById with basic support for compound primary keys.
434
435 LoadFromHash
436 Takes a hashref, such as created by DBIx::SearchBuilder and populates
437 this record's loaded values hash.
438
439 _LoadFromSQL QUERYSTRING @BIND_VALUES
440 Load a record as the result of an SQL statement
441
442 Create
443 Takes an array of key-value pairs and drops any keys that aren't known
444 as columns for this recordtype
445
446 Delete
447 Delete this record from the database. On failure return a
448 Class::ReturnValue with the error. On success, return 1;
449
450 Table
451 Returns or sets the name of the current Table
452
453 QuotedTableName
454 Returns the name of current Table, or the table provided as an
455 argument, including any quoting
456 based on yje Handle's QuoteTableNames flag and driver method.
457
458 _Handle
459 Returns or sets the current DBIx::SearchBuilder::Handle object
460
462 Jesse Vincent, <jesse@fsck.com>
463
464 Enhancements by Ivan Kohler, <ivan-rt@420.am>
465
466 Docs by Matt Knopp <mhat@netlag.com>
467
469 DBIx::SearchBuilder
470
471
472
473perl v5.32.1 2021-04-27 DBIx::SearchBuilder::Record(3)