project-init

This commit is contained in:
srikar committed 2026-09-25 08:14:04 -07:00
commit 65691a0aee
7 files changed
+897

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
"""
Database layer: connect to MySQL, verify/create the student_db database,
and verify/create the STUDENT, GUARDIAN and ATTENDANCE tables per the
schema (Tables 9.3, 9.4, 9.5).
Schema notes:
- GUARDIAN.GUID is the primary key (12-digit Aadhaar number, stored as CHAR(12)).
- STUDENT.GUID is a foreign key referencing GUARDIAN.GUID.
- ATTENDANCE has a composite primary key (AttendanceDate, RollNumber), and
RollNumber is also a foreign key referencing STUDENT.RollNumber.
- Because STUDENT references GUARDIAN, GUARDIAN must be created first.
"""
import sys
import pymysql
import pymysql.cursors
import config
# Table creation statements, in dependency order (GUARDIAN -> STUDENT -> ATTENDANCE)
TABLE_DEFINITIONS = {
"GUARDIAN": """
CREATE TABLE GUARDIAN (
GUID CHAR(12) NOT NULL,
GName VARCHAR(20) NOT NULL,
GPhone CHAR(10) NULL,
GAddress VARCHAR(30) NOT NULL,
PRIMARY KEY (GUID),
UNIQUE (GPhone)
) ENGINE=InnoDB
""",
"STUDENT": """
CREATE TABLE STUDENT (
RollNumber INT NOT NULL,
SName VARCHAR(20) NOT NULL,
SDateofBirth DATE NOT NULL,
GUID CHAR(12) NOT NULL,
PRIMARY KEY (RollNumber),
FOREIGN KEY (GUID) REFERENCES GUARDIAN(GUID)
ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB
""",
"ATTENDANCE": """
CREATE TABLE ATTENDANCE (
AttendanceDate DATE NOT NULL,
RollNumber INT NOT NULL,
AttendanceStatus CHAR(1) NOT NULL,
PRIMARY KEY (AttendanceDate, RollNumber),
FOREIGN KEY (RollNumber) REFERENCES STUDENT(RollNumber)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT chk_attendance_status CHECK (AttendanceStatus IN ('P', 'A'))
) ENGINE=InnoDB
""",
}
# Creation order matters because of foreign keys.
TABLE_ORDER = ["GUARDIAN", "STUDENT", "ATTENDANCE"]
def connect_server(database=None):
"""Connect to the MySQL server (optionally selecting a database)."""
try:
conn = pymysql.connect(
host=config.DB_HOST,
port=config.DB_PORT,
user=config.DB_USER,
password=config.DB_PASSWORD,
database=database,
connect_timeout=config.DB_CONNECT_TIMEOUT,
cursorclass=pymysql.cursors.DictCursor,
autocommit=False,
)
return conn
except pymysql.err.OperationalError as e:
print(f"\n[ERROR] Could not connect to MySQL server at "
f"{config.DB_HOST}:{config.DB_PORT} as user '{config.DB_USER}'.")
print(f" Details: {e}")
sys.exit(1)
def ensure_database():
"""Verify the student_db database exists; create it if it does not."""
conn = connect_server(database=None)
try:
with conn.cursor() as cur:
cur.execute("SHOW DATABASES LIKE %s", (config.DB_NAME,))
exists = cur.fetchone() is not None
if exists:
print(f"[OK] Database '{config.DB_NAME}' found.")
else:
print(f"[..] Database '{config.DB_NAME}' not found. Creating it...")
cur.execute(
f"CREATE DATABASE `{config.DB_NAME}` "
"CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
)
conn.commit()
print(f"[OK] Database '{config.DB_NAME}' created.")
finally:
conn.close()
def ensure_tables(conn):
"""Verify each required table exists; create any that are missing."""
with conn.cursor() as cur:
cur.execute("SHOW TABLES")
existing = {row[f"Tables_in_{config.DB_NAME}"] for row in cur.fetchall()}
for table in TABLE_ORDER:
if table in existing:
print(f"[OK] Table '{table}' found.")
else:
print(f"[..] Table '{table}' not found. Creating it...")
with conn.cursor() as cur:
cur.execute(TABLE_DEFINITIONS[table])
conn.commit()
print(f"[OK] Table '{table}' created.")
def get_connection():
"""
Full startup sequence:
1. Ensure the student_db database exists (creating it if needed).
2. Connect to student_db.
3. Ensure all required tables exist (creating any that are missing).
Returns an open connection to student_db, ready for use.
"""
print(f"Connecting to MySQL server at {config.DB_HOST}:{config.DB_PORT} ...")
ensure_database()
conn = connect_server(database=config.DB_NAME)
print(f"[OK] Connected to database '{config.DB_NAME}'.")
ensure_tables(conn)
return conn