From 4cb02fa8f15a8e90a523e6db7630f5aece616504 Mon Sep 17 00:00:00 2001 From: tboyle252-sudo Date: Fri, 10 Oct 2025 13:59:03 +0000 Subject: [PATCH] Assignment completed --- lesson_25/createdb/add_users.py | 78 ++++++++++++++++++ lesson_25/createdb/test_queries.py | 60 ++++++++++++++ .../lesson25/models/LibraryDataModel.java | 9 +- .../main/resources/queries/thomasboyle.sql | 21 +++++ .../db_app/src/main/resources/sqlite/data.db | Bin 16384 -> 28672 bytes 5 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 lesson_25/createdb/add_users.py create mode 100644 lesson_25/createdb/test_queries.py create mode 100644 lesson_25/db/db_app/src/main/resources/queries/thomasboyle.sql diff --git a/lesson_25/createdb/add_users.py b/lesson_25/createdb/add_users.py new file mode 100644 index 000000000..142a9ab3d --- /dev/null +++ b/lesson_25/createdb/add_users.py @@ -0,0 +1,78 @@ +import sqlite3 +import bcrypt +import uuid + +# Create a connection to the SQLite database +conn = sqlite3.connect('../db/db_app/src/main/resources/sqlite/data.db') +cursor = conn.cursor() + +# Create the library_users table +cursor.execute(''' +CREATE TABLE IF NOT EXISTS library_users ( + id TEXT PRIMARY KEY, + email TEXT NOT NULL UNIQUE, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + password TEXT NOT NULL +) +''') + +# Sample users data +users = [ + { + 'id': str(uuid.uuid4()), + 'email': 'john.doe@example.com', + 'first_name': 'John', + 'last_name': 'Doe', + 'password': 'password123' + }, + { + 'id': str(uuid.uuid4()), + 'email': 'jane.smith@example.com', + 'first_name': 'Jane', + 'last_name': 'Smith', + 'password': 'securepass456' + }, + { + 'id': str(uuid.uuid4()), + 'email': 'mike.johnson@example.com', + 'first_name': 'Mike', + 'last_name': 'Johnson', + 'password': 'mypassword789' + }, + { + 'id': str(uuid.uuid4()), + 'email': 'sarah.wilson@example.com', + 'first_name': 'Sarah', + 'last_name': 'Wilson', + 'password': 'libraryuser2024' + }, + { + 'id': str(uuid.uuid4()), + 'email': 'admin@library.org', + 'first_name': 'Library', + 'last_name': 'Admin', + 'password': 'adminpass2024' + } +] + +# Insert users with bcrypt hashed passwords +for user in users: + # Hash the password using bcrypt + password_bytes = user['password'].encode('utf-8') + salt = bcrypt.gensalt() + hashed_password = bcrypt.hashpw(password_bytes, salt) + + cursor.execute(''' + INSERT OR REPLACE INTO library_users (id, email, first_name, last_name, password) + VALUES (?, ?, ?, ?, ?) + ''', (user['id'], user['email'], user['first_name'], user['last_name'], hashed_password.decode('utf-8'))) + +# Commit the changes and close the connection +conn.commit() +conn.close() + +print("Library users table created and populated with 5 users!") +print("Users created:") +for user in users: + print(f"- {user['first_name']} {user['last_name']} ({user['email']})") diff --git a/lesson_25/createdb/test_queries.py b/lesson_25/createdb/test_queries.py new file mode 100644 index 000000000..a613ceecd --- /dev/null +++ b/lesson_25/createdb/test_queries.py @@ -0,0 +1,60 @@ +import sqlite3 + +# Connect to the database +conn = sqlite3.connect('../db/db_app/src/main/resources/sqlite/data.db') +cursor = conn.cursor() + +print("=== Testing SQL Queries ===\n") + +# Query 1: Count of media items by type +print("Query 1: Count of media items by type") +cursor.execute(""" +SELECT type, COUNT(*) as count +FROM media_items +GROUP BY type +ORDER BY count DESC; +""") +results = cursor.fetchall() +for row in results: + print(f" {row[0]}: {row[1]}") +print() + +# Query 2: Sum of total pages checked out by guests +print("Query 2: Sum of total pages checked out by guests") +cursor.execute(""" +SELECT SUM(mi.pages) as total_pages_checked_out +FROM checked_out_items co +JOIN media_items mi ON co.item_id = mi.id +WHERE mi.pages IS NOT NULL AND mi.pages > 0; +""") +result = cursor.fetchone() +print(f" Total pages checked out: {result[0] if result[0] else 0}") +print() + +# Query 3: Show all 5 guests and any corresponding records in the checked_out_items table +print("Query 3: Show all 5 guests and any corresponding records in the checked_out_items table") +cursor.execute(""" +SELECT g.name, g.email, g.type, co.item_id, co.due_date +FROM guests g +LEFT JOIN checked_out_items co ON g.email = co.email +ORDER BY g.name; +""") +results = cursor.fetchall() +for row in results: + item_id = row[3] if row[3] else "None" + due_date = row[4] if row[4] else "None" + print(f" {row[0]} ({row[1]}) [{row[2]}] - Item: {item_id}, Due: {due_date}") +print() + +# Bonus: Show library users +print("Bonus: Library Users") +cursor.execute(""" +SELECT id, email, first_name, last_name +FROM library_users +ORDER BY last_name, first_name; +""") +results = cursor.fetchall() +for row in results: + print(f" {row[2]} {row[3]} ({row[1]}) - ID: {row[0][:8]}...") + +conn.close() diff --git a/lesson_25/db/db_app/src/main/java/com/codedifferently/lesson25/models/LibraryDataModel.java b/lesson_25/db/db_app/src/main/java/com/codedifferently/lesson25/models/LibraryDataModel.java index 6c268f962..36f800673 100644 --- a/lesson_25/db/db_app/src/main/java/com/codedifferently/lesson25/models/LibraryDataModel.java +++ b/lesson_25/db/db_app/src/main/java/com/codedifferently/lesson25/models/LibraryDataModel.java @@ -1,13 +1,5 @@ package com.codedifferently.lesson25.models; -import com.codedifferently.lesson25.library.Book; -import com.codedifferently.lesson25.library.Dvd; -import com.codedifferently.lesson25.library.Librarian; -import com.codedifferently.lesson25.library.LibraryGuest; -import com.codedifferently.lesson25.library.Magazine; -import com.codedifferently.lesson25.library.MediaItem; -import com.codedifferently.lesson25.library.Newspaper; -import com.codedifferently.lesson25.library.Patron; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -17,6 +9,7 @@ public class LibraryDataModel { public List mediaItems; public List guests; + public List users; public List getMediaItems() { List results = new ArrayList<>(); diff --git a/lesson_25/db/db_app/src/main/resources/queries/thomasboyle.sql b/lesson_25/db/db_app/src/main/resources/queries/thomasboyle.sql new file mode 100644 index 000000000..0494e629f --- /dev/null +++ b/lesson_25/db/db_app/src/main/resources/queries/thomasboyle.sql @@ -0,0 +1,21 @@ +-- SQL Queries for Lesson 25 Database Assignment +-- Author: GitHub Copilot +-- Date: October 10, 2025 + +-- Query 1: Count of media items by type +SELECT type, COUNT(*) as count +FROM media_items +GROUP BY type +ORDER BY count DESC; + +-- Query 2: Sum of total pages checked out by guests +SELECT SUM(mi.pages) as total_pages_checked_out +FROM checked_out_items co +JOIN media_items mi ON co.item_id = mi.id +WHERE mi.pages IS NOT NULL AND mi.pages > 0; + +-- Query 3: Show all 5 guests and any corresponding records in the checked_out_items table +SELECT g.name, g.email, g.type, co.item_id, co.due_date +FROM guests g +LEFT JOIN checked_out_items co ON g.email = co.email +ORDER BY g.name; \ No newline at end of file diff --git a/lesson_25/db/db_app/src/main/resources/sqlite/data.db b/lesson_25/db/db_app/src/main/resources/sqlite/data.db index 8baa982d2b27c50808a4c569a14c47972c41a695..ca2e5a9032f8e767aa43d1d6afcf4aef3eaebf08 100644 GIT binary patch delta 1452 zcma)5OK;*<6owE&CknWkibiRwib|0(m15)fqtY}(f?>dr@URnzG(y+*H5d#|FvOwN zl(>s_n>cu3dK1P5;2uCS=s8YQ>c--S0enzH`2Fudc#ZzlX24*3+R- zDCU3n=d+t#YBL?eq?>r66k1t(7ec;D{Fac{-X+%KzrOZC#|sqht2~KJ*bHpSxm{9{gRk^;7UDNP5H;vQ?l5QQNy(BY+XZkZ$40^^ZA!>#x9>p`C_@;weS$EmZedeByp67z`qF`%^9kW8w><` z-yA%fm%!{{yL6{dCa`al>NY`c=O$-jmdYE)FxzwZhP^N3yXmp549<^wJ^3Wx2NhTA zmdBcrr6yB+B6aC50ld}anDTUE(~IgHgqqH=D5t8FU!C=NFdB`r0s{$6r&M0!954hO z%rz~?9z27WpnqmTOtbs-zp<0y?2jL!zgeKrI~K@D&^LHEtx z?R7diEt@@9v^xWz)V%trz#N`5p0~^FMYYr$PM)90VrFcg>lD_MI=M#S;H++qiPO$u z-NiaN!?nKF$KJ|POc9d4BnB&xwC<~+Yn+bKD&SCo;|Y{yaRX-sl>@xc1p|mVeRI^g z{dsR~TJ&K(KywCzEYYm>N0ohGo0u-O1ruv)<72yes>+x0Ak*828KT)OI?`#*<*Nre zjk&D16pkrO@*^)w;iPVG1oU-)3`!e}hN?WtqnZkFhGTevpxLh9GN#)w5aPwX62Tm@ zHk`At^|EF0>_rFT8VaoE?YvYsj~GdolyZkUDl|p+f^Sww6RXLIY8$jC)bL<6*jR)P zAvE$9`5t+J{P^bc)Sro)Yi9Z+qJ$UO*Ju#9$U-d#fs1Gz2?AS-2(z>kQ64Qazq>wP zhLD%YFUTLrE97?G=eJ)bBkAzJ-dyz4$kXtDy@2JwIbXLeZG**iVBZ-H;3@8 GF$4fGP78_v