The Professor-Student Mixed Form Application
This EQUEL/FORMS application lets the user browse and update information about graduate students who report to a specific professor. The program is structured in a master/detail fashion, with the professor being the master entry, and the students the detail entries. The application uses two forms--one to contain general professor information and another for detailed student information.
The objects used in this application are:
The program uses the "masterfrm" as the general-level master entry, in which data can only be retrieved and browsed, and the "studentfrm" as the detailed screen, in which specific student information can be updated.
The runtime user enters a name in the pname (professor name) field and then selects the Students menu operation. The operation fills the displayed and hidden columns of the table field "studenttbl" with detailed information of the students reporting to the named professor.
The user may then browse the table field (in read mode), which displays only the names and ages of the students. More information about a specific student may be requested by selecting the Zoom menu operation. This operation displays the form "studentfrm." The fields of "studentfrm" are filled with values stored in the hidden columns of "studenttbl."
The user may make changes to three fields (sgpa, scomment and sadvisor). If validated, these changes will be written back to the database table (based on the unique student id), and to the table field's data set. This process can be repeated for different professor names.
The following two create statements describe the Professor and Student database tables:
## create student -- Graduate student table
## (sname = c25, -- Name
## sage = i1, -- Age
## sbdate = c25, -- Birth date
## sgpa = f4, -- Grade point average
## sidno = i4, -- Unique student number
## scomment = text(200), -- General comments
## sadvisor = c25) -- Advisor's name
## create professor -- Professor table
## (pname = c25, -- Professor's name
## pdept = c10) -- Department
-- Master and student compiled forms (imported objects)
## package Compiled_Forms is
## masterfrm, studentfrm: Integer;
pragma import_object( masterfrm );
pragma import_object( studentfrm );
## end Compiled_Forms;
with Compiled_Forms; use Compiled_Forms;
with Text_Io; use Text_Io;
with Integer_Text_Io; use Integer_Text_Io;
## with equel_forms;
-- Procedure: Prof_Student
-- Purpose: Main body of "Professor Student"
-- Master-Detail application.
## procedure Prof_Student is
-- Graduate student record maps to "student" database table
## type Student_Rec is
## record
## sname: String(1..25);
## sage: Short_Short_Integer;
## sbdate: String(1..25);
## sgpa: Float;
## sidno: Integer;
## scomment: String(1..200);
## sadvisor: String(1..25);
## end record;
## grad: Student_Rec;
-- Professor record maps to "professor" database table
## type Prof_Rec is
## record
## pname: String(1..25);
## pdept: String(1..10);
## end record;
## prof: Prof_Rec;
-- Useful forms runtime information
## lastrow, -- Lastrow in table field
## istable: Integer; -- Is a table field?
-- Utility buffers
## msgbuf: String(1..100); -- Message buffer
## respbuf: String(1..1); -- Response buffer
## oldadv: String(1..25); -- Old advisor name before Zoom
-- Function: Student_Info_Changed
-- Purpose: Allow the user to zoom into the details of
-- a selected student. Some of the data can be
-- updated by the user. If any updates were
-- made, then reflect these back into the
-- database table.The procedure returns TRUE if
-- any changes were made.
-- Parameters:
-- None
-- Returns:
-- TRUE/FALSE - Changes were made to the
-- database. Sets the global "grad" record
-- with the new data.
## function Student_Info_Changed return Boolean is
## changed: Integer; -- Changes made to the form?
## valid_advisor: Integer; -- Is advisor a professor?
## begin
-- Display the detailed student information
## display #studentfrm update
## initialize
## (sname = grad.sname,
## sage = grad.sage,
## sbdate = grad.sbdate,
## sgpa = grad.sgpa,
## sidno = grad.sidno,
## scomment = grad.scomment,
## sadvisor = grad.sadvisor)
## activate menuitem "Write"
## {
-- If changes were made then update the
-- database table. Only bother with the
-- fields that are not read-only.
## inquire_frs form (changed = change)
if (changed = 1) then
## validate
## message "Writing to database. . ."
## getform
## (grad.sgpa = sgpa,
## grad.scomment = scomment,
## grad.sadvisor = sadvisor)
-- Enforce integrity of name
## retrieve (valid_advisor =
## count(p.pname
## where p.pname = grad.sadvisor))
if (valid_advisor = 0) then
## message "Not a valid name"
## sleep 2
## resume field sadvisor
end if;
## replace s
## (sgpa = grad.sgpa,
## scomment = grad.scomment,
## sadvisor = grad.sadvisor)
## where s.sidno = grad.sidno
end if;
## breakdisplay
## } -- "Write"
## activate menuitem "End", frskey3
## {
-- End without submitting changes
changed := 0;
## breakdisplay
## } -- "End"
## finalize
return (changed = 1);
## end Student_Info_Changed;
## begin
-- Start up Ingres and the FORMS system
## forms
## message "Initializing Student Administrator . . ."
## ingres personnel
## range of p is professor, s is student
## addform masterfrm
## addform studentfrm
-- Initialize "studenttbl" with a data set in READ
-- mode. Declare hidden columns for all the extra
-- fields that the program will display when more
-- information is requested about a student. Columns
-- "sname" and "sage" are displayed, all other columns
-- are hidden, to be used in the student information form.
## inittable #masterfrm studenttbl read
## (sbdate = char(25),
## sgpa = float4,
## sidno = integer4,
## scomment = char(200),
## sadvisor = char(20))
-- Drive the application, by running "masterfrm", and
-- allowing the user to "zoom" into a selected
-- student.
## display #masterfrm update
## initialize
## {
## message "Enter an Advisor name . . ."
## sleep 2
## }
## activate menuitem "Students", field "pname"
## {
-- Load the students of the specified professor
## getform (prof.pname = pname)
-- If no professor name is given then resume
if (prof.pname(1) = ' ') then
## resume field pname
end if;
-- Verify that the professor exists. If not
-- print a message, and continue. We assume
-- that each professor has exactly one department.
prof.pdept := (1..10 = ' ');
## retrieve (prof.pdept = p.pdept)
## where p.pname = prof.pname
-- If no professor report error
if (prof.pdept(1) = ' ') then
msgbuf := (1..100 => ' ');
msgbuf(1..59) :=
"No professor with name '" &
prof.pname & "' [RETURN]";
## prompt noecho (msgbuf, respbuf)
## clear field all
## resume field pname
end if;
-- Fill the department field and load students
## message "Retrieving Student Information . . ."
## putform (pdept = prof.pdept)
## clear field studenttbl
## redisplay -- Refresh for query
-- With the advisor name, load into the
-- "studenttbl" table field all the graduate -- students who report to the professor with that name.
-- Columns "sname" and "sage" will be displayed,
-- and all other columns will be hidden.
## retrieve
## (grad.sname = s.sname,
## grad.sage = s.sage,
## grad.sbdate = s.sbdate,
## grad.sgpa = s.sgpa,
## grad.sidno = s.sidno,
## grad.scomment = s.scomment,
## grad.sadvisor = s.sadvisor)
## where s.sadvisor = prof.pname
## {
## loadtable #masterfrm studenttbl
## (sname = grad.sname,
## sage = grad.sage,
## sbdate = grad.sbdate,
## sgpa = grad.sgpa,
## sidno = grad.sidno,
## scomment = grad.scomment,
## sadvisor = grad.sadvisor)
## }
## resume field studenttbl
## } -- "Students"
## activate menuitem "Zoom"
## {
-- Confirm that user is on "studenttbl", and that
-- the table field is not empty. Collect data
-- from the row and zoom for browsing and updating.
## inquire_frs field #masterfrm (istable = table)
if (istable = 0) then
## prompt noecho
## ("Select from the student table [return]",
## respbuf)
## resume field studenttbl
end if;
## inquire_frs table #masterfrm (lastrow = lastrow)
if (lastrow = 0) then
## prompt noecho
## ("There are no students [return]",
## respbuf)
## resume field pname
end if;
-- Collect all data on student into graduate
-- record
## getrow #masterfrm studenttbl
## (grad.sname = sname,
## grad.sage = sage,
## grad.sbdate = sbdate,
## grad.sgpa = sgpa,
## grad.sidno = sidno,
## grad.scomment = scomment,
## grad.sadvisor = sadvisor)
oldadv := grad.sadvisor;
-- Display "studentfrm", and if any changes were
-- made make the updates to the local table field
-- row. Only make updates to the columns
-- corresponding to
-- writable fields in "studentfrm". If the student
-- changed advisors then delete this row from display.
if (Student_Info_Changed) then
if (grad.sadvisor /= oldadv) then
## deleterow #masterfrm studenttbl
else
## putrow #masterfrm studenttbl
## (sgpa = grad.sgpa,
## scomment = grad.scomment,
## sadvisor = grad.sadvisor)
end if;
end if;
## } -- "Zoom"
## activate menuitem "Quit", frskey2
## {
## breakdisplay
## } -- "Quit"
## finalize
## clear screen
## endforms
## exit
## end Prof_Student;