Платформы корпоративных информационных систем

         

MysqIPerl



MysqIPerl

Монти Видениус, автор MySQL, написал также и интерфейс Perl к MySQL, Mysql.pm. Он основывался на модуле Msql.pm для mSQL, поэтому интерфейсы двух модулей почти идентичны. На практике мы недавно преобразовали целый сайт из mSQL в MySQL, выполнив команду «perl -e 's/^Msql/Mysql/>> *.cgi» в каждом каталоге, содержащем CGI. Это составило 95% всей работы. Разумеется, при этом вы не получаете преимуществ MySQL, но таким путем можно быстро и легко встать на путь использования MySQL. Mysql.pm входит составной частью в пакет msql-mysql-modules Йохена Видмана (Jochen Wiedmann).

Одним из самых больших различий между MySQL и mSQL является их работа с последовательностями. В mSQL последовательность определяется в таблице командой CREATE SEQUENCE on tablename . Значение последовательности можно получать после этого, как обычное поле таблицы командой SELECT _se.q from tablename . В MySQL к первичному ключу добавляется флаг AU-TO_INCREMENT . При попытке ввода null в это поле оно автоматически инкрементируется. Как MySQL, так и mSQL допускают в каждой таблице только одну последовательность. Подробное обсуждение последовательностей в MySQL и mSQL см. в главе 6 «Диалект SQL, используемый в MySQL и mSQL».

Чтобы показать некоторые функции Mysql.pm, вернемся к примеру с экзаменами. Разобравшись с subject.cgi, займемся таблицей сведений об учащихся. Ее структура такова:

CREATE TABLE student (

id INT NOT NULL auto_increment,

first VARCHAR(50),

middle VARCHAR(50),

last VARCHAR(50),


ext VARCHAR(50),

subjects VARCHAR(100),

age INT,

sex INT,

address BLOB,

city VARCHAR(50),

state VARCHAR(5),

zip VARCHAR(10),

phone VARCHAR(10),

PRIMARY KEY (id)

)

В этой таблице находятся все данные, используемые программой subject, cgi, a также другие сведения, которые относятся к учащемуся. Программа student.cgi, работающая с этой таблицей, должна выполнять все те функции, которые программа subject.cgi выполняла в отношении таблицы subject.

Нельзя работать с базой данных mSQL через модуль Mysql.pm, как и с базой MySQL через Msql.pm. Программа stu-dent.cgi предполагает, что таблица предметов находится в базе данных MySQL. Аналогично, программа subject.cgi рассчитывает на mSQL-версию таблицы учащихся.

Чтобы продемонстрировать, как работает Mysql.pm, мы подробно изучим ту часть student.cgi, которая позволяет пользователю изменять сведения об учащемся. Так же как операция «add» (добавление) в примере для Msql.pm была разбита на четыре отдельные функции, операция «change» (изменение) разбита здесь на три отдельные функции.

Первая функция - изменения, выводит форму, позволяющую пользователю найти учащегося, данные о котором нужно изменить:

sub change {

print header, start_html('title'=>'Поиск учащегося для изменения денных'

'BGCOLOR'=>'white');

&print_form('search2', Поиск учащегося для изменения данных',1);

print <<END_OF_HTML; <р>

<INPUT TYPE=HIDDEN NAME="subaction" VALUE="change2">

<INPUT TYPE=SUBMIT VALUE=" Искать учащегося ">

<INPUT TYPE=SUBMIT NAME="all" VALUE=" Просмотр всех учащихся ">

<INPUT TYPE=RESET>

</form></body></html>

END_OF_HTML }

Форма, используемая для поиска учащегося с целью изменения, настолько сходна с формами для просмотра данных и для добавления, что во всех трех случаях используется одна функция, print_form , показанная ниже:

sub print_form {

my ($action,$message,$any) = @_;

print <<END_OF_HTML;

<FORM METHOD=post ACTION="students.cgi">

<INPUT TYPE=HIDDEN NAME="action" VALUE="$action">

<H1>$message</h1>

END_OF_HTML

if ($any) {

print <<END_OF_HTML; <р>Поиск

<SELECT NAME="bool">

<OPTION VALUE="ог">любой

<OPTION VALUE="and">Bce </select> выбранные вами.

END_OF_HTML

У

print <<END_OF_HTML; <P>

Имя:

<INPUT NAME="first" SIZE=20>

Отчество:

<INPUT NAME="middle" SIZE=10>

Фамилия:

<INPUT NAME="last" SIZE=20>

МЛ./III/И т.д..:

<INPUT NAME="ext" SIZE=5> <br>

Адрес:

<INPUT NAME="address" SIZE=40><br>

Город:

<INPUT NAME="city" SIZE=20>

Штат:

<INPUT NAME="state" SIZE=5>

Почтовый индекс:

<INPUT NAME="zip" SIZE=10><br>

Телефон:

<INPUT NAME="phone" SIZE=15><br>

Возраст:

<INPUT NAME="age" SIZE=5>

Пол:

<SELECT NAME="sex">

END_OF_HTML

if ($any) {

print <<END_OF_HTML; <OPTION VALUE="">He имеет значения

END_OF_HTML

}

print <<END_OF_HTML;

<OPTION VALUE="1">Myжской

<OPTION VALUE="2">Женский

</select><br>

<P>

Записан на:<br>

END_OF_HTML

&print_subjects("MULTIPLE SIZE=5");

}

Благодаря использованию трех параметров эта функция настраивает шаблон формы так, что может использоваться в самых различных целях. Обратите внимание, что эта вспомогательная функция использует другую вспомогательную функцию, print_subjects . Последняя выводит список всех имеющихся предметов из таблицы subject, как в примере Msql.pm.

sub print_subjects { my $modifier = "";

$modifier = shift if @_;

print qq%<SELECT NAME="subjects" $modifier>\n%;

my $out = $dbh->query("select * from subject order by name");

while(my(%keys)=$out->fetchhash) {

print qq%<OPTION VALUE="$keys{'id'}">$keys{'name'}\n%;

}

print "</select>\n";

}

Параметры поиска, введенные в первую форму, передаются функции search2, фактически осуществляющей поиск. На самом деле это функция, написанная для поиска учащегося, данные о котором нужно показать. Поскольку она делает как раз то, что нам требуется, мы можем ею воспользоваться, если сообщим ей, что после поиска хотим перейти

к следующей функции изменения, change2. Для этого мы ввели в форму скрытую переменную subaction=change2 . Она сообщает search2, куда отправить пользователя дальше:

sub search2 {

my $out = $dbh->query(&make_search_query);

my $hits = $out->numrows;

my $subaction = "view";

$subaction = param('subaction')

if param('subaction');

print header, start_html('title'=>'Результаты поиска учащихся', 'BGCOLOR'=>'white');

if (not Shits) {

print <<END_OF_HTML;

<Н1>Учащихся не найдено</h1>

<P>

He найдено учащихся, удовлетворяющих вашему критерию.

END_OF_HTML } else {

print <<END_OF_HTML;

<H1> Найдено $hits учащихся </h1> <р>

<UL>

END_OF_HTML

while(my(%fields)=$out->fetchhash) {

print qq%<LI>

<A HREF="students.cgi?action=$subaction&id=$fields

{'id'}">$fields{'first'} $fields{'middle'} $fields{'last'}%;

print ", $fields{'ext'}" if $fields{'ext'};

print "\n</a>"; } }

print <<END_OF_HTML; </ul> <p>

<A HREF="students.cgi?action=search">HcKaTb</a> снова.

</body></html>

END_OF_HTML }

С помощью функции make_search_query эта функция сначала ищет учащихся, отвечающих критериям поиска. Затем она выводит список найденных записей, среди которых пользователь может сделать выбор. ID выбранной записи передается функции change2, как показано ниже:

sub change2 {

my $out = $dbh->query

("select * from student where id=$id");

my($did,Ifirst,$middle,$last,

$ext,Ssubjects.Sage,$sex,$address,

$city,$state,$zip,$phone) = $out->fetch row;

my ©subjects = split(/:/,$subjects);

shift,©subjects;

my $name = "$first $tmiddle $last";

if ($ext) { $name .= ", $ext"; }

print header, start_html('title'=>"$name", 'BGCOLOR'=>'white');

print <<END_OF_HTML;

<H1>$name</h1> <p>

<FORM ACTION="students.cgi" METHOD=POST>

<INPUT TYPE=HIDDEN NAME="action" VALUE="change3">

<INPUT TYPE^HIDDEN NAME="id" VALUE="$id">

Имя:

<INPUT NAME="first" VALUE="$first" SIZE=20>

Отчество:

<INPUT NAME="middle" VALUE="$middle" SIZE=10>

Фамилия:

<INPUT NAME="last" VALUE="$last" SIZE=20>

МЛ./III/И т.д.

<INPUT NAME="ext" VALUE="$ext" SIZE=5> <br>

Адрес:

<INPUT NAME="address" VALUE="$address" SIZE=40><br>

Город:

<INPUT NAME="city" VALUE="$city" SIZE=20>

Штат:

<INPUT NAME="state" VALUE="$state" SIZE=5>

Почтовый индекс:

<INPUT NAME="zip" VALUE="$zip" SIZE=10xbr>

Телефон:

<INPUT NAME="phone" VALUE="$phone" SIZE=15><br>

Возраст:

<INPUT NAME="age" VALUE="$age" SIZE=5>

Пол:

END_OF_HTML

my %sexes = ( '1' => 'Мужской',

'2' => 'Женский' );

print popup_menu('name'=>'Пол', 'values'=>["!', '2'], 'default'=>"$sex", ' labels'=>\%sexes);

print <<END_OF_HTML; <p>

Записан на:<br>

END_OF_HTML

my @ids = ();

my %subjects = ();

my $out2 = $dbh->query("select id,name from subject order by name");

while(my($id,$subject)=$out2->fetchrow) { push(@ids,Sid);

$subjects{"$id"} = $subject; }

print scrolling_list('name'=>'subjects', 'values'=>[@ids], 'default'=>[@subjects], 'size'=>5, 'multiple'=>'true', 'labels'=>\%subjects);

print <<END_OF_HTML;

<р>

<INPUT TYPE=SUBMIT VALUE=" Изменить данные об учащемся ">

<INPUT TYPE=SUBMIT NAME="delete" VALUE=" Удалить учащегося ">

<INPUT TYPE=RESET>

</form></body></html>

END_OF_HTML

}

Главная задача этой функции - вывести форму, очень похожую на ту, которую порождает print^from. Однако значениями по умолчанию в этой форме должны быть те, которые соответствуют выбранному учащемуся. В результате пользователь может редактировать одни поля, оставляя другие неизменными.

Несколько функций, предоставляемых модулем CGI.pm, оказываются очень удобными при выводе формы со значениями, установленными по умолчанию, особенно функция CGI: :scrolling_list , выводящая блок HTML <SELECT> с заданными параметрами. Среди прочих, функция принимает параметры values, default и labels, относящиеся к значениям каждого тега <OPTION> , задающие выбираемые по умолчанию пункты и их метки, видимые пользователю.

Эта функция выводит заполненную форму, как если бы это была форма для добавления. Разница в том, что это данные для учащегося, уже имеющегося в базе данных. Функция changes принимает данные и обновляет данные в базе, как показано ниже:

sub changes {

if (param('delete')) { &delete2($id); } else {

my Squery = "update student set "; my @query = ();

foreach ('first', 'middle', 'last', 'ext', 'address', 'city', 'state', 'zip', 'phone') {

if (param($_)) { push(@query,"$_ = ".

$dbh->quote(param($_))); } }

push(@query,"age=".param('age')) if param('age');

push(@query,"sex=".param('sex')) if param('sex');

my $subjects = "':";

$subjects .= join(":",param('subjects'));

$subjects .= ":" unless $subjects eq "':";

$subjects .= "'";

push(@query, "subjects=$subjects");

Squery .= join(", ",@query) . " where id=$id"; $dbh->query($query);

print header, start_html('title'=>'Данные об учащемся изменены',

'BGCOLOR'=>'white'); # Вывести форму с сообщением об успехе

}

}

Обратите внимание, что при выборе кнопки «Delete» на странице изменения функция автоматически передает управление функции удаления. Это одно из главных преимуществ объединения в одной программе нескольких функций. Если вмешательства пользователя не требуется, то можно перескакивать между функциями без посылки пользователю сообщений о перенаправлении.

Оставшаяся часть этой функции довольно проста. Данные об учащемся собираются в запросе UPDATE, который отправляется серверу MySQL. Затем пользователю посылается страница с сообщением об успешном завершении работы.



Содержание раздела