NAME
CAM::SQLObject - Object parent class for SQL delegates
LICENSE
Copyright 2005 Clotho Advanced Media, Inc., <cpan@clotho.com>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
COMPARISON
This is one of many modules that tries to apply an Object-Oriented front on SQL database content. The primary thing that's special about it is that the helper module, CAM::SQLManager, has a slick way of encapsulating the SQL so your Perl code has no SQL in it.
The advantage of externalizing your SQL is like the advantage of externalizing HTML content via templating systems. You can work on them separately and you don't need your programmer to also be a DBA. Having the SQL be separate also lets you easily test and optimize your queries separately from the main program logic. Very handy. See CAM::SQLManager for more info.
SYNOPSIS
package Foo;
use CAM::SQLObject;
our @ISA = qw(CAM::SQLObject);
sub sqlcmd { return "foo.xml" }
sub keyName { return "foo_id" }
sub insertQueryName { return "add" }
[ ... other specific changes for this package ... ]
sub renderfoo_name {
my ($self) = @_;
return "NAME: " . $self->getfoo_name();
}
sub getfoo_name {
my ($self) = @_;
return $self->{fields}->{foo_name};
}
sub setfoo_name {
my ($self, $value) = @_;
$self->{fields}->{foo_name} = $value;
}
sub setfoo_id {
my ($self, $value) = @_;
$self->{fields}->{foo_id} = $value;
$self->{keyvalue} = $value;
}
DESCRIPTION
This class is not meant to be instantiated directly. Instead, it is intended to be the superclass of real database frontend objects. Those objects will typically add several get<field> and set<field> routines to act as accessors and mutators for the database fields.
CLASS METHODS
- AUTOLOAD
-
If you call a method on this class that does not exist, the AUTOLOAD function takes over. The CAM::SQLObject autoloader handles a few specialized dynamic methods:
If that method name looks like one of:
$obj->set<field>(...) $obj->get<field>(...) $obj->render<field>(...)
then AUTOLOAD implements the appropriate call of the following:
$obj->set(<field>, ...) $obj->get(<field>, ...) $obj->render(<field>, ...)
If a subclass overrides a particular get, set, or render method, then that one will be used. The SYNOPSIS above shows how to write an override method.
Special case: If the field starts with
Table_
, then that is replaced with the tableName() value plus and underscore. If the class does not define the table name, then the method will fail and a warning will be emitted.If the method name looks like:
$pkg->retrieve<query>(...)
then AUTOLOAD implements a call to:
$pkg->retrieve(<query>, ...)
which can be overloaded in ways similar to the object methods above.
Note that get(), set() and render() are instance methods while retrieve() is a class method.
- new
-
Creates a new stub object.
The following documenation is DEPRECATED as of version 0.50. New subclasses should instead override individual functions instead of changing the new() method.
Subclasses should consider overriding the following fields, in order of priority:
Name Default Purpose ---- ------- ------- sqlcmd undef location of the SQL templates (see SQLManager) keyname undef name of the primary key field (needed for save()) tablename undef name of the SQL table (needed for fieldNames()) update_name "update" name of query in sqlcmd (needed for save()) insert_name "insert" name of query in sqlcmd (needed for save()) delete_name "delete" name of query in sqlcmd keygen undef which technique should be used to get new keys keygen_data undef info needed for how to generate keys
See newkey() below for more information on keygen and keygen_data.
- getMgr
-
Retrieves a CAM::SQLManager instance for this class. This can be called as a class method or as an instance method.
- setDBH DBH
-
Tells the SQL manager to use the specified database handle for all interaction with objects of this class. If setDBH() is not called, the default database handle from CAM::SQLManager is used. This method must be called before any objects are instantiated.
- retrieveByKey KEYVALUE
-
Class method to retrieve a single object for the specified key. Objects with complicated SQL representations should override this method.
This method executes an implicit query that looks like:
select * from <table> where <keyname>=<keyvalue>
- retrieve QUERYNAME, [KEY => VALUE, KEY => VALUE, ...]
-
Generic class method to retrieve objects from a specified query. The extra parameters are passed as bind variables to the query. This is pretty much just a handy wrapper around the CAM::SQLManager method retrieveObjects().
In scalar context, just the first object will be returned. In array context, all of the matching objects are returned.
Recommended usage: Use this via the autoloaded method retrieve<queryname>(). For example, if you have a query "GetOldClients" which takes "year" as a query parameter, then call it like:
@clients = CAM::SQLObject->retrieveGetOldClients(year => "1998");
instead of
@clients = CAM::SQLObject->retrieve("GetOldClients", year => "1998");
The former example has the advantage that subclasses can easily override it to do different and interesting things.
OVERRIDE METHODS
The following methods are all class or instance methods. Subclasses are encouraged to override them for more specific functionality.
- sqlcmd
-
This class or instance method returns the name of the XML file used to hold SQL commands. Subclasses have the following options:
- override the new() method to explicitly set the sqlcmd parameter (this is the old style and is deprecated, since it did not work as a class method) - override the sqlcmd() method to specify the file (recommended for unusual file names) - let CAM::SQLObject try to find the file
With the latter option, this method will search in the following places for the sqlcmd file (in this order):
- use the package name, replacing '::' with '/' (e.g. Foo::Bar becomes $sqldir/Foo/Bar.xml) - use the trailing component of the package name (e.g. Foo::Bar becomes $sqldir/Bar.xml)
Subclasses which are happy to use these default file names should not override this method, or change the sqlcmd proprty of any instances. Otherwise, this method should either be overridden by all subclasses (which is the recommended style), or those subclasses should override the new() method to set the sqlcmd field explicitly (which is the previous, now deprecated, style).
Here is a simple example override method:
sub sqlcmd { return "foobar.xml"; }
- keyName
-
Returns the name of the primary key field (needed for save() and retrieveByKey()). This default method returns the primary key name from the SQL Manager's XML file, or undef.
- tableName
-
Returns the name of the SQL table (needed for fieldNames() and retrieveByKey()). This default method returns the table name from the SQL Manager's XML file, or undef.
- updateQueryName
-
Returns the name of the default query to do record updates in SQL XML file (needed for save()). This default method returns "update".
- insertQueryName
-
Returns the name of the default query to do record inserts in SQL XML file (needed for save()). This default method returns "insert".
- deleteQueryName
-
Returns the name of the default query to do record deletes in SQL XML file. This default method returns "delete".
- keygenAlgorithm
-
Returns the name of the algorithm that the newkey() method uses to generate its keys. This default method returns undef. See newkey() for more details.
- keygenData
-
Returns the ancillary data needed to support the algorithm specified by keygenAlgorithm(). The contents of this data depend on the algorithm chosen. This default method returns undef. See newkey() for more details.
INSTANCE METHODS
- get_key
-
Retrieve the object key.
- set_key
-
Change the object key.
- get FIELD
-
Retrieve a field. This method is intended for internal use only, i.e. from AUTOLOAD or from subclass accessors. An example of the latter:
sub getFOO_ID { my $self = shift; return $self->get("FOO_ID") + $ID_offset; }
- render FIELD
-
Retrieve a field, with output formatting applied. This method is intended for internal use only, i.e. from AUTOLOAD or from subclass accessors. An example of the latter:
sub renderFOO_ID { my $self = shift; return "ID " . &html_escape($self->render("FOO_ID")); }
- set FIELD, VALUE [FIELD, VALUE, ...]
-
Assign a field. This method is intended for internal use only, i.e. from AUTOLOAD or from subclass mutators. An example of the latter:
sub setFOO_ID { my $self = shift; my $value = shift; return $self->set("FOO_ID", $value - $ID_offset); }
- fill QUERYNAME
-
Given an object with partially filled fields, run an SQL query that will retrieve more fields. The query should be designed to return just one row. If any command in the query does not return exactly one row, the command will fail.
Example:
$obj = new ACME::Towel; $obj->set_serial_number("0123456789"); $obj->fill("get_towel_by_sn");
- fieldNames
- fieldNames TABLENAME
-
Retrieves an array of the names of the fields in the primary SQL table. If TABLENAME is omitted, this applies to the primary table (this only works if the subclass sets the $self->{tablename} property). This function uses some MySQL specific directives...
(Note: this is a kludge in that it runs the "describe <table>" SQL directly, instead of going through the SQLManager's XML interface)
- query
-
Run the specified query against this object. All bound SQL parameters will be read from this object. This is applicable to both SELECT as well as UPDATE/INSERT queries. While usually called as an instance method, this can be called as a class method if all you are interested in is the side effects of the SQL query instead of the data.
NOTE! This method does not retrieve the results of SELECT statements into the object. If you wish to apply SELECT data to your objects, use either fill() or retrieve().
- save
-
Either update or insert this object into the database. The keyname field must be set so this function can figure out whether to update or insert.
- update
-
Run the default update SQL template. This function is usually just called from the save() function.
- insert
-
Run the default insert SQL template. This function is usually just called from the save() function.
- delete
-
Run the default delete SQL template.
- getAllFields
- allFields <deprecated>
-
Returns a hash of all the fields, all retrieved via the accessor functions. "allFields" is the old name for this function, and is here for backward compatibility only.
- renderAllFields
-
Returns a hash of all the fields, retrieved via the render functions.
- newkey
- newkey KEYGEN, KEYGENDATA
-
Create a new, unique key. Note that this key is NOT added to the object. This is a wrapper for several different key generation techniques. The following techniques are provided:
- keygen = <reference to function>, keygen_data = <anything>
-
The specified function is called with keygen_data as its argument. This function should return the new key.
- keygen = query, keygen_data = 'queryname'
-
The key generation SQL is part of the SQL command template. <queryname> is run via SQLManager.
- keygen = insertcountertable, keygen_data = 'table.keycol,randcol'
-
Insert into a counter table and retrieve the resulting key. This technique uses a random number to distinguish between concurrent inserts. This technique does not lock the counter table. This technique calls srand() and rand(). Note: this technique assumes that the keycolumn is an autoincrementing column that des not backtrack upon deletes.
- keygen = lockcountertable, keygen_data = 'table.keycol'
-
Lock the counter table, add one to the counter, retrieve the counter, unlock the counter table.
- keygen = mysqlcountertable, keygen_data = 'table.keycol'
-
Add one to the counter and use MySQL's atomic retrieval to return the new value of that counter. This technique does not lock the counter table.
- keygen = maxcountertable, keygen_data = 'table.keycol'
-
Find the maximum value in the specified column, then add one to get the new key. This does not lock, so you may want to lock manually.
AUTHOR
Clotho Advanced Media Inc., cpan@clotho.com
Primary developer: Chris Dolan
SEE ALSO
CAM::SQLManager