From: Sam H. v. a. <we...@ma...> - 2005-07-26 16:33:42
|
Log Message: ----------- first steps towards an SQL-specific version of DB.pm. I'm not quite sure=20 how I'm going to proceed on this. We tried too much abstraction, but I=20 don't want to end up with not enough abstraction, either. Added Files: ----------- webwork2/lib/WeBWorK/DB: SQL.pm Revision Data ------------- --- /dev/null +++ lib/WeBWorK/DB/SQL.pm @@ -0,0 +1,244 @@ +########################################################################= ######## +# WeBWorK Online Homework Delivery System +# Copyright =A9 2000-2003 The WeBWorK Project, http://openwebwork.sf.net= / +# $CVSHeader: webwork2/lib/WeBWorK/DB/SQL.pm,v 1.1 2005/07/26 16:35:10 s= h002i Exp $ +#=20 +# This program is free software; you can redistribute it and/or modify i= t under +# the terms of either: (a) the GNU General Public License as published b= y the +# Free Software Foundation; either version 2, or (at your option) any la= ter +# version, or (b) the "Artistic License" which comes with this package. +#=20 +# This program is distributed in the hope that it will be useful, but WI= THOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or = FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License o= r the +# Artistic License for more details. +########################################################################= ######## + +package WeBWorK::DB::SQL; + +=3Dhead1 NAME + +WeBWorK::DB::SQL - SQL-specific implementation of the WeBWorK::DB API. + +=3Dcut + +use strict; +use warnings; +use Carp; +use DBI; +use WeBWorK::Utils qw(runtime_use); + +use constant ALLOWED_SCHEMA =3D> "WeBWorK::DB::Schema::SQL"; +use constant ALLOWED_DRIVER =3D> "WeBWorK::DB::Driver::SQL"; + +########################################################################= ######## +# constructor +########################################################################= ######## + +sub new($$) { + my ($invocant, $dbLayout) =3D @_; + my $class =3D ref($invocant) || $invocant; +=09 + # data that is not table-specific + my $global_source; + my $global_usernameRO; + my $global_passwordRO; + my $global_usernameRW; + my $global_passwordRW; + my $global_debug; +=09 + # data that is table-specific + my %table_data; +=09 + # load the modules required to handle each table, and create driver + my %dbLayout =3D %$dbLayout; + foreach my $table (keys %dbLayout) { + my $layout =3D $dbLayout{$table}; + my $record =3D $layout->{record}; + my $schema =3D $layout->{schema}; + my $driver =3D $layout->{driver}; + my $source =3D $layout->{source}; + my $params =3D $layout->{params}; + =09 + my $usernameRO =3D $params->{usernameRO}; + my $passwordRO =3D $params->{passwordRO}; + my $usernameRW =3D $params->{usernameRW}; + my $passwordRW =3D $params->{passwordRW}; + my $debug =3D $params->{debug}; + =09 + # make sure the schema is the one we can deal with + croak "Table '$table' wants schema module '$schema', but ".__PACKAGE__= ." will only work if the requested schema module is '".ALLOWED_SCHEMA."'.= Can't continue." + unless $schema eq ALLOWED_SCHEMA; + =09 + # make sure the driver is the one we can deal with + croak "Table '$table' wants driver module '$driver', but ".__PACKAGE__= ." will only work if the requested driver module is '".ALLOWED_DRIVER."'.= Can't continue." + unless $driver eq ALLOWED_DRIVER; + =09 + # get DBI data source + layout_error($table, "source", $global_source, $source) + if defined $global_source and $global_source ne $source; + $global_source =3D $source; + =09 + # get usernames and passwords + layout_error($table, "usernameRO", $global_usernameRO, $usernameRO) + if defined $global_usernameRO and $global_usernameRO ne $usernameRO; + layout_error($table, "passwordRO", $global_passwordRO, $passwordRO) + if defined $global_passwordRO and $global_passwordRO ne $passwordRO; + layout_error($table, "usernameRW", $global_usernameRW, $usernameRW) + if defined $global_usernameRW and $global_usernameRW ne $usernameRW; + layout_error($table, "passwordRW", $global_passwordRW, $passwordRW) + if defined $global_passwordRW and $global_passwordRW ne $passwordRW; + $global_usernameRO =3D $usernameRO; + $global_passwordRO =3D $passwordRO; + $global_usernameRW =3D $usernameRW; + $global_passwordRW =3D $passwordRW; + =09 + # debug flag + layout_error($table, "debug", $global_debug, $debug) + if defined $global_debug and $global_debug ne $debug; + $global_debug =3D $debug; + =09 + # we still want to allow a choice of record classes, since it doesn't = cost us anything. + runtime_use($record); + =09 + # this is a temporary data structure that describes how the user descr= ibed the tables + # in the database layout, with some munging + $table_data{$table} =3D { + record =3D> $record, + tableOverride =3D> $params->{tableOverride}, + fieldOverride =3D> $params->{fieldOverride}, + }; + } +=09 + my $dbhRO =3D DBI->connect_cached( + $global_source, + $global_usernameRO, + $global_passwordRO, + { RaiseError =3D> 1 }, + ) or die $DBI::errstr; +=09 + my $dbhRW =3D DBI->connect_cached( + $global_source, + $global_usernameRW, + $global_passwordRW, + { RaiseError =3D> 1 }, + ) or die $DBI::errstr; +=09 + my $self =3D { + #source =3D> $global_source, + #usernameRO =3D> $global_usernameRO, + #passwordRO =3D> $global_passwordRO, + #usernameRW =3D> $global_usernameRW, + #passwordRW =3D> $global_passwordRW, + dbhRO =3D> $dbhRO, + dbhRW =3D> $dbhRW, + debug =3D> $global_debug, + tables =3D> \%table_data, + }; +=09 + bless $self, $class; + return $self; +} + +########################################################################= ######## +# general functions +########################################################################= ######## + +sub hashDatabaseOK { + return 1; +} + +########################################################################= ######## +# password functions +########################################################################= ######## + +sub newPassword { + my ($self, @prototype) =3D @_; +=09 + return $self->record("password")->new(@prototype); +} + +sub listPasswords { + my ($self) =3D @_; +=09 + croak "listPasswords: requires 0 arguments" + unless @_ =3D=3D 1; +=09 + my $table =3D $self->sql_table("password"); + my $field =3D $self->sql_field("user_id"); + my $stmt =3D "SELECT `$field` from `$table`"; +=09 + my $dbh =3D $self->{dbhRO}; + my $sth =3D $dbh->preprare_cached($stmt); + $sth->execute; + return map { $_->[0] } $sth->fetchall_arrayref; +} + +sub addPassword { + my ($self, $Password) =3D @_; +=09 + croak "addPassword: requires 1 argument" + unless @_ =3D=3D 2; + croak "addPassword: argument 1 must be of type ", $self->record("passwo= rd") + unless ref $Password eq $self->{password}->{record}; +=09 + checkKeyfields($Password); +=09 + my $table =3D $self->sql_table("password"); + my @key_fields =3D $self->sql_fields("password", $self->record("passwor= d")->KEYFIELDS); + my @fields =3D $self->sql_fields("password", $self->record("password")-= >FIELDS); +=09 +=09 +=09 + croak "addPassword: password exists (perhaps you meant to use putPasswo= rd?)" + if $self->{password}->exists($Password->user_id); + croak "addPassword: user ", $Password->user_id, " not found" + unless $self->{user}->exists($Password->user_id); +=09 + return $self->{password}->add($Password); +} + +########################################################################= ######## +# utilities +########################################################################= ######## + +sub layout_error { + my ($table, $param, $oldval, $newval) =3D @_; +=09 + croak "Table '$table' sets $param to '$newval', but some other table al= ready set it to '$oldval'. ", + __PACKAGE__, " can only be used if all tables set $param to the same v= alue."; +} + +sub record { + my ($self, $table) =3D @_; +=09 + return $self->{tables}{$table}{record}; +} + +sub sql_table { + my ($self, $table) =3D @_; +=09 + return $self->{tables}{$table}{tableOverride} || $table; +} + +sub sql_field { + my ($self, $table, $field) =3D @_; +=09 + return $self->{tables}{$table}{fieldOverride}{$field} || $field; +} + +sub sql_fields { + my ($self, $table, @fields) =3D @_; +=09 + return map { $self->sql_field($table, $_) } @fields; +} + +sub box { +=09 +} + +sub unbox { +=09 +} + +1; |