################################################################################ # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project # $Id$ ################################################################################ package WeBWorK::DB; =head1 NAME WeBWorK::DB - interface with the WeBWorK databases. =head1 SYNOPSIS my $db = WeBWorK::DB->new($courseEnvironment); my @userIDs = $db->listUsers(); my $Sam = $db->{user}->{record}->new(); $Sam->user_id("sammy"); $Sam->first_name("Sam"); $Sam->last_name("Hathaway"); # etc. $db->addUser($User); my $Dennis = $db->getUser("dennis"); $Dennis->status("C"); $db->putUser->($Dennis); $db->deleteUser("sammy"); =head1 DESCRIPTION WeBWorK::DB provides a consistent interface to a number of database backends. Access and modification functions are provided for each logical table used by the webwork system. The particular backend ("schema" and "driver"), record class, data source, and additional parameters are specified by the C<%dbLayout> hash in the course environment. =head1 ARCHITECTURE The new database system uses a three-tier architecture to insulate each layer from the adjacent layers. =head2 Top Layer: DB The top layer of the architecture is the DB module. It provides the methods listed below, and uses schema modules (via tables) to implement those methods. / new* list* exists* add* get* put* delete* \ <- api +------------------------------------------------------------------+ | DB | +------------------------------------------------------------------+ \ password permission key user set set_user problem problem_user / <- tables =head2 Middle Layer: Schemas The middle layer of the architecture is provided by one or more schema modules. They are called "schema" modules because they control the structure of the data for a table. This includes odd things like the way multiple tables are encoded in a single hash in the WW1Hash schema, and the encoding scheme used. The schema modules provide an API that matches the requirements of the DB layer, on a per-table basis. Each schema module has a style that determines which drivers it can interface with. For example, WW1Hash is a "hash" style schema. SQL is a "dbi" style schema. =head3 Examples Both WeBWorK 1.x and 2.x courses use: / password permission key \ / user \ <- tables provided +-----------------------------+ +----------------+ | Auth1Hash | | Classlist1Hash | +-----------------------------+ +----------------+ \ hash / \ hash / <- driver style required WeBWorK 1.x courses also use: / set_user problem_user \ / set problem \ +-------------------------+ +---------------------+ | WW1Hash | | GlobalTableEmulator | +-------------------------+ +---------------------+ \ hash / \ null / The GlobalTableEmulator schema emulates the global set and problem tables using data from the set_user and problem_user tables. WeBWorK 2.x courses also use: / set set_user problem problem_user \ +-------------------------------------+ | WW2Hash | +-------------------------------------+ \ hash / =head2 Bottom Layer: Drivers Driver modules implement a style for a schema. They provide physical access to a data source containing the data for a table. The style of a driver determines what methods it provides. All drivers provide C and C methods. A hash style driver provides a C method which returns the tied hash. A dbi style driver provides a C method which returns the DBI handle. =head3 Examples / hash \ / hash \ / hash \ <- style +--------+ +--------+ +--------+ | DB | | GDBM | | DB3 | +--------+ +--------+ +--------+ / dbi \ / ldap \ +-------+ +--------+ | SQL | | LDAP | +-------+ +--------+ =head2 Record Types In C<%dblayout>, each table is assigned a record class, used for passing complete records to and from the database. The default record classes are subclasses of the WeBWorK::DB::Record class, and are named as follows: User, Password, PermissionLevel, Key, Set, UserSet, Problem, UserProblem. In the following documentation, a reference the the record class for a table means the record class currently defined for that table in C<%dbLayout>. =cut use strict; use warnings; use Carp; use Data::Dumper; use WeBWorK::Utils qw(runtime_use); ################################################################################ # constructor ################################################################################ =head1 CONSTRUCTOR =over =item new($ce) The C method creates a DB object and brings up the underlying schema/driver structure according to the C<%dbLayout> hash in C<$ce>, a WeBWorK::CourseEnvironment object. =back =head2 C<%dbLayout> Format The C<%dbLayout> hash consists of items keyed by table names. The value of each item is a reference to a hash containing the following items: =over =item record The name of a perl module to use for representing the data in a record. =item schema The name of a perl module to use for access to the table. =item driver The name of a perl module to use for access to the data source. =item source The location of the data source that should be used by the driver module. Depending on the driver, this may be a path, a url, or a DBI spec. =item params A reference to a hash containing extra information needed by the schema. Some schemas require parameters, some do not. Consult the documentation for the schema in question. =back For each table defined in C<%dbLayout>, C loads the record, schema, and driver modules. It the schema module's C method lists the current table (or contains the string "*") and the output of the schema and driver modules' C