Modified by Aarne Ranta from earlier years' specifications by many other teachers at Chalmers and GU
The purpose of this assignment is to give you hands-on experience with designing, constructing and using a database for a real-world-like domain. You will see all aspects of database creation, from understanding the domain to using the final database from external applications.
To pass the programming assignment, you must pass all five tasks described on this page. You will do the assignment in groups of two.
You must submit your solutions through the Fire reporting system.
You must submit your group's solutions to each task by the given deadline, which are given on the course web page. After submission, your assignment will be graded ("pass" or "reject") and you will receive comments on your solution (for tasks 1, 2, and 3). If your submission is rejected, you are allowed to refine your solution and re-submit it. There will be set of automated test to preliminarily grade your assignment.
To pass the final part of the assignment, you must demonstrate your system to one of the teachers. Your files for task 4 must be uploaded to the Fire system after you have demonstrated your system, and before the task 4 deadline.
In this assignment you will design and construct a database, together with a front end application, that handles university students and courses. You will do this in four distinct tasks:
All of the tasks are related to each other. They deal with the same database, and tasks 3 an 4 build on task 1. Task 2 is an independent analysis and sanity check on task 1. (In previous years, the Design task 2 was made before the Construction task 1. We have swapped the order for two reasons:
For each task you will hand in and get feedback on your results. Since errors in one task may propagate to the next one, it is wise to hand in your solutions early to get more chances for feedback.
Be sure to read through the full description of the assignment before you start since the requirements we place on the system must influence your initial design as well.
The domain that you will model in this assignment is that of courses and students at a university. So as not to make the task too large and unspecified, you will here get a description of the domain that restricts the problem somewhat. Note that the described domain is not identical to Chalmers or GU.
The university for which you are building this system is organized into departments for employees, such as the Dept. of Computing Science (CS), and study programmes for students, such as the Computer Science and Engineering programme (CSEP). Programmes are hosted by departments, but several departments may collaborate on a programme, which is the case with CSEP that is co-hosted by the CS department and the Department of Computer Engineering (CE). Department names and abbreviations are unique, as are programme names but not necessarily abbreviations.
Each study programme is further divided into branches, for example CSEP has branches Computer Languages, Algorithms, Software Engineering etc. Note that branch names are unique within a given programme, but not necessarily across several programmes. For instance, both CSEP and a programme in Automation Technology could have a branch called Interaction Design. For each study programme, there are mandatory courses. For each branch, there are additional mandatory courses that the students taking that branch must read. Branches also name a set of recommended courses from which all students taking that branch must read a certain amount to fulfill the requirements of graduation, see below.
A student always belongs to a programme. Students must pick a single branch within that programme, and fulfill its graduation requirements, in order to graduate. Typically students choose which branch to take in their fourth year, which means that students who are in the early parts of their studies may not yet belong to any branch.
Courses are given by a department (e.g. CS gives the Databases course), and may be read by students reading any study programme. Some courses may be mandatory for certain programmes, but not so for others. Students get credits for passing courses, the exact number may vary between courses (but all students get the same number of credits for the same course). Some, but not all, courses have a restriction on the number of students that may take the course at the same time. Courses can be classified as being mathematical courses, research courses or seminar courses. Not all courses need to be classified, and some courses may have more than one classification. The university will occasionally introduce other classifications. Some courses have prerequisites, i.e. other courses that must be read before a student is allowed to register to it.
Students need to register for courses in order to read them. To be allowed to register, the student must first fulfill all prerequisites for the course. It should not be possible for a student to register to a course unless the prerequisite courses are already passed. It should not be possible for a student to register for a course which they have already passed.
If a course becomes full, subsequent registering students are put on a waiting list. If one of the previously registered students decides to drop out, such that there is an open slot on the course, that slot is given to the student who has waited the longest. When the course is finished, all students are graded on a scale of 'U', '3', '4', '5'. Getting a 'U' means the student has not passed the course, while the other grades denote various degrees of success.
A study administrator can override both course prerequisite requirements and size restrictions and add a student directly as registered to a course. (Note: you will not implement any front end application for study administrators, only for students. The database must still be able to handle this situation.)
For a student to graduate there are a number of requirements she must first fulfill. She must have passed (have at least grade 3) in all mandatory courses of the study programme she belongs to, as well as the mandatory courses of the particular branch that she must have chosen. Also she must have passed at least 10 credits worth of courses among the recommended courses for the branch. Furthermore she needs to have read and passed (at least) 20 credits worth of courses classified as mathematical courses, 10 credits worth of courses classified as research courses, and one seminar course. Mandatory and recommended courses that are also classified in some way are counted just like any other course. As an example, if one of the mandatory courses of a programme is also a seminar course, students of that programme will not be required to read any more seminar courses.
You will design and implement a database for the above domain, and a front end application intended for students of the university. Through the application they should be able to see their own information, register to, and unregister from courses.
Formally, your application should have the following modes:
- Info: Given a students national identification number, the system should provide
- the name of the student, the students national identification number and their university issued login name/ID (something similar to how the CID works for chalmers students) - the programme and branch (if any) that the student is following. - the courses that the student has read, along with the grade. - the courses that the student is registered to. - whether or not the student fulfills the requirements for graduation
- Register: Given a student id number and a course code, the system should try to register the student for that course. If the course is full, the student should be placed in the waiting list for that course. If the student has already passed the course, or is already registered, or does not meet the prerequisites for the course, the registration should fail. The system should notify the student of the outcome of the attempted registration, and the reason for failure (if any). - Unregister: Given a student id number and a course code, the system should unregister the student from that course. If there are students waiting to be registered, and there is now room on the course, the one first in line should be registered for the course. The system should acknowledge the removed registration for the student. If the student is not registered to the course when trying to unregister, the system need not notify this, but no student from the waiting list (if applicable) should be promoted in that case.
Your task is to construct the database by implementing the database schema in a database engine (PostgreSQL). The schema is explained abstractly in this file:
You should implement the schema with
CREATE TABLE statements that
Thus you should create all tables, marking key and foreign key constraints in the process, and you should also insert checks that ensure that only valid data can be inserted in the database. Examples of invalid data would be the grade '6', or a course that takes a negative number of students.
When you have created the tables, you should fill the tables with example data. This can be time-consuming, but it is an important part of the development of a database. Having data in the database is crucial in order to properly verify that it behaves the way that you expect it to. You should fill the tables with enough data so that it is possible to test that your application can handle the various operations specified above. Just inserting tons of data is of no use if the data still doesn't test all parts of the database. Here is a (very) non-exhaustive list of data you will need to include:
Important: When you insert data in the database, do it by writing the insert statements in a file that can then be executed. This way you won't have to re-do all the work if there is something that you need to change with the table.
Since you know exactly what information your application will need from the database, in what forms, it is a good idea to write views that provide that information in a simple form. In a real setting, we would even ensure using privileges that the application cannot work with anything but these views. Unfortunately we cannot let you test working with privileges on the PostgreSQL machine we use, but we will still expect your application to adhere to the privileges we list.
Following the system specification, create these views:
StudentsFollowing(student, program, branch)For all students, their SSN, the program and the branch (if any) they are following. The
branchcolumn is the only column in any of the views that is allowed to be NULLABLE.
FinishedCourses(student, course, grade, credits)For all students, all finished courses, along with their codes, grades (grade
'5') and number of credits. The type of the grade should be a character type, e.g.
Registrations(student, course, status)All registered and waiting students for all courses, along with their waiting status (
PassedCourses(student, course, credits)For all students, all passed courses, i.e. courses finished with a grade other than 'U', and the number of credits for those courses. This view is intended as a helper view towards the
PathToGraduationview (and for task 4), and will not be directly used by your application.
UnreadMandatory(student, course)For all students, the mandatory courses (branch and programme) they have not yet passed. This view is intended as a helper view towards the
PathToGraduationview, and will not be directly used by your application.
PathToGraduation(student, totalCredits, mandatoryLeft, mathCredits, researchCredits, seminarCourses, status)For all students, their path to graduation, i.e. a view with columns for -
ssn: the student's SSN. -
totalCredits: the number of credits they have taken. -
mandatoryLeft: the number of courses that are mandatory for a branch or a program they have yet to read. -
mathCredits: the number of credits they have taken in courses that are classified as math courses. -
researchCredits: the number of credits they have taken in courses that are classified as research courses. -
seminarsCourses: the number of seminar courses they have read. -
status: whether or not they qualify for graduation. The SQL type of this field should be
FALSE). Make sure that your views use the right names of columns! Use
ASto name a column. Deliverables: For task 1, you should submit the following files through Fire
tables.sql: your SQL code for creating the tables.
insert.sql: your SQL code containing the insert statements for the data.
views.sql: your SQL code for creating the listed views.
Note that SQL code should be in plain text format. Make sure that PostgreSQL can execute your files before you hand them in. Test this by clearing out your database and then running your SQL files again.
The task in this lab is to take a look back at the database implemented in Lab 1 and check how we should have done it. More precisely, we will
There are many interesting outcomes that may result from this study:
Your first task is to create an E-R diagram that correctly models the domain described in the Domain description above.
You can use any tool you like
for this task, as long as you hand in your solution as an image in one of
Dia has (usually) nicer graphics, whereas Query Converter produces the schema automatically. You must in both cases use the translations specified in Lecture Notes, Section 3.3, and mark the keys and references properly.
Hint: if your diagram does not contain at least one weak entity, at least one ISA relationship, and at least one many-to-at-most-one relationship, you have probably done something wrong.
Your second task is to formulate all functional dependencies in the domain and derive a valid schema from them. This can (and must) be done independently of the E-R design and of the schema in task1.txt.
Domain(....). You will have to rename some attributes so that all names are distinct.
Domain(....). Do not look at your E-R model or task1.txt at this point!
Domain(....), as well as all BCNF violations.
Domain(....)to distinct tables by using the BCNF normalization algorithm.
Here is a non-exhaustive list of things you may want to consider when searching for functional dependencies: - department names and abbreviations - study programme names and abbreviations - branch names - student names and identification numbers - student programmes and branches - course names and codes - course classifications and prerequisites - course waiting lists
Nint: the Query Converter can automate much of the analysis, as soon as you have identified the functional dependencies yourself. It can get slow when the schema is very large, but you can then just reload the page to kill the process.
Deliverables: For Task 2, you should submit the following files through Fire
ER.png: your E-R diagram as a
ER-schema.txt: the database schema derived from your E-R diagram, as a text file (no PDF, no Microsoft Word, no HTML!)
Domain(...)schema together with the functional dependencies you have found (you can omit dependencies that can be derived from the ones you mention)
FD-schema.txt: the decomposed schemas using the BCNF algorithm
design-report.pdf: a report comparing the results of the different types of analysis (a text file
,htmlis also OK)
Criteria of acceptance:
ER.png: the E-R diagram must be syntactically correct and a reasonable model for the domain (and you cannot do this without weak entities and ISA entities!)
ER-schema.txt: the ER-schema must be correctly derived from the diagram (automatic, if you use Query Converter)
FD.txt: you should have found all and only the reasonable functional dependencies in the domain (derived ones can be omitted)
FD-schema.txt: the decompositions should be correct (this is partly automatic if you use Query Converter, but you should make sure to mark the keys and references)
design-report.pdf: the report should identify all cases where the ER and FD analyses lead to different schemas and, at least in some cases, argue why any of them is preferable. A similar comparison should be done with the schema in Lab 1. In the simplest case, you can just say that the schema is exactly the same. You can say this if some names of attributes and tables are different, as long as the structure is the same.
When your tables and views are implemented in Task 1, the next task is to create two triggers to handle some key issues in registration and unregistration. Here is a piece of code to get you started on the first trigger:
Postgresql trigger example
But first, you should define one more view that can be used by your triggers, and your application in Task 1:
CourseQueuePositions(course,student,place): For all students who are in the queue for a course, the course code, the student's identification number, and the student's current place in the queue (the student who is first in a queue will have place "1" in that queue, etc.). When a student tries to register for a course, it is possible that the course is already full, in which case the student should be put in the waiting list for that course. When a student unregisters, it might be that there is now room for some student who is in the waiting list, and who should then be registered for the course instead. Such things are typically handled via triggers. You should write two triggers:
Registrationsinstead of on the tables themselves (the view was built in task 1 above). (One reason for this is that we "pretend" that you only have the privileges listed under Task 4, which means you cannot insert data into, or delete data from, the underlying tables directly. But even if we lift this restriction, there is another reason for not defining these triggers on the underlying tables - can you figure out why?) Testing. we will prepare test cases (in SQL) for testing both insertion and deletion to check the triggers work. These tests will be applied automatically in Fire when the lab registration is open.
Deliverables. For task 4, you should hand in the following files:
triggers.sql: SQL code for creating the two triggers.
setup.sql: SQL code that sets up your database for testing the triggers. This will normally be the concatenation of files
views.sqlfrom Task 1. We must be able to test your triggers by executing the files
triggers.sql, in that order.
Make sure that PostgreSQL can execute your files before you hand them in.