main
Michael Kowalczyk 12 months ago
parent 78ba36e73c
commit aeb0816d9f

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 226 KiB

@ -17,7 +17,7 @@ For a database engine, SQLite was compared with MySQL, as both are free. Accord
#### Backups #### Backups
SQLite works based on a single database file, so it will be straightforward to schedule automatic backups. For simplicity of deployment, the plan is to implement this in the Node.js server script itself. SQLite works based on a single database file and it has built-in functionality for making a backup, so it will be straightforward to schedule automatic backups. For simplicity of deployment, the plan is to implement this in the Node.js server script itself.
### Client-server data communication: JSON over AJAX ### Client-server data communication: JSON over AJAX
@ -29,6 +29,8 @@ JSON will be used for client-server data communication (e.g. visit and user data
## Major database tables ## Major database tables
There will only need to be 3 main database tables: Users, Visits, and Committments. These tables will implement the internal model supposed in the user interface document. There will also be a table for storing configuration data; see https://stackoverflow.com/questions/2300356/using-a-single-row-configuration-table-in-sql-server-database-bad-idea for a discussion of two possible implementations of the configuration table.
## Performance ## Performance
## Scalability ## Scalability

@ -0,0 +1,49 @@
DBMS = Database Management System (e.g. MySQL, MariaDB, PostgreSQL, Oracle, Access, MongoDB)
SQL:
This should be your default option for most applications
Relational database with predefined schema
Data organized in tables, rows, and columns
Uses SQL as a common language, but some features may be DBMS-specific (MySQL vs PostgreSQL, etc.)
Well-suited for multi-table transactions
NoSQL:
Useful when you need high-performance at a huge scale, with little or no relation between tables
Allows storing data with no schema
Well-suited for documents, JSON, time series data, data dumps, and logs
Records can have internal structure (such as an array or tree-like structure)
Lack of good support for joins can be circumvented by storing joined data multiple times in different records
This sacrifices memory for time
Maintaining data consistency is more challenging
Some NoSQL DMBSs have limited support for joins and transactions
Note: If you just need to dump a bunch of JSON data (or something similar) from your application and fetch it back at a later time, you may not need a detailed database model. You may just want to store the JSON data directly (which both SQL and NoSQL databases can do).
SQLite:
From their website: "SQLite does not compete with client/server databases. SQLite competes with fopen()"
Benefits:
Simple to setup
Low latency, even for large sequences of SQL statements
Transactional
Serverless
Single data file
Lightweight processing
Drawbacks:
Any write operation requires a lock on the whole database; many simultaneous writes will slow it down
Lacks stored procedures
Lacks user management (e.g. who has permission to write to which table)
Transaction:
A unit of work on the database (possibly with multiple actions), treated independently of other such units.
If you are using a database, you must learn how to use transactions
Properties (ACID):
Atomic - either all of the transaction takes affect, or none of it (including under power failures and crashes)
Consistent - database invariants are maintained (constraints, triggers, referential integrity, etc.)
Isolated - transactions are executed as if they were sequential
Durable - committed transactions are never forgotten (i.e. they stored to non-volatile memory)
Basic operations (CRUD) and their associated SQL statements:
Create (INSERT)
Retrieve (SELECT)
Update (UPDATE)
Delete (DELETE)

@ -0,0 +1,107 @@
Naming conventions I'll be using:
UpperCamelCase tables and columns
Plural table names (less likely to conflict with reserved words)
Singular column names
Associative table names:
The names the other two tables joined by an underscore: either can be singular or plural as the relationship dictates.
Primary keys are named [SingularTableName]ID, and identically when appearing as a foreign key.
When needed, add a prefix: SourceWarehouseID and DestinationWarehouseID
Some SQLite specific commands
.open CampusVisit.db
.tables
PRAGMA table_info(TableName);
PRAGMA foreign_keys = ON; /* Need this one to define foreign key contraints. */
CREATE TABLE Users(
UserID INTEGER PRIMARY KEY,
Name VARCHAR(100) UNIQUE NOT NULL,
Email VARCHAR(20) UNIQUE NOT NULL,
PasswordHash VARCHAR(64) NOT NULL,
IsAdmin BOOLEAN NOT NULL,
IsFaculty BOOLEAN NOT NULL,
IsCoordinator BOOLEAN NOT NULL,
Availability INTEGER DEFAULT -9223372036854775808 /* 64 bits. LSB is Sunday 8am, then 9am, 10, ... Monday 8am, 9am, .... Sign bit is "other time" category. */
);
CREATE TABLE Visits(
VisitID INTEGER PRIMARY KEY,
UserID INTEGER, /* DEFAULT NULL is implicit in SQLite. NULL values are allowed with the foreign key. */
StudentInfo VARCHAR(100) NOT NULL DEFAULT '',
OtherVisitors VARCHAR(100) NOT NULL DEFAULT '',
Hometown VARCHAR(50) NOT NULL DEFAULT '',
Day VARCHAR(10) NOT NULL, /* YYYY-MM-DD */
Availability INTEGER NOT NULL DEFAULT 0, /* Same format as Users.Availability */
DecidedTime INTEGER, /* Same format as Users.Availability */
Status VARCHAR(9) CHECK(Status IN ('proposed','assigned','confirmed','completed','canceled')) NOT NULL DEFAULT 'proposed',
Notes VARCHAR(500) NOT NULL DEFAULT '',
NotificationFrequency INTEGER NOT NULL DEFAULT 2,
FOREIGN KEY(UserID) REFERENCES Users(UserID)
);
CREATE TABLE Visits_Users (
VisitID INTEGER,
UserID INTEGER,
Willingness VARCHAR(10) CHECK(Willingness IN ('cannot', 'prefer not', 'can do')) NOT NULL, /* unknown if pair is missing from the table */
PRIMARY KEY (VisitID, UserID),
FOREIGN KEY(VisitID) REFERENCES Visits(VisitID),
FOREIGN KEY(UserID) REFERENCES Users(UserID)
);
CREATE TABLE Settings(
Key VARCHAR(100) PRIMARY KEY,
Value VARCHAR(100) NOT NULL DEFAULT ''
);
Initialization:
Initial values for global settings (hyperlink lifetime and notification frequency)
INSERT INTO Settings VALUES ('HyperlinkLifetime','7');
INSERT INTO Settings VALUES ('CoordinatorNotificationFrequency','3');
Login screen:
Check username/password
SELECT COUNT() FROM Users WHERE Email='mkowalcz@nmu.edu' AND PasswordHash='secret';
Visits tab:
Create new visit
INSERT INTO Visits (StudentInfo,Day) VALUES ('Joe Bloggs, Major: CS', '2025-04-15');
Get list of all visits, joined with faculty guides
SELECT Visits.VisitID,Visits.StudentInfo,Users.name FROM Visits LEFT JOIN Users ON Visits.UserID=Users.UserID;
Delete a visit
DELETE FROM Visits WHERE VisitID='1';
Visit detail window:
Get committment levels for all faculty for a given visit
SELECT VisitID, Users.UserID, Name, Email FROM Visits_Users INNER JOIN Users ON Visits_Users.UserID=Users.UserID WHERE VisitID=2;
Find intersection of visit availability with each faculty availability
SELECT Users.UserID, Name, Visits.Availability & Users.Availability FROM Visits INNER JOIN Users WHERE VisitID=1; /* Note that this is using the bitwise and operator "&" because of the way we are storing availability. */
Set email frequency for a particular visit
UPDATE Visits SET NotificationFrequency=4 WHERE VisitID=2;
Set committment level for a given faculty member
INSERT INTO Visits_Users VALUES (1,1,'prefer not');
Claim a visit and a time
UPDATE Visits SET DecidedTime=4, Status='assigned' WHERE VisitID=1 AND Status='proposed';
INSERT INTO Visits_Users VALUES (1,1,'can do') ON CONFLICT (VisitID,UserID) DO UPDATE SET Willingness='can do' WHERE (VisitID,UserID)=(1,1);
Update visit details
UPDATE Visits SET UserID=1 WHERE VisitID=3;
User tab:
Get list of users, including faculty availability
SELECT * FROM Users;
Create new user
INSERT INTO Users(Name,Email,PasswordHash,IsAdmin,IsFaculty,IsCoordinator) VALUES ('DrKow', 'mkowalcz@nmu.edu', 'secret', TRUE, TRUE, TRUE);
INSERT INTO Users(Name,Email,PasswordHash,IsAdmin,IsFaculty,IsCoordinator) VALUES ('Randy', 'rappleto@nmu.edu', 'secret', FALSE, TRUE, FALSE);
Update user attributes
UPDATE Users SET PasswordHash='secret',IsAdmin=TRUE WHERE Name='DrKow';
Update faculty availability
UPDATE Users SET Availability=-9223372036854775801 WHERE Email='rappleto@nmu.edu';
Delete user
DELETE FROM Users WHERE UserID=2;
Update global settings
UPDATE Settings SET Value='5' WHERE Key='HyperlinkLifetime';
UPDATE Settings SET Value='5' WHERE Key='CoordinatorNotificationFrequency';
References:
https://stackoverflow.com/questions/7662/database-table-and-column-naming-conventions
https://dev.to/ovid/database-naming-standards-2061
https://stackoverflow.com/questions/3037188/naming-of-boolean-column-in-database-table
https://stackoverflow.com/questions/2300356/using-a-single-row-configuration-table-in-sql-server-database-bad-idea
https://www.sqlite.org/foreignkeys.html
https://www.sqlite.org/lang.html
Loading…
Cancel
Save