NAME
Win32::ASP::DBRecordGroup - an abstract parent class for representing groups of database records
SYNOPSIS
DESCRIPTION
The main purpose of Win32::ASP::DBRecordGroup
is to be subclassed. It implements a generic set of default behavior for the purpose of reading a group of records from a table, displaying that group of records in an HTML table, and allowing edits to that group if applicable. All Win32::ASP::DBRecordGroup
classes rely upon a Win32::ASP::DBRecord
class that implements the underlying record.
Internal Data Structure
The internal data structure of a instance of Win32::ASP::DBRecordGroup
consists of the following elements, all optional:
- orig
-
This is a reference to an array of DBRecord objects storing data read from the database.
- edit
-
This is a reference to an array of DBRecord objects storing the currently modified data.
Class Methods
Class methods were used to implement access to class properties. Since Perl doesn't enforce a distinction between class and instance methods, these methods can be called on both class names and on instances of the class, which ends up being incredibly useful. I strongly recommend against ever calling these methods using subroutine notation (i.e. &_DB
or &_PRIMARY_KEY
). Perl methods execute in the namespace in which they were defined, which means that if you further subclass and define a new implementation of those methods, any methods you don't override that were in the parent class will call the parent class's versions of those methods. That's bad. Always call these methods with the arrow notation and you'll be safe.
Mandatory Class Methods
These class methods will be overridden in every child class.
- _DB
-
The
_DB
method should return theWin32::ASP::DB
(or subclass there-of) object that is used for database access. A frequent implementation looks like this:sub _DB { return $main::TheDB; }
- _TYPE
-
The
_TYPE
method should return the name of theWin32::ASP::DBRecord
subclass that implements the underlying records for this DBRecordGroup object. - _QUERY_METAS
-
The
_QUERY_METAS
method should return a reference to a hash of subroutines that implement more complicated querying behavior. The subroutines will be passed the appropriate query specification and should return legal SQL for inclusion within a query. Of note, for performance reasons the method is usually implemented like so:sub _QUERY_METAS { return $MyStuff::MyRecordGroup::query_metas; } $MyStuff::MyRecordGroup::query_metas = { Status => sub { my($values) = @_; $values or return; return "Status LIKE '[$values]'"; }, };
The above
Status
query_meta presumes a single character status field and that the passed value indicates a list of desired status values. For instance, the status values might beN
for new records,P
for in process records, andF
for finished records. Using the above query_meta, a user could query forStatus=NP
, which would indicate they desired new and in process records. They could get the same results by querying for!F
.Note that there is a security hole in the above code - if a user queries for
Status=N] GO do_something_ugly_here
, they will effectively "jump" out of the LIKE statement and may be able to execute arbitrary SQL code. Defending against this possibility is left as an excercise for the reader.
Optional Class Methods
These class methods can be overriden in a child class.
- _MIN_COUNT
-
The
_MIN_COUNT
method defines the minimum number of records to display when allowing the user to edit a group of records. - _NEW_COUNT
-
The
_NEW_COUNT
method defines the minimum number of blank records to display when allowing the user to edit a group of records.
Instance Methods
new
This is a basic new
method. It simply creates an anonymous hash and returns a reference. The new
method is not responsible for reading data or anything else. Just creating a new record group object. You will probably not need to override this method.
query
This is the heart of the DBRecordGroup class. The method is passed three parameters: a reference to a hash of constraints, a string specifying how to order the results, and a string specifying a list of columns to retrieve.
The hash of constraints should be indexed on the field name (or query_meta name). If the index references a query_meta, the value will be passed to the query_meta subroutine. If the index doesn't reference a query_meta, the field will be tested for equality with the specified value. The specified value will be formatted by the field's as_sql
method before being included in the SQL. All of the constraints will be ANDed together to form the WHERE
clause in the SQL.
The order string should be a comma separated list of field names. Bare field names will be sorted in ascending order; field names preceded by a minus sign will be sorted in descending order.
The columns string should be one of three things: empty, an asterisk, or a comma separated list of field names. If the string is absent or an asterisk, the query will retrieve all the columns If a comma separated list is specified, the query will only retrieve those columns. The advantage of this is that queries can be optimized to return only the information that will be displayed to the user. Keep in mind, however, that if the DBRecord object requires specific fields in order to make determinations about viewability or the like, those columns need to be specified in the column list. As a result, query
is frequently overriden to automatically append those columns to the column list before call SUPER::query
.
After setting up the SQL for the query, query
calls exec_sql
on the appropriate Win32::ASP::DB object (determined by calling $self->_DB
). It then iterates over the result set returned, creating new DBRecord objects of the appropriate class and calling _read
on them. The call to _read
is wrapped in a try
block - if the user doesn't have rights to view the record, _read
will throw an exception. That exception will be trapped and the record won't be be appended to the array of DBRecord objects.
Another common modification to query
involves adding constraints to all queries to explicitly call query_metas that are responsible for ascertaining viewability. This can greatly improve performance - if the user asks for every record in the system, the query handles the weeding out of those records that are not viewable, rather than reading the data and letting _read
throw an exception. Again, this can be easily handled by overriding the method and then calling SUPER::query
.
query_deep
index_hash
insert
delete
should_update
update
edit
merge_inner
split_inner
post
add_extras
set_prop
gen_table
get_QS_constraints
make_QS_constraints
debug_dump
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 176:
=back without =over