Initial Commit

This commit is contained in:
2025-10-02 10:08:38 -04:00
commit a21adf25be
13 changed files with 75400 additions and 0 deletions

10
.envrc Normal file
View File

@@ -0,0 +1,10 @@
export DIRENV_WARN_TIMEOUT=20s
eval "$(devenv direnvrc)"
# `use devenv` supports the same options as the `devenv shell` command.
#
# To silence the output, use `--quiet`.
#
# Example usage: use devenv --quiet --impure --option services.postgres.enable:bool true
use devenv

186
.gitignore vendored Normal file
View File

@@ -0,0 +1,186 @@
# Devenv
.devenv*
devenv.local.nix
# direnv
.direnv
# pre-commit
.pre-commit-config.yaml
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
# CS374-Database-Systems
A collection of homeworks, labs, and projects from the CS374 Database Systems
class at JMU.

111
create_load.py Normal file
View File

@@ -0,0 +1,111 @@
import os
import random
import psycopg
from dotenv import load_dotenv
from faker import Faker
_ = load_dotenv()
USERNAME = os.getenv("USERNAME")
PASSWORD = os.getenv("PASSWORD")
CONNSTR = (
f"host=data.cs.jmu.edu port=5432 dbname=sec2 user={USERNAME} password={PASSWORD}"
)
fake = Faker()
def make_releases() -> list[tuple[int, str, str, float, int]]:
releases: list[tuple[int, str, str, float, int]] = []
for i in range(0, 20):
title = fake.bs()
format = "CD"
sample_rate = 44.1
release_year = int(fake.year())
releases.append((i, title, format, sample_rate, release_year))
return releases
def make_tracks() -> list[tuple[int, str, float, str, int]]:
tracks: list[tuple[int, str, float, str, int]] = []
for i in range(0, 20):
title = fake.bs()
duration_sec = random.uniform(0.0, 1200.0)
track_artist = fake.name()
release_id = random.randint(0, 19)
tracks.append((i, title, duration_sec, track_artist, release_id))
return make_tracks()
def create_tables(cur: psycopg.Cursor):
with psycopg.connect(CONNSTR) as conn:
with conn.cursor() as cur:
_ = cur.execute(
"""
CREATE TABLE IF NOT EXISTS Release (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
format TEXT NOT NULL,
sample_rate_khz REAL,
release_year INTEGER NOT NULL
)
"""
)
_ = cur.execute(
"""
CREATE TABLE IF NOT EXISTS Track (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
duration_sec REAL NOT NULL,
track_artist TEXT,
release_id INTEGER,
FOREIGN KEY (release_id) REFERENCES Release(id)
)
"""
)
conn.commit()
def insert_table1():
with psycopg.connect(CONNSTR) as conn:
with conn.cursor() as cur:
cur.executemany(
"""
INSERT INTO Release (id, title, format, sample_rate_khz, release_year)
VALUES (%s, %s, %s, %s, %s)
""",
make_releases(),
)
conn.commit()
def insert_table2():
with psycopg.connect(CONNSTR) as conn:
with conn.cursor() as cur:
cur.executemany(
"""
INSERT INTO Track (id, title, duration_sec, track_artist, release_id)
VALUES (%s, %s, %s, %s, %s)
""",
make_tracks(),
)
conn.commit()
if __name__ == "__main__":
# Connect to postgres and create a cursor
with psycopg.connect(CONNSTR) as conn:
with conn.cursor() as cur:
create_tables(cur)

BIN
crud-operations/hw2.db Normal file

Binary file not shown.

295
crud-operations/hw2.py Normal file
View File

@@ -0,0 +1,295 @@
"""Practice writing CRUD queries using SQLite and Python's DB-API.
Author: Nicholas Tamassia
Version: 2025-09-08
"""
from pprint import pprint
import sqlite3
def connect(path):
"""Connect to the SQLite database file and return a cursor.
This function defines the global variables con and cur, which
you will use throughout the module.
THE CODE IS ALREADY FINISHED; DO NOT EDIT THIS FUNCTION.
Args:
path (str): File system path to the SQLite database file.
Returns:
sqlite3.Cursor: An object for executing SQL statements.
"""
global con, cur
con = sqlite3.connect(path)
cur = con.cursor()
cur.execute("PRAGMA foreign_keys = ON")
def create():
"""Execute SQL statements that create two tables of your choice.
Try to think of a unique example; no two students should have the
same table/column names and design. Your tables must have at least
five columns. At least one column must be an INTEGER, at least one
column must be a REAL number, and at least one column must be TEXT.
The first column of each table must be "id integer PRIMARY KEY".
Generally, this is not a good design, but it makes autograding the
assignment easier.
The second table must have a FOREIGN KEY reference to the first
table. Most but not all of the columns should be NOT NULL.
"""
cur.execute("""
CREATE TABLE IF NOT EXISTS Release (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
format TEXT NOT NULL,
sample_rate_khz REAL,
release_year INTEGER NOT NULL
)
""")
cur.execute("""
CREATE TABLE IF NOT EXISTS Track (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
duration_sec REAL NOT NULL,
track_artist TEXT,
release_id INTEGER,
FOREIGN KEY (release_id) REFERENCES Release(id)
)
""")
def drop():
"""Execute SQL statements that drop your tables, if they exist.
This function is called at the beginning of the __main__ block so
that you can run the program over and over again to test your code.
"""
cur.execute("DROP TABLE IF EXISTS Track")
cur.execute("DROP TABLE IF EXISTS Release")
def insert_sample():
"""Execute SQL statements that insert three rows into each table.
The rows you insert should have realistic data values that show an
example of what the data might look like in each table. Please write
one INSERT statement that inserts three rows, not three statements
that insert one row each. At least one of the text values must have
an apostrophe (Ex: "JMU's mascot is the Duke Dog").
Note: The id values (in the first column) should be automatically
generated by SQLite. Do not include the id column in your code.
"""
cur.execute("""
INSERT INTO Release (title, format, sample_rate_khz, release_year)
VALUES
('In Praise of Shadows', '2xCD', 44.1, 2016),
('Queen A''rcadia', 'CD', 44.1, 2015),
('Gravity Noize', 'Digital Media', 44.1, 2018);
""")
cur.execute("""
INSERT INTO Track (title, duration_sec, track_artist, release_id)
VALUES
('Monochrome', 583.275, 'Proteus', 1),
('Bloody Duchess', 231.321, '葉月ゆら', 2),
('Storm Coming', 443.6743, 'Einhander', 1);
""")
def insert(title: str, format: float, sample_rate_khz: str, release_year: int):
"""Execute an SQL statement that inserts a row into the first table.
The values must be passed as parameters to this function. If your
table has 10 columns, then this function should have 9 parameters.
As a matter of style, the parameter and column names must match.
Note: The id value (in the first column) should be automatically
generated by SQLite. Do not include the id column in your code.
TODO Add parameters to the function definition and the docstring.
Args:
title (str): The title of the relase
format (str): The format of the relase
sample_rate_khs (float): The sample rate in kHz of the relase
release_year (int): The year the release was released
"""
cur.execute("""
INSERT INTO Release (title, format, sample_rate_khz, release_year)
VALUES (?, ?, ?, ?)
""", (title, format, sample_rate_khz, release_year))
def select_all() -> list[tuple]:
"""Execute an SQL statement that selects all rows from the first table.
Returns:
list[tuple]: Each tuple represents a row of the table.
"""
return cur.execute("""
SELECT * FROM Release
""").fetchall()
def select(pk: int) -> tuple:
"""Execute an SQL statement that selects one row from the first table.
Args:
pk (int): The id of the row to select.
Returns:
tuple: The row for the specified pk, or None if not found.
"""
return cur.execute("""
SELECT * FROM Release WHERE Release.id = ?
""", (pk,)).fetchone()
def update(id: int, title: str, format: str, sample_rate_khz: float, release_year: int):
"""Execute an SQL statement that updates one row in the first table.
The values must be passed as parameters to this function. If your
table has 10 columns, then this function should have 10 parameters.
As a matter of style, the parameter and column names must match.
TODO Add parameters to the function definition and the docstring.
Args:
id (int): The id of the release to update
title (str): The title of the relase
format (str): The format of the relase
sample_rate_khs (float): The sample rate in kHz of the relase
release_year (int): The year the release was released
"""
cur.execute("""
UPDATE Release
SET title = ?, format = ?, sample_rate_khz = ?, release_year = ?
WHERE id = ?
""", (title, format, sample_rate_khz, release_year, id))
def delete(pk):
"""Execute an SQL statement that deletes one row from the first table.
Note that, because of the foreign key, you cannot delete a row that is
referenced by the second table. If needed, modify the insert_sample()
function to insert at least one row that is not related to the second
table. Use that row's id to test this function.
Args:
pk (int): The id of the row to delete.
"""
cur.execute("""
DELETE FROM Release WHERE id = ?
""", (pk,))
def insert_invalid():
"""Cause the foreign key constraint to be violated by inserting a row.
The purpose of this function is to demonstrate your understanding of
foreign keys. Execute an SQL statement that inserts an invalid row into
the second table. The values should be hard-coded -- don't use question
marks in the query. SQLite should raise an IntegrityError when you call
the cur.execute() method.
"""
cur.execute("""
INSERT INTO Track (title, duration_sec, track_artist, release_id)
VALUES ('Personalizer', 473.2374, 'Electro.muster vo.みとせのりこ', 8);
""")
def update_invalid():
"""Cause the foreign key constraint to be violated by updating a row.
The purpose of this function is to demonstrate your understanding of
foreign keys. Execute an SQL statement that updates a row in the second
table. SQLite should raise an IntegrityError. The query values should be
hard-coded -- don't use question marks.
"""
cur.execute("""
UPDATE Track
SET release_id = 8
WHERE title = 'Storm Coming'
""")
def delete_invalid():
"""Cause the foreign key constraint to be violated by deleting a row.
The purpose of this function is to demonstrate your understanding of
foreign keys. Execute an SQL statement that deletes a row in the first
table. SQLite should raise an IntegrityError. The query values should be
hard-coded -- don't use question marks.
"""
cur.execute("""
DELETE FROM Release
WHERE title = 'In Praise of Shadows'
""")
if __name__ == "__main__":
# Feel free to modify the path to your SQLite database file.
# The autograder will use a different path for the database.
connect("hw2.db")
# The following code is provided to test your functions before submitting.
# TODO Be sure to add the arguments required for insert() and update().
drop()
create()
insert_sample()
pprint(select_all())
print()
insert("The Personalizer", "CD", 44.1, 2012)
pprint(select(2))
print()
update(4, "The Personalizer [リクエスト盤]", "CD", 44.1, 2012)
delete(4)
pprint(select_all())
print()
# The following tests make sure that your "invalid" functions work.
try:
insert_invalid()
print("insert_invalid doesn't work")
except sqlite3.IntegrityError:
pass
try:
update_invalid()
print("update_invalid doesn't work")
except sqlite3.IntegrityError:
pass
try:
delete_invalid()
print("delete_invalid doesn't work")
except sqlite3.IntegrityError:
pass

103
devenv.lock Normal file
View File

@@ -0,0 +1,103 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1759178241,
"owner": "cachix",
"repo": "devenv",
"rev": "11aec9c56d7538301edb74e01b86d2f5ada42996",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1758108966,
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1758532697,
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "207a4cb0e1253c7658c6736becc6eb9cace1f25f",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": [
"git-hooks"
]
}
}
},
"root": "root",
"version": 7
}

30
devenv.nix Normal file
View File

@@ -0,0 +1,30 @@
{ pkgs, ... }:
{
# https://devenv.sh/packages/
packages = [ pkgs.git ];
# https://devenv.sh/languages/
languages.python = {
enable = true;
venv = {
enable = true;
requirements = ''
Faker==37.8.0
psycopg==3.2.10
psycopg-binary==3.2.10
python-dotenv==1.1.1
tzdata==2025.2
'';
};
};
# https://devenv.sh/services/
# services.postgres.enable = true;
enterShell = ''
echo "Welcome to CS374-Database-Systems"
'';
# See full reference at https://devenv.sh/reference/options/
}

15
devenv.yaml Normal file
View File

@@ -0,0 +1,15 @@
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
inputs:
nixpkgs:
url: github:cachix/devenv-nixpkgs/rolling
# If you're using non-OSS software, you can set allowUnfree to true.
# allowUnfree: true
# If you're willing to use a package that's vulnerable
# permittedInsecurePackages:
# - "openssl-1.1.1w"
# If you have more than one devenv you can merge them
#imports:
# - ./backend

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
python-dbapi/vdoe.db Normal file

Binary file not shown.

141
python-dbapi/vdoe.py Normal file
View File

@@ -0,0 +1,141 @@
"""Analyze SOL test pass rates and other results provided by VDOE.
Author: Nicholas Tamassia
Version: 2.9.2025
"""
import csv
import sqlite3
# TODO add your functions here (see the lab instructions)
def create_tables():
_ = cur.execute("DROP TABLE IF EXISTS participation")
_ = cur.execute(
"""
CREATE TABLE participation (
div_num integer,
div_name text,
sch_num integer,
sch_name text,
sch_type text,
low_grade text,
high_grade text,
subject text,
subgroup text,
number_tested integer,
number_students integer,
part_rate_2324 real
)
"""
)
_ = cur.execute("DROP TABLE IF EXISTS test_results")
_ = cur.execute(
"""
CREATE TABLE test_results (
div_num integer,
div_name text,
sch_num integer,
sch_name text,
sch_type text,
low_grade text,
high_grade text,
subject text,
grade_level text,
test_name text,
pass_rate_2122 integer,
pass_rate_2223 integer,
pass_rate_2324 integer,
adv_rate_2122 integer,
adv_rate_2223 integer,
adv_rate_2324 integer
)"""
)
con.commit()
def import_data():
with open("School-Participation_rates_23_24.csv", newline="") as file:
reader = csv.reader(file)
_ = next(reader) # skip header row
for row in reader:
_ = cur.execute(
"""INSERT INTO participation
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
row,
)
with open("School_Test_by_level_2023_2024.csv", newline="") as file:
reader = csv.reader(file)
_ = next(reader) # skip header row
for row in reader:
_ = cur.execute(
"""INSERT INTO test_results
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
row,
)
con.commit()
def query_school(div_num: int, sch_num: int):
# Query the participation rates
res = cur.execute(
"""
SELECT div_name, sch_name, subject, number_tested, number_students
FROM participation
WHERE div_num = ?
AND sch_num = ?
AND subgroup = 'All Students'
""",
(div_num, sch_num),
)
students_tested: list[tuple[str, str, str, int, int]] = res.fetchall()
print()
print(f"Results for {students_tested[0][1]}, {students_tested[0][0]}")
print()
for row in students_tested:
print(f"Subject: {row[2]}, Tested: {row[3]}/{row[4]}")
res = cur.execute(
"""
SELECT subject, grade_level, test_name, pass_rate_2324
FROM test_results
WHERE div_num = ?
AND sch_num = ?
""",
(div_num, sch_num),
)
data: list[tuple[str, int, str, float | str | None]] = res.fetchall()
print()
for row in data:
if row[3] is not None and row[3] != "<":
print(f"{row[0]}, {row[1]}, {row[2]}, 2023-24 Pass Rate: {row[3]}")
print()
def update_school(div_num: int, sch_num: int):
print("Hacking database...", end="")
_ = cur.execute(
"""
UPDATE test_results
SET pass_rate_2324 = 100, adv_rate_2324 = 100
WHERE div_num = ?
AND sch_num = ?
""",
(div_num, sch_num),
)
con.commit()
print("success!\nHave a nice day.")
# DO NOT EDIT THESE VARIABLES; use them in your functions.
# Connect to the SQLite database file and create a cursor.
if __name__ == "__main__":
con = sqlite3.connect("vdoe.db")
cur = con.cursor()
create_tables()
import_data()
div_num = int(input("Enter division number: "))
sch_num = int(input("Enter school number: "))
query_school(div_num, sch_num)
update_school(div_num, sch_num)