diff --git a/task-1/schema.sql b/task-1/schema.sql index a3b443b..5122d20 100644 --- a/task-1/schema.sql +++ b/task-1/schema.sql @@ -1 +1,66 @@ --- Write here your DDL statements to create the tables for the database. \ No newline at end of file +-- Write here your DDL statements to create the tables for the database. +CREATE TABLE members ( + member_id SERIAL PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, + phone TEXT, + address TEXT +); + +CREATE TABLE library_cards ( + card_id SERIAL PRIMARY KEY, + card_number TEXT UNIQUE NOT NULL, + issued_on DATE NOT NULL, + expires_on DATE NOT NULL CHECK (expires_on > issued_on), + member_id INT UNIQUE NOT NULL REFERENCES members(member_id) +); + +CREATE TABLE publishers ( + publisher_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); + +CREATE TABLE books ( + book_id SERIAL PRIMARY KEY, + isbn TEXT UNIQUE NOT NULL, + title TEXT NOT NULL, + publisher_id INT REFERENCES publishers(publisher_id) +); +CREATE TABLE authors ( + author_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); +CREATE TABLE book_authors ( + book_id INT NOT NULL REFERENCES books(book_id), + author_id INT NOT NULL REFERENCES authors(author_id), + PRIMARY KEY (book_id, author_id) +); +CREATE TABLE tags ( + tag_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); +CREATE TABLE book_tags ( + book_id INT NOT NULL REFERENCES books(book_id), + tag_id INT NOT NULL REFERENCES tags(tag_id), + PRIMARY KEY (book_id, tag_id) +); +CREATE TABLE copies ( + copy_id SERIAL PRIMARY KEY, + barcode TEXT UNIQUE NOT NULL, + shelf_code TEXT, + book_id INT NOT NULL REFERENCES books(book_id) +); + +CREATE TABLE borrowings ( + borrowing_id SERIAL PRIMARY KEY, + copy_id INT NOT NULL REFERENCES copies(copy_id), + member_id INT NOT NULL REFERENCES members(member_id), + borrowed_at TIMESTAMP NOT NULL, + due_date TIMESTAMP NOT NULL, + returned_at TIMESTAMP, + fine_eur NUMERIC DEFAULT 0 CHECK (fine_eur >= 0), + CHECK (returned_at IS NULL OR returned_at >= borrowed_at) + +); + + diff --git a/task-2/src/main/java/org/hyf/Main.java b/task-2/src/main/java/org/hyf/Main.java index 7be95f2..fd97856 100644 --- a/task-2/src/main/java/org/hyf/Main.java +++ b/task-2/src/main/java/org/hyf/Main.java @@ -1,7 +1,204 @@ package org.hyf; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.PreparedStatement; + public class Main { + + private static Connection getConnection() throws SQLException { + String url = "jdbc:postgresql://localhost:5432/library_db"; + String user = "postgres"; + String pass = "postgres"; + return DriverManager.getConnection(url, user, pass); + } + + // Inset Data + public static void insertData() { + try (Connection conn = getConnection()) { + + // Publisher 2 rows + PreparedStatement pub = conn.prepareStatement( + "INSERT INTO publishers (name) VALUES (?) ON CONFLICT (name) DO NOTHING" + ); + pub.setString(1, "O'Reilly"); + pub.executeUpdate(); + pub.setString(1, "Addison-Wesley"); + pub.executeUpdate(); + + // Authors 2 rows + PreparedStatement auth = conn.prepareStatement( + "INSERT INTO authors (name) VALUES (?) ON CONFLICT (name) DO NOTHING" + ); + + //row 1 + auth.setString(1, "Douglas Crockford"); + auth.executeUpdate(); + + //row 2 + auth.setString(1, "Eric Freeman"); + auth.executeUpdate(); + + // Books + PreparedStatement book = conn.prepareStatement( + "INSERT INTO books (isbn, title, publisher_id) VALUES (?, ?, ?) ON CONFLICT (isbn) DO NOTHING" + ); + + // row 1 + book.setString(1, "9780596517748"); + book.setString(2, "JavaScript: The Good Parts"); + book.setInt(3, 1); + book.executeUpdate(); + + // row 2 + book.setString(1, "9780596007126"); + book.setString(2, "Head First Design Patterns"); + book.setInt(3, 1); + book.executeUpdate(); + + + // Members + PreparedStatement mem = conn.prepareStatement( + "INSERT INTO members (email, name, phone, address) VALUES (?, ?, ?, ?) ON CONFLICT (email) DO NOTHING" + ); + + //row 1 + mem.setString(1, "omar@example.com"); + mem.setString(2, "Omar"); + mem.setString(3, "+31689012345"); + mem.setString(4, "Rijnkade 19, Utrecht"); + mem.executeUpdate(); + + //row 2 + mem.setString(1, "tom@example.com"); + mem.setString(2, "Tom"); + mem.setString(3, "+31645678901"); + mem.setString(4, "Biltstraat 88, Utrecht"); + mem.executeUpdate(); + + // Library Cards + PreparedStatement card = conn.prepareStatement( + "INSERT INTO library_cards (card_number, issued_on, expires_on, member_id) VALUES (?, ?, ?, ?) ON CONFLICT (card_number) DO NOTHING" + ); + + // row 1 + card.setString(1, "C-1008"); + card.setDate(2, java.sql.Date.valueOf("2024-01-30")); + card.setDate(3, java.sql.Date.valueOf("2027-01-30")); + card.setInt(4, 1); + card.executeUpdate(); + + //row 2 + card.setString(1, "C-1004"); + card.setDate(2, java.sql.Date.valueOf("2023-11-20")); + card.setDate(3, java.sql.Date.valueOf("2026-11-20")); + card.setInt(4, 2); + card.executeUpdate(); + + // Copies + PreparedStatement copy = conn.prepareStatement( + "INSERT INTO copies (barcode, shelf_code, book_id) VALUES (?, ?, ?) ON CONFLICT (barcode) DO NOTHING" + ); + + // row 1 + copy.setString(1, "BC-0011"); + copy.setString(2, "B-03"); + copy.setInt(3, 1); + copy.executeUpdate(); + + //row 2 + copy.setString(1, "BC-0013"); + copy.setString(2, "B-03"); + copy.setInt(3, 1); + copy.executeUpdate(); + + // Borrowings + PreparedStatement bor = conn.prepareStatement( + "INSERT INTO borrowings (copy_id, member_id, borrowed_at, due_date, returned_at, fine_eur) " + + "VALUES (?, ?, ?, ?, ?, ?)" + ); + + // row 1 Omar + bor.setInt(1, 1); + bor.setInt(2, 1); + bor.setTimestamp(3, java.sql.Timestamp.valueOf("2025-12-02 08:08:00")); + bor.setTimestamp(4, java.sql.Timestamp.valueOf("2025-12-23 08:08:00")); + bor.setTimestamp(5, java.sql.Timestamp.valueOf("2025-12-13 08:08:00")); + bor.setBigDecimal(6, new java.math.BigDecimal("0.00")); + bor.executeUpdate(); + + //row 2 Tom + bor.setInt(1, 2); + bor.setInt(2, 2); + bor.setTimestamp(3, java.sql.Timestamp.valueOf("2026-01-10 08:51:00")); + bor.setTimestamp(4, java.sql.Timestamp.valueOf("2026-01-31 08:51:00")); + bor.setTimestamp(5, java.sql.Timestamp.valueOf("2026-01-25 08:51:00")); + bor.setBigDecimal(6, new java.math.BigDecimal("0.00")); + bor.executeUpdate(); + + System.out.println("Inserted 2 rows per table."); + + } catch (SQLException e) { + e.printStackTrace(); + + } + + } + + // Fetch Data + public static void fetchData() { + String sql = """ + SELECT + b.title AS book_title, + p.name AS publisher_name, + c.barcode AS copy_barcode, + m.name AS member_name, + br.borrowed_at, + br.returned_at + FROM borrowings br + JOIN copies c ON br.copy_id = c.copy_id + JOIN books b ON c.book_id = b.book_id + JOIN publishers p ON b.publisher_id = p.publisher_id + JOIN members m ON br.member_id = m.member_id + ORDER BY br.borrowed_at + LIMIT 10 + """; + + try (Connection conn = getConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + + System.out.println("\n BORROWING RECORDS "); + System.out.println("---------------------------"); + + while (rs.next()) { + String title = rs.getString("book_title"); + String publisher = rs.getString("publisher_name"); + String barcode = rs.getString("copy_barcode"); + String member = rs.getString("member_name"); + String borrowedAt = rs.getString("borrowed_at"); + String returnedAt = rs.getString("returned_at"); + + System.out.println( + "Book: " + title + + " | Publisher: " + publisher + + " | Copy: " + barcode + + " | Member: " + member + + " | Borrowed: " + borrowedAt + + " | Returned: " + returnedAt + ); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + + } + public static void main(String[] args) { - System.out.println("You code goes here :) You can overwrite this entire method."); + insertData(); + fetchData(); } }