The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
	<TITLE></TITLE>
	<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.1  (Win32)">
	<META NAME="AUTHOR" CONTENT="Nathan Goodman">
	<META NAME="CREATED" CONTENT="20041204;8294237">
	<META NAME="CHANGEDBY" CONTENT="Nathan Goodman">
	<META NAME="CHANGED" CONTENT="20041230;12121823">
	<STYLE>
	<!--
		@page { size: 8.5in 11in }
		TD P { margin-bottom: 0.08in; font-size: 10pt; line-height: 0.14in }
		H1 { margin-top: 0.22in; margin-bottom: 0.08in }
		H1.western { font-family: "Times New Roman", serif; font-size: 10pt }
		P { margin-bottom: 0.14in; font-size: 10pt; line-height: 0.14in }
		P.code-western { margin-bottom: 0in; font-family: "Courier New", monospace; font-size: 10pt; line-height: 100% }
		P.code-cjk { margin-bottom: 0in; font-size: 10pt; line-height: 100% }
		P.code-ctl { margin-bottom: 0in; font-size: 10pt; line-height: 100% }
		P.row-heading-western { font-size: 10pt; font-weight: bold }
		P.row-heading-cjk { font-size: 10pt }
		P.row-heading-ctl { font-size: 10pt }
		H2 { text-decoration: underline }
		H2.western { font-size: 10pt; font-weight: medium }
		TH P { margin-bottom: 0.08in; font-size: 10pt; line-height: 0.14in }
	-->
	</STYLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<H1 CLASS="western">NAME</H1>
<P STYLE="margin-bottom: 0.2in">Class::AutoDB - Almost automatic
object persistence -- MySQL only for now</P>
<H1 CLASS="western">SYNOPSIS</H1>
<P>This class works closely with Class::AutoClass to provide almost
transparent object persistence.</P>
<P><U>Define class that that uses AutoDB</U></P>
<P>Person class with attributes 'name', 'sex', 'hobbies', and
'friends', where 'friends' is a list of Persons.</P>
<PRE>package Person;
use Class::AutoClass;
@ISA=qw(Class::AutoClass);
  
@AUTO_ATTRIBUTES=qw(name sex friends);
%AUTODB=
  (-collection=&gt;'Person',
   -keys=&gt;qq(name string, sex string, friends list(object)));
Class::AutoClass::declare(__PACKAGE__);</PRE><P>
<U>Store new objects</U></P>
<PRE>use Class::AutoDB;
use Person;
my $autodb=new Class::AutoDB(-database=&gt;'test');
my $joe=new Person(-name=&gt;'Joe',-sex=&gt;'male');
my $mary=new Person(-name=&gt;'Mary',-sex=&gt;'female');
my $bill=new Person(-name=&gt;'Bill',-sex=&gt;'male');
# Set up friends lists
$joe-&gt;friends([$mary,$bill]);
$mary-&gt;friends([$joe,$bill]);
$bill-&gt;friends([$joe,$mary]);
$autodb-&gt;put_objects;           # store objects in database
</PRE><P>
<U>Retrieve existing objects</U></P>
<PRE>use Class::AutoDB;
use Person;
my $autodb=new Class::AutoDB(-database=&gt;'test');

my $cursor=$autodb-&gt;find(-collection=&gt;'Person',-name=&gt;'Joe'); # run query
print &quot;Number of Joe's in database: &quot;,$cursor-&gt;count,&quot;\n&quot;;
while (my $joe=$cursor-&gt;get_next) {                # loop getting objects
  # $joe is a Person object -- do what you want with it
  my $friends=$joe-&gt;friends;
  for my $friend (@$friends) {
    my $friend_name=$friend-&gt;name;
    print &quot;Joe's friend is named $friend_name\n&quot;;
  }
}</PRE><P>
<SPAN STYLE="text-decoration: none">-- OR -- </SPAN><U>Get data in
one step rather than via loop</U></P>
<PRE>use Class::AutoDB;
use Person;
my $autodb=new Class::AutoDB(-database=&gt;'test');
my $cursor=$autodb-&gt;find(-collection=&gt;'Person',-name=&gt;'Joe');
my @joes=$cursor-&gt;get;</PRE><P>
<SPAN STYLE="text-decoration: none">-- OR &ndash; </SPAN><U>Run query
and get data in one step</U></P>
<PRE>use Class::AutoDB;
use Person;
my $autodb=new Class::AutoDB(-database=&gt;'test');
my @joes=$autodb-&gt;get(-collection=&gt;'Person',-name=&gt;'Joe');</PRE><P>
<FONT COLOR="#ff0000"><U><SPAN STYLE="background: transparent">[not
yet implemented: Delete existing objects</SPAN></U></FONT></P>
<PRE><FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">use Class::AutoDB;</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">use Person;</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">my $autodb=new Class::AutoDB(-database=&gt;'test');</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">my $cursor=$autodb-&gt;find(-collection=&gt;'Person',-name=&gt;'Joe');</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">while (my $joe=$cursor-&gt;get_next) { </SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">  $autodb-&gt;del($joe);</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">}</SPAN></FONT>
<FONT COLOR="#ff0000"><SPAN STYLE="background: transparent">]</SPAN></FONT></PRE><H1 CLASS="western">
DESCRIPTION</H1>
<P>This class implements a simple object persistence mechanism. It is
designed to work with Class::AutoClass. 
</P>
<H2 CLASS="western">Persistence model</H2>
<P>This is how you're supposed to imagine the system works. The
section on <U>Current Design</U> explains how it really works at
present.</P>
<P>Objects are stored in <I>collections</I>. Each collection has any
number of search keys, which you can think of as attributes of an
object or columns of a relational table. You can search for objects
in the collection by specifying values of search keys. For example</P>
<P><FONT FACE="Courier New, monospace">my
$cursor=$autodb-&gt;find(-collection=&gt;'Person',-name=&gt;'Joe');</FONT></P>
<P>finds all objects in the 'Person' collection whose 'name' key is
'Joe'. If you specify multiple search keys, the values are ANDed.</P>
<P><FONT COLOR="#ff0000">[not yet implemented: The 'find' method also
allows almost raw SQL queries with the caveat that these are very
closely tied to the implementation and will not be portable if we
ever change the implementation.]</FONT></P>
<P>A collection can contain objects from many different classes.
(This is Perl after all -- what else would you expect ??!!) 
</P>
<P><FONT COLOR="#ff0000">[not yet implemented: To limit a search to
objects of a specific class, you can pass a 'class' parameter to
find. In fact, you can search for objects of a given class
independent of the collection by specifying a 'class' parameter
without a 'collection'.]</FONT></P>
<P><FONT COLOR="#ff0000">[not yet implemented: When you create an
object, the system automatically stores it in the database at an
'appropriate' time, presently just before Perl destroys the in-memory
copy of the object. You can also store objects sooner. When you
update an object, it gets marked as such, and is likewise
automatically updated in the database. Again, you can do the update
manually if you prefer.]</FONT></P>
<P>You can store specific objects in the database using the 'put'
method on an object or store all objects using the 'put_objects'
method on AutoDB. <FONT COLOR="#ff0000">[not yet implemented:
'put_objects' consults the put_policy to decide which objects to
store.]</FONT></P>
<PRE>$object-&gt;put;            # store one object
<FONT FACE="Courier New, monospace">$autodb-&gt;put_objects;    # store all objects</FONT></PRE><H2 CLASS="western">
Set up classes to use AutoDB</H2>
<P>To use the mechanism, you define the <FONT FACE="Courier New, monospace">%AUTODB</FONT>
variable in your AutoClass definition. See Class::AutoClass. If you
do not set <FONT FACE="Courier New, monospace">%AUTODB</FONT>, or set
it to undef or (), auto-persistence is turned off for your class.</P>
<P><FONT COLOR="#ff0000">[Not yet implemented: In the simplest case,
you can simply set</FONT></P>
<P><FONT COLOR="#ff0000"><FONT FACE="Courier New, monospace">%AUTODB=(1);</FONT></FONT></P>
<P><FONT COLOR="#ff0000">This will cause your class to be persistent,
using the default collection name and without any search keys.] </FONT>
</P>
<P>More typically, you set <FONT FACE="Courier New, monospace">%AUTODB</FONT>
to a HASH of the form</P>
<PRE>  %AUTODB=(
    -collection=&gt;'Person', 
    -keys=&gt;qq(name string, sex string, friends list(object)));</PRE><P STYLE="margin-left: 0.2in">
<FONT FACE="Courier New, monospace">-collection</FONT> is the name of
the collection that will be used to store objects of your class
(collection names must be &lt;= 255 characters), and 
</P>
<P STYLE="margin-left: 0.2in"><FONT FACE="Courier New, monospace">-keys</FONT>
is a string that defines the search keys that will be defined for the
class.</P>
<P>The 'keys' string consists of attribute, data type pairs. Each
attribute is generally an attribute defined in the AutoClass
<FONT FACE="Courier New, monospace">@AUTO_ATTRIBUTES</FONT> or
<FONT FACE="Courier New, monospace">@OTHER_ATTRIBUTES</FONT>
variables. Technically, it's the name of a method that can be called
with no arguments. The value of an attribute must be a scalar, an
object reference, or an ARRAY (or list) of such values. 
</P>
<P>The data type can be 'string', 'integer', 'float', 'object', <FONT COLOR="#ff0000">[not
yet implemented: any legal MySQL column type]</FONT>, or the phrase
list(&lt;data type&gt;), eg, 'list(integer)'. These are translated
into MySQL types as follows:</P>
<TABLE WIDTH=100% BORDER=0 CELLPADDING=8 CELLSPACING=0>
	<COL WIDTH=53*>
	<COL WIDTH=203*>
	<THEAD>
		<TR>
			<TD WIDTH=21%>
				<P><B>AutoDB type</B></P>
			</TD>
			<TD WIDTH=79%>
				<P><B>MySQL type</B></P>
			</TD>
		</TR>
	</THEAD>
	<TBODY>
		<TR>
			<TD WIDTH=21%>
				<P>string</P>
			</TD>
			<TD WIDTH=79%>
				<P>longtext</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=21%>
				<P>integer</P>
			</TD>
			<TD WIDTH=79%>
				<P>int</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=21%>
				<P>float</P>
			</TD>
			<TD WIDTH=79%>
				<P>double</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=21%>
				<P>object</P>
			</TD>
			<TD WIDTH=79%>
				<P>bigint unsigned</P>
			</TD>
		</TR>
	</TBODY>
</TABLE>
<P>The 'keys' parameter can also be an array of attribute names, eg,</P>
<P><FONT FACE="Courier New, monospace">-keys=&gt;[qw(name sex)]</FONT></P>
<P>in which case the data type of each attribute is assumed to be
'string'. This works in many cases even if the data is really
numeric.</P>
<P>The types 'object' and 'list(object)' only work on objects whose
persistence is managed by our Persistence mechanisms.</P>
<P>The 'collection' value may also be an array of collection names
(and may be called 'collections') in which case the object is stored
in all the collections.</P>
<P>A subclass need not define %AUTODB, but may instead rely on the
value set by its super-classes. If the subclass does define %AUTODB,
its values are 'added' to those of its super-classes. Thus, if the
suclass uses a different collection than its super-class, the object
is stored in both. It is an error for a subclass to define the type
of a search key differently than its super-classes. It is also an
error for a subclass to inherit a search key from multiple
super-classes with different types We hope this situation is rare!</P>
<P>Technically, <FONT FACE="Courier New, monospace">%AUTODB</FONT> is
a parameter list for the register method of Class::AutoDB. See that
method for more details. Some commonly used paramters are</P>
<P STYLE="margin-left: 0.2in"><FONT COLOR="#ff0000">[ not yet
implemented:</FONT></P>
<P STYLE="margin-left: 0.2in"><FONT COLOR="#ff0000"><FONT FACE="Courier New, monospace">-transients</FONT>:
an array of attributes that should not be stored. This is useful for
objects that contain computed values or other information of a
transient nature.</FONT></P>
<P STYLE="margin-left: 0.2in"><FONT COLOR="#ff0000"><FONT FACE="Courier New, monospace">-auto_gets</FONT>:
an array of attributes that should be automatically retrieved when
this object is retrieved. These should be attributes that refer to
other auto-persistent objects. This useful in cases where there are
attributes that are used so often that it makes sense to retrieve
them as soon as possible. ]</FONT></P>
<H2 CLASS="western">Using AutoDB in your code</H2>
<P>After setting up your classes to use AutoDB, here's how you use
the mechanism.</P>
<P>The first step is to connect your program to the database. This is
accomplished via the 'new' method. 
</P>
<P>Then you typically retrieve some number of &quot;top level&quot;
objects explcitly by running a query. This is accomplished via the
'find' and 'get' methods (there are several flavors of 'get'). Then,
you operate on objects as usual. If you touch an object that has not
yet been retrieved from the database, the system will automatically
get it for you. <FONT COLOR="#ff0000">[Not yet implemented: You can
also manually retrieve objects at any time by running 'get'.]</FONT></P>
<P><FONT COLOR="#ff0000">[Not yet implemented: You can create new
objects as usual and they will be automatically written to the
database when you're done with them. More precisely,
Class::AutoDB::Object::DESTROY writes the object to the database when
Perl determines that the in-memory representation of the object is no
longer needed. This is guaranteed to happen when the program
terminates if not before. You can also manually write objects to the
database earlier if you so desire by running the 'put' method on
them. If you override DESTROY, make sure you call
Class::AutoDB::Object::DESTROY in your method.</FONT></P>
<P><FONT COLOR="#ff0000">You can modify objects as usual and the
system will take care of writing the updates to the database, just as
it does for new objects.]</FONT></P>
<P>You can store specific objects in the database using the 'put'
method on an object or store all objects using the 'put_objects'
method on AutoDB. <FONT COLOR="#ff0000">[not yet implemented:
'put_objects' consults the put_policy to decide which objects to
store.]</FONT></P>
<PRE>$object-&gt;put;            # store one object
<FONT FACE="Courier New, monospace">$autodb-&gt;put_objects;    # store all objects</FONT></PRE><H2 CLASS="western">
Flavors of 'new', 'find', and 'get'</H2>
<P>The examples in the SYNOPSIS use variables named <FONT FACE="Courier New, monospace">$autodb</FONT>,
<FONT FACE="Courier New, monospace">$cursor</FONT>, <FONT FACE="Courier New, monospace">$joe</FONT>,
and <FONT FACE="Courier New, monospace">@joes</FONT> among others.
These names reflect the various stages of data access that arise.</P>
<P>The first step is to connect to the database. This is accomplished
by 'new'. 
</P>
<P>Next a query is sent to the database and executed. This is
typically accomplished by invoking 'find' on an AutoDB object. The
resulting object (called <FONT FACE="Courier New, monospace">$cursor
</FONT>in the SYNOPSIS) is called a 'cursor' object. A cursor
object's main purpose is to enable data access. (DBI afficionados
will recogonize that it's possible to 'prepare' a query before
executing it. This is done under the covers here.)</P>
<P>Finally data is retrieved. This is typically accomplished by
invoking 'get_next' or 'get' on a cursor object. Data can be
retrieved one object at a time (via 'get_next') or all at once (via
'get'). As a convenience, you can do the 'find' and 'get' in one
step, by invoking 'get' on an AutoDB object.</P>
<P>The query executed by 'find' can either be a simple key based
search, or <FONT COLOR="#ff0000">[not yet implemented: an almost raw,
arbitrarily complex SQL query]</FONT>. The former is specified by
providing key=&gt;value pairs as was done in the SYNOPSIS, eg,</P>
<P><FONT FACE="Courier New, monospace">$cursor=$autodb-&gt;find(-collection=&gt;'Person',-name=&gt;'Joe',-sex=&gt;'male');</FONT></P>
<P>The key=&gt;value pairs are ANDed as one would expect. The above
query retrieves all Persons whose name is Joe and sex is male.</P>
<P><FONT COLOR="#ff0000">[not yet implemented: 'find' can also be
invoked on a cursor object. The effect is to AND the new query with
the old. This only works with queries expressed as key=&gt;value
pairs, and not raw SQL, since conjoining raw SQL is a bear.]</FONT></P>
<P><FONT COLOR="#ff0000">[not yet implemented: The raw form is
specifed by providing a SQL query (as a string) that lacks the SELECT
phrase, eg,</FONT></P>
<P><FONT COLOR="#ff0000"><FONT FACE="Courier New, monospace">$cursor=$autodb-&gt;find(qq(FROM
Person WHERE name=&quot;Joe&quot; AND sex=&quot;male&quot;));</FONT></FONT></P>
<P><FONT COLOR="#ff0000">To use this form, you have to understand the
relational database schema generated by AutoDB. This is not portable
across implementations, It's main value is to write complex queries
that cannot be represented in the key=&gt;value form. For example</FONT></P>
<PRE><FONT COLOR="#ff0000">$cursor=$autodb-&gt;find(qq(FROM Person p, Person friend, Person_friends friends</FONT>
<FONT COLOR="#ff0000">			 WHERE p.name=&quot;Joe&quot; AND </FONT>
<FONT COLOR="#ff0000">			 (friend.name=&quot;Mary&quot; OR friend.name=&quot;Bill&quot;) AND</FONT>
<FONT COLOR="#ff0000">			 friends.person=p));</FONT></PRE><P>
<FONT COLOR="#ff0000">]</FONT></P>
<H2 CLASS="western">Creating and initializing the database</H2>
<P>Before you can use AutoDB, you have to create a MySQL database
that will hold your data. We do not provide a means to do this here,
since you may want to put your AutoDB data in a database that holds
other data as well. The database can be empty or not. AutoDB creates
all the tables it needs -- you need not (and should not create) these
yourself.</P>
<P><B>Important note</B>: Hereafter, the term 'database' refers to
the tables created by AutoDB. Phrases like 'create the database' or
'initialize the database' refer to these tables only, and not the
entire MySQL database that contains the AutoDB database.</P>
<P>Methods are provided to create or drop the entire database
(meaning, of course, the AutoDB database, not the MySQL database) or
individual collections.</P>
<P>AutoDB maintains a registry that describes the collections stored
in the database. Registration of collections is usually handled by
AutoClass behind the scenes as class definitions are encountered. The
system consults the registry when running queries, when writing
objects to the database, and when modifying the database schema. 
</P>
<P>When 'new' connects to the database, it reads the registry saved
from the last time AutoDB ran. It merges this with an in-memory
registry that generally reflects the currently loaded classes. 'new'
merges the registries, and stores the result for next time if the new
registry is different from the old. 
</P>
<H2 CLASS="western">Current Design</H2>
<P>Caveat: The present implementation assumes MySQL. It is unclear
how deeply this assumption affects the design.</P>
<P>Every object is stored as a BLOB constructed by Data::Dumper. The
database contains a single 'object table' for the entire database
whose schema is 
</P>
<PRE>create table _AutoDB (
    oid bigint unsigned not null,
    primary key (oid),
    object longblob
    );</PRE><P>
The oid is a unique object identifier assigned by the system. An oid
is a permanent, immutable identifier for the object.</P>
<P><FONT COLOR="#ff0000">[Not yet implemented: The name of this table
can be chosen when the database is created. '_AutoDB' is the
default.]</FONT></P>
<P>For each collection, there is one table we call the base table
that holds scalar search keys, and one table per list-valued search
keys. The name of the base table is the same as the name of the
collection; there is no way to change this at present. For our Person
example, the base table would be</P>
<PRE>create table Person (
    oid bigint unsigned not null,     --- foreign key pointing to _AutoDB
    primary key (oid),                --- also primary key here
    name longtext,
    sex longtext
    );</PRE><P>
If a Person has a significant_other (also a Person), the table would
look like this:</P>
<PRE>create table Person (
    oid bigint unsigned not null,     --- foreign key pointing to _AutoDB
    primary key (oid),                --- also primary key here
    name longtext,
    sex longtext
    significant_other bigint unsigned --- foreign key pointing to _AutoDB
    );</PRE><P>
The data types specified in the 'keys' parameter are used to define
the data types of these columns. They are also used to ensure correct
quoting of values bound into SQL queries. It is safe to use 'string'
as the data type even if the data is numeric unless you intend to run
'raw' SQL queries against the database and want to do numeric
comparisons.</P>
<P>For each list valued search key, eg, 'friends' in our example, we
need another table which (no surprise) is a classic link table. The
name is constructed by concatenating the collection name and key
name, with a '_' in between.</P>
<PRE>create table Person_friends (
    oid bigint unsigned not null,  --- foreign key pointing to _AutoDB
    friends bigint unsigned        --- foreign key pointing to _AutoDB
                                   --- (will be a Person)
    );</PRE><P>
A small detail: since the whole purpose of these tables is to enable
querying, indexes are created for each column by default.</P>
<P>When the system stores an object, it converts any object
references contained therein into the oids for those objects. In
other words, objects in the database refer to each other using oids
rather than the in-memory object references used by Perl. There is no
loss of information since an oid is a permanent, immutable identifier
for the object.</P>
<P>When an object is retrieved from the database, the system does NOT
immediately process the oids it contains. Instead, the system waits
until the program tries to access the referenced object at which
point it automatically retrieves the object from the database.
Options are provided to retrieve oids earlier.</P>
<P>If a program retrieves the same oid multiple times, the system
short circuits the database access and ensures that only one copy of
the object exists in memory at any point in time. If this weren't the
case, a program could end up with two objects representing Joe, and
an update to one would not be visible in the other. If both copies
were later stored, one update would be lost. The core of the solution
is to maintain an in-memory hash of all fetched objects (keyed by
oid). The software consults this hash when asked to retrieve an
object; if the object is already in memory, it is returned without
even going to the database.</P>
<a name="bugs_and_wishlist"></a>
<H1 CLASS="western">BUGS and WISH-LIST</H1>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=37*>
	<COL WIDTH=130*>
	<COL WIDTH=89*>
	<THEAD>
		<TR VALIGN=TOP>
			<TH WIDTH=14%>
				<P><FONT SIZE=2>Name</FONT></P>
			</TH>
			<TH WIDTH=51%>
				<P><FONT SIZE=2>Description</FONT></P>
			</TH>
			<TH WIDTH=35%>
				<P><FONT SIZE=2>Priority/When</FONT></P>
			</TH>
		</TR>
	</THEAD>
	<TBODY>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">transients</P>
			</TD>
			<TD WIDTH=51%>
				<P>Allow specification of attributes that are not stored</P>
			</TD>
			<TD WIDTH=35%>
				<P>Important. This release.</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">auto_gets 
				</P>
			</TD>
			<TD WIDTH=51%>
				<P>Allow specification of attributes that are automatically
				fetched when this object is fetched</P>
			</TD>
			<TD WIDTH=35%>
				<P>Wish-list</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">MySQL column types</P>
			</TD>
			<TD WIDTH=51%>
				<P><BR>
				</P>
			</TD>
			<TD WIDTH=35%>
				<P>Wish-list</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">Delete operation</P>
			</TD>
			<TD WIDTH=51%>
				<P><BR>
				</P>
			</TD>
			<TD WIDTH=35%>
				<P>Important. This release.</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">Dirty method</P>
			</TD>
			<TD WIDTH=51%>
				<P><BR>
				</P>
			</TD>
			<TD WIDTH=35%>
				<P>Important. This release.</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">Raw SQL</P>
			</TD>
			<TD WIDTH=51%>
				<P><BR>
				</P>
			</TD>
			<TD WIDTH=35%>
				<P>This release or next</P>
			</TD>
		</TR>
		<TR>
			<TD WIDTH=14%>
				<P CLASS="row-heading-western">General alter</P>
			</TD>
			<TD WIDTH=51%>
				<P>Allow arbitrary alterations of schema</P>
			</TD>
			<TD WIDTH=35%>
				<P>Wish-list</P>
			</TD>
		</TR>
	</TBODY>
</TABLE>
<a name="methods_and_functions"></a>
<H1 CLASS="western">METHODS and FUNCTIONS - Initialization</H1>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-before: always">
	<COL WIDTH=32*>
	<COL WIDTH=62*>
	<COL WIDTH=62*>
	<COL WIDTH=100*>
	<TR>
		<TD WIDTH=12%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<P><FONT FACE="Courier New, monospace">new</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=7 WIDTH=12%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB(-database=&gt;'test');</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB
  (-database=&gt;'test',-host=&gt;'localhost',
   -user=&gt;'nat',password=&gt;'bad_password');</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB(-database=&gt;'test',-create=&gt;1);</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB(-database=&gt;'test',-drop=&gt;1);</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB(-database=&gt;'test',-alter=&gt;1);</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB(-database=&gt;'test',-read_only=&gt;1);</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<PRE>my $autodb=new Class::AutoDB
  (-database=&gt;'test',read_only_schema=&gt;1);</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=12%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<P>Constructor.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=28 WIDTH=12%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88%>
			<P><B>Connection parameters (MySQL only, at present)</B></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-database</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Database name. No default.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-host</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Database host (or server). Defaults to localhost</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-server</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Synonym for -host</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-user</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Database username. Defaults to current operation system, more
			precisely the value of the USER environment variable</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-password</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Database user's password. Defaults to no password</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-dbd</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Name of DBD driver. Defaults to 'mysql' which is also the only
			value currently supported.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-dsn</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>DSN (data source) string in the format supported by your DBD
			driver. For MySQL, the format is &quot;dbi:driver:database_name[:other
			information]&quot;. See documentation for DBI and your DBD driver.</P>
			<P>If not supplied, this is computed by the software.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-dbh</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Connected database handle returned by DBI::connect. See DBI
			documentation.</P>
			<P>If not supplied, the software calls DBI::connect itself</P>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88%>
			<P><B>Access parameters</B></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-read_only</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P><FONT COLOR="#ff0000">[not yet implemented: If true, database
			is opened in read only mode. Implies -read_only_schema. Takes
			precedence over -create, -alter, -drop.]</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-read_only_schema</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Single option to turn off -create, -alter, -drop. If true, no
			schema changes are allowed. If false: schema changes are allowed
			as explained below.</P>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88%>
			<P><B>Schema modification parameters</B></P>
			<P>These control what schema changes will be carried out
			automatically by 'new'. It is illegal to specify more than one of
			these.</P>
			<P>When all three options are left unspecified or set to undef,
			the system adopts what we hope is a sensible default: (1) if the
			database does not exist, it is created; and (2) if the database
			exists, but some collections in the in-memory registry do not
			exist in the database, these collections are created.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=4 WIDTH=24%>
			<P CLASS="code-western">-create</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Controls whether the database may be created.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>undef</P>
		</TD>
		<TD WIDTH=39%>
			<P>See default described above</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>any true value, e.g., 1</P>
		</TD>
		<TD WIDTH=39%>
			<P>Database creation is forced: the database is created whether or
			not it exists. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>defined but false, e.g., 0</P>
		</TD>
		<TD WIDTH=39%>
			<P>Database is not created even if it does not exist. Instead an
			error is thrown if alterations are required.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=4 WIDTH=24%>
			<P CLASS="code-western">-drop</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Controls whether database is automatically dropped</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>undef</P>
		</TD>
		<TD WIDTH=39%>
			<P>See default described above</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>any true value, e.g., 1</P>
		</TD>
		<TD WIDTH=39%>
			<P>Database is dropped. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>defined but false, e.g., 0</P>
		</TD>
		<TD WIDTH=39%>
			<P>Database is not dropped An error is thrown if alterations are
			required.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=4 WIDTH=24%>
			<P CLASS="code-western">-alter</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Controls whether the schema may be altered</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>undef</P>
		</TD>
		<TD WIDTH=39%>
			<P>See default described above</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>any true value, e.g., 1</P>
		</TD>
		<TD WIDTH=39%>
			<P>Schema alterations are allowed to add new collections and new
			search keys to existing collections</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P>defined but false, e.g., 0</P>
		</TD>
		<TD WIDTH=39%>
			<P>Schema alterations are not allowed. Instead an error is thrown
			if alterations are required.</P>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=3 WIDTH=88%>
			<P><B>Miscellaneous parameters</B></P>
			<P>Most users will have no need to specify these</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-object_table</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Name of AutoDB object table. Defaults to _AutoDB</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-registry</P>
		</TD>
		<TD COLSPAN=2 WIDTH=63%>
			<P>Registry. Defaults to $Class::AutoDB::AUTO_REGISTRY. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=12%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<P>Class::AutoDB object</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=12%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD COLSPAN=3 WIDTH=88% VALIGN=TOP>
			<P>The connection parameters are just those that we find useful in
			our work. Many more are possible. If you need other parameters,
			you can construct a DSN in your code and pass that as a parameter
			or open a database handle in your code and pass that in.</P>
		</TD>
	</TR>
</TABLE>
<H1 CLASS="western">METHODS and FUNCTIONS &ndash; Simple Attributes</H1>
<P>These are methods for getting and setting the values of simple
attributes. Methods have the same name as the attribute. Some of
these should be read-only (more precisely, should only be written by
code internal to the object), but this is not enforced. 
</P>
<P>To get the value of attribute <FONT FACE="Courier New, monospace">xxx</FONT>,
just say 
</P>
<P STYLE="margin-left: 0.29in"><FONT FACE="Courier New, monospace">$xxx=$object-&gt;xxx;
</FONT>
</P>
<P>To set an attribute, say</P>
<P STYLE="margin-left: 0.29in"><FONT FACE="Courier New, monospace">$object-&gt;xxx($new_value);
</FONT>
</P>
<P>To clear it, say 
</P>
<P STYLE="margin-left: 0.31in"><FONT FACE="Courier New, monospace">$object-&gt;xxx(undef);</FONT></P>
<H2 CLASS="western">Connection attributes</H2>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">database</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Database name.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">host</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Database host (or server).</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">server</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Synonym for -host</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">user</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Database username. Defaults to current operation system, more
			precisely the value of the USER environment variable</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">password</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Database user's password. Defaults to no password</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">dbd</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Name of DBD driver. 'mysql' which is the only value currently
			supported.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">dsn</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>DSN (data source) string in the format supported by your DBD
			driver. For MySQL, the format is &quot;dbi:driver:database_name[:other
			information]&quot;. See documentation for DBI and your DBD driver.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">dbh</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Database handle returned by DBI::connect</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<H2 CLASS="western">Access attributes</H2>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">read_only</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>If true, database is opened in read only mode. Implies
			-read_only_schema. Takes precedence over -create, -alter, -drop.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">read_only_schema</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Single option to turn off -create, -alter, -drop. If true, no
			schema changes are allowed. If false: schema changes are allowed
			as explained above.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<H2 CLASS="western">Miscellaneous attributes</H2>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">object_table</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Name of AutoDB object table.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-write before connection established. Read-only after
			connection established</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">registry</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Registry</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-only.</P>
		</TD>
	</TR>
</TABLE>
<H2 CLASS="western">Query-related tributes &lt;TODO: get his right&gt;</H2>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><FONT FACE="Courier New, monospace">cursors</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>List of cursors associated with session</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Read-only.</P>
		</TD>
	</TR>
</TABLE>
<P STYLE="margin-bottom: 0in; line-height: 100%"><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=39*>
	<COL WIDTH=217*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Attribute</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western"><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Access</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
</TABLE>
<H1 CLASS="western">METHODS and FUNCTIONS &ndash; Queries and Updates</H1>
<P>These methods read or write the actual database structure. They
are only legal when connected to the database. 
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=65*>
	<COL WIDTH=153*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>find</PRE>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=2 WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$cursor=$autodb-&gt;find (-collection=&gt;'Person',
                     -name=&gt;'Joe',-sex=&gt;'male');</PRE>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$cursor=$autodb-&gt;find (-collection=&gt;'Person',
                     -query=&gt;{-name=&gt;'Joe',-sex=&gt;'male'});</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Executes a query. The query can either be a simple key based
			search, <FONT COLOR="#ff0000">[not yet implemented: or an almost
			raw, arbitrarily complex SQL query]</FONT>. The former is
			specified by providing key=&gt;value pairs as was done in the
			SYNOPSIS. The key=&gt;value pairs are ANDed as one would expect.
			The above queries retrieve all Persons whose name is Joe and sex
			is male.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=3 WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<P><FONT FACE="Courier New, monospace">-collection</FONT></P>
		</TD>
		<TD WIDTH=60% VALIGN=TOP>
			<P>Name of collection being queried</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=25%>
			<P><FONT FACE="Courier New, monospace">-query</FONT></P>
		</TD>
		<TD WIDTH=60% VALIGN=TOP>
			<P>key=&gt;value pairs. Each key must be a search key defined for
			the collection. Each value must be a single value of the correct
			type for the key. For all types except 'object', the value must be
			a scalar. For 'object', the value must be an object; the software
			extracts the object's oid and uses that to query the database.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=25%>
			<P><FONT FACE="Times New Roman, serif">Other args</FONT></P>
		</TD>
		<TD WIDTH=60% VALIGN=TOP>
			<P>Other args are interpreted as search keys</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>A cursor object which can subsequently be used to retrieve the
			results.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>If the collection has a search key named 'collection', you must
			use the second form to include it in a query.</P>
		</TD>
	</TR>
</TABLE>
<P ALIGN=LEFT><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=218*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>count</PRE>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=5 WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE><FONT FACE="Times New Roman, serif"><B>Operating on AutoDB </B></FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>$count=$autodb-&gt;count (-collection=&gt;'Person',
                     -name=&gt;'Joe',-sex=&gt;'male');</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>$count=$autodb-&gt;count (-collection=&gt;'Person',
                     -query=&gt;{-name=&gt;'Joe',-sex=&gt;'male'});</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE><FONT FACE="Times New Roman, serif"><B>Operating on Cursor</B></FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>count=$cursor-&gt;count;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>When operating on an AutoDB object, count the number of objects
			that satisfy a query. The arguments are exactly as for 'find'.</P>
			<P>When operating on a Cursor object, count the number of objects
			that satisfy the query associated with the cursor. The software
			executes a count SQL query; it does not retrieve the objects. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=85%>
			<P><FONT FACE="Times New Roman, serif">See 'find'</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>Number</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>If the collection has a search key named 'collection', you must
			use the second form to include it in a query.</P>
		</TD>
	</TR>
</TABLE>
<P ALIGN=LEFT><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=218*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>get </PRE>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=8 WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE><FONT FACE="Times New Roman, serif"><B>Operating on AutoDB </B></FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>@objects=$autodb-&gt;get (-collection=&gt;'Person',
                     -name=&gt;'Joe',-sex=&gt;'male');</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>$objects=$autodb-&gt;count (-collection=&gt;'Person',
                     -query=&gt;{-name=&gt;'Joe',-sex=&gt;'male'});</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>@objects=$autodb-&gt;count (-collection=&gt;'Person',
                     -query=&gt;{-name=&gt;'Joe',-sex=&gt;'male'});</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>$objects=$autodb-&gt;count (-collection=&gt;'Person',
                     -query=&gt;{-name=&gt;'Joe',-sex=&gt;'male'});</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE><FONT FACE="Times New Roman, serif"><B>Operating on Cursor</B></FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>$objects=$cursor-&gt;get;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=85% VALIGN=TOP>
			<PRE>@objects=$cursor-&gt;get;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>When operating on an AutoDB object, execute query and retrieve
			results. The arguments are exactly as for 'find'</P>
			<P>When operating on a Cursor object, retrieve results of query
			associated with the cursor. It is possible to mix 'get' 'get_next'
			operations. If some 'get_next' operations have been run on the
			cursor, 'get' retrieves the remaining objects.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=85%>
			<P><FONT FACE="Times New Roman, serif">See 'find'</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>ARRAY or ARRAY ref of objects depending on context.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD WIDTH=85% VALIGN=TOP>
			<P>If the collection has a search key named 'collection', you must
			use the second form to include it in a query.</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=64*>
	<COL WIDTH=154*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>get_next</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$object=$cursor-&gt;get_next;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Retrieve the next result for the cursor. The order is
			arbitrary. Returns <FONT FACE="Courier New, monospace">undef</FONT>
			if there are no more results. This allows simple while loops of
			the form shown in the SYNOPSIS to iterate over the results</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE><FONT FACE="Times New Roman, serif">none</FONT></PRE>
		</TD>
		<TD WIDTH=60%>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>object</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=64*>
	<COL WIDTH=154*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>reset</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$cursor-&gt;reset;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Re-execute query associated with the cursor. A subsequent
			get_next operation will start at the beginning.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE><FONT FACE="Times New Roman, serif">none</FONT></PRE>
		</TD>
		<TD WIDTH=60%>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Nothing</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=64*>
	<COL WIDTH=154*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>put_objects</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$autodb-&gt;put_objects;</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Store all objects in the database <FONT COLOR="#ff0000">[not
			yet implemented: subject to the put_policy. If -read_only is set ,
			this is a nop]</FONT></P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE><FONT FACE="Times New Roman, serif">none</FONT></PRE>
		</TD>
		<TD WIDTH=60%>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Nothing</P>
		</TD>
	</TR>
</TABLE>
<H1 CLASS="western">METHODS and FUNCTIONS &ndash; Manage
registrations</H1>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=37*>
	<COL WIDTH=62*>
	<COL WIDTH=157*>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<PRE><FONT FACE="Courier New, monospace">auto_register</FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<PRE>auto_register
   (-class=&gt;'Person',
    -collection=&gt;'Person',
    -keys=&gt;qq(name string, dob integer, 
              significant_other object,friends list(object)),
    -transients=&gt;[qw(age)],
    -auto_gets=&gt;[qw(significant_other)]);</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<P>Register a collection with the system. Called automatically by
			Class::AutoClass::declare as class definition are encountered. Use
			'register' method below for explicit registrations.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=6 WIDTH=14%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=24%>
			<P CLASS="code-western">-class</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Name of class being registered</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-collection</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Name of collection being registered or ARRAY ref of names</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-collections</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Synonym for -collection</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-keys</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Search keys for collection.</P>
			<P>Can be string of comma separated attribute and data type pairs,
			or ARRAY ref of attributes in which case the type is assumed to be
			'string'. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-transients</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>ARRAY ref of attributes that will not be stored.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-auto_gets</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>ARRAY ref of attributes that should be automatically retrieved
			when this object is retrieved.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<H1 CLASS="western" STYLE="font-weight: medium">Nothing</H1>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=2 WIDTH=14%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<H1 CLASS="western" STYLE="font-weight: medium">The arguments are
			passed to <FONT FACE="Courier New, monospace">Class::AutoDB::Registration::new</FONT>.
						</H1>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<P>The keys argument is a HASH ref of attribute, data type pairs.
			Each attribute is generally an attribute defined in the AutoClass
			@AUTO_ATTRIBUTES or @OTHER_ATTRIBUTES variables. (technically,
			it's the name of a method that can be called with no arguments.
			The value of an attribute must be a scalar, an object reference,
			or an ARRAY (or list) of such values.</P>
			<P>The data type can be 'string', 'integer', 'float', 'object', or
			the phrase list(&lt;data type&gt;), eg, 'list(integer)'. These can
			be abbreviated. The types 'object' and 'list(object)' only work
			for objects whose persistence is managed by AutoDB.</P>
			<P>The 'keys' parameter can also be an array of attribute names,
			eg,</P>
			<P><FONT FACE="Courier New, monospace">-keys=&gt;[qw(name sex)]</FONT></P>
			<P STYLE="font-weight: medium">in which case the data type of each
			attribute is assumed to be 'string'. This works in many cases even
			if the data is really numeric as discussed in the Persistence
			Model section above.</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=37*>
	<COL WIDTH=62*>
	<COL WIDTH=157*>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<PRE><FONT FACE="Courier New, monospace">register</FONT></PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<PRE>$autodb-&gt;register
   (-class=&gt;'Person',
    -collection=&gt;'Person',
    -keys=&gt;qq(name string, dob integer, 
              significant_other object,friends list(object)),
    -transients=&gt;[qw(age)],
    -auto_gets=&gt;[qw(significant_other)]);</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<P>Register a collection with the system. See 'auto_register'
			method above for automatic registrations.</P>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=6 WIDTH=14%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=24%>
			<P CLASS="code-western">-class</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Name of class being registered</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-collection</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Name of collection being registered or ARRAY ref of names</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-collections</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Synonym for -collection</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-keys</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>Search keys for collection.</P>
			<P>Can be string of comma separated attribute and data type pairs,
			or ARRAY ref of attributes in which case the type is assumed to be
			'string'. 
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-transients</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>ARRAY ref of attributes that will not be stored.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=24%>
			<P CLASS="code-western">-auto_gets</P>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P>ARRAY ref of attributes that should be automatically retrieved
			when this object is retrieved.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=14%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<H1 CLASS="western" STYLE="font-weight: medium">Nothing</H1>
		</TD>
	</TR>
	<TR>
		<TD ROWSPAN=2 WIDTH=14%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<H1 CLASS="western" STYLE="font-weight: medium">The arguments are
			passed to <FONT FACE="Courier New, monospace">Class::AutoDB::Registration::new</FONT>.
						</H1>
		</TD>
	</TR>
	<TR>
		<TD COLSPAN=2 WIDTH=86% VALIGN=TOP>
			<P>The keys argument is a HASH ref of attribute, data type pairs.
			Each attribute is generally an attribute defined in the AutoClass
			@AUTO_ATTRIBUTES or @OTHER_ATTRIBUTES variables. (echnically, it's
			the name of a method that can be called with no arguments. The
			value of an attribute must be a scalar, an object reference, or an
			ARRAY (or list) of such values.</P>
			<P>The data type can be 'string', 'integer', 'float', 'object', or
			the phrase list(&lt;data type&gt;), eg, 'list(integer)'. These can
			be abbreviated. The types 'object' and 'list(object)' only work
			for objects whose persistence is managed by AutoDB.</P>
			<P>The 'keys' parameter can also be an array of attribute names,
			eg,</P>
			<P><FONT FACE="Courier New, monospace">-keys=&gt;[qw(name sex)]</FONT></P>
			<P STYLE="font-weight: medium">in which case the data type of each
			attribute is assumed to be 'string'. This works in many cases even
			if the data is really numeric as discussed in the Persistence
			Model section above.</P>
		</TD>
	</TR>
</TABLE>
<H1 CLASS="western">METHODS and FUNCTIONS &ndash; Manage database
schema 
</H1>
<P>These methods read or write the actual database structure. They
are only legal when connected to the database. 
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=63*>
	<COL WIDTH=155*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>exists</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>my $bool=$autodb-&gt;exists</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Test whether the registry exists in the database</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE>none</PRE>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>0 or 1 indicate the registry does not or does exist. <FONT FACE="Courier New, monospace">undef</FONT>
			is used internally to indicate that we don't know the answer.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Notes</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>This method really only checks whether the AutoDB object table
			exists in the database. The method consults the database if it
			doesn't know and caches the result. Methods that change the answer
			(e.g., create and drop), update the cached value.</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=63*>
	<COL WIDTH=155*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>create</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western">$autodb-&gt;create</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Create AutoDB database. First, the existing AutoDB database, if
			any, is dropped. This drops the _AutoDB table and all tables used
			to implement the collections that exist in the saved registry.
			Then, the new database is created. This creates the_AutoDb table
			and all tables needed to implement the collections registered in
			the current, in-memory registry.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE>none</PRE>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Nothing</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=63*>
	<COL WIDTH=155*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>drop</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P CLASS="code-western">$autodb-&gt;drop</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Drop AutoDB database. This drops the _AutoDB table and all
			tables used to implement the collections that exist in the current
			or saved registry.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE>none</PRE>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Nothing</P>
		</TD>
	</TR>
</TABLE>
<P><BR><BR>
</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
	<COL WIDTH=38*>
	<COL WIDTH=63*>
	<COL WIDTH=155*>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Title</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>alter</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Usage</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<PRE>$autodb-&gt;alter</PRE>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Function</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Alter AutoDB to reflect differences between the current,
			in-memory registry and the saved registry. The only alterations
			that are allowed are expansions. New collections can be created
			and new search keys can be added to existing collections.</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Args</P>
		</TD>
		<TD WIDTH=25%>
			<PRE>none</PRE>
		</TD>
		<TD WIDTH=61% VALIGN=TOP>
			<P><BR>
			</P>
		</TD>
	</TR>
	<TR>
		<TD WIDTH=15%>
			<P CLASS="row-heading-western">Returns</P>
		</TD>
		<TD COLSPAN=2 WIDTH=85% VALIGN=TOP>
			<P>Nothing</P>
		</TD>
	</TR>
</TABLE>
<H1 CLASS="western"><BR><BR>
</H1>
</BODY>
</HTML>