Initial Commit
This commit is contained in:
10
.envrc
Normal file
10
.envrc
Normal 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
186
.gitignore
vendored
Normal 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
4
README.md
Normal 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
111
create_load.py
Normal 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
BIN
crud-operations/hw2.db
Normal file
Binary file not shown.
295
crud-operations/hw2.py
Normal file
295
crud-operations/hw2.py
Normal 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
103
devenv.lock
Normal 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
30
devenv.nix
Normal 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
15
devenv.yaml
Normal 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
|
||||
56064
python-dbapi/School-Participation_rates_23_24.csv
Normal file
56064
python-dbapi/School-Participation_rates_23_24.csv
Normal file
File diff suppressed because it is too large
Load Diff
18441
python-dbapi/School_Test_by_level_2023_2024.csv
Normal file
18441
python-dbapi/School_Test_by_level_2023_2024.csv
Normal file
File diff suppressed because it is too large
Load Diff
BIN
python-dbapi/vdoe.db
Normal file
BIN
python-dbapi/vdoe.db
Normal file
Binary file not shown.
141
python-dbapi/vdoe.py
Normal file
141
python-dbapi/vdoe.py
Normal 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)
|
||||
Reference in New Issue
Block a user