diff --git a/Week1/databases/connectDatabases.js b/Week1/databases/connectDatabases.js new file mode 100644 index 000000000..cde9b1fd0 --- /dev/null +++ b/Week1/databases/connectDatabases.js @@ -0,0 +1,21 @@ +import pkg from "pg"; +const { Client } = pkg; + +export async function connectDB(database = "world") { + const client = new Client({ + user: "hyfuser", + host: "localhost", + database: database, + password: "hyfpassword", + port: 5432, + }); + + try { + await client.connect(); + console.log(`Connected to database: ${client.database}`); + return client; + } catch (error) { + console.error("Connection error:", error); + throw error; + } +} diff --git a/Week1/databases/exercise2_world.js b/Week1/databases/exercise2_world.js new file mode 100644 index 000000000..8cb8fa169 --- /dev/null +++ b/Week1/databases/exercise2_world.js @@ -0,0 +1,64 @@ +import { connectDB } from "./connectDatabase.js"; + +async function runQueries() { + const client = await connectDB("world"); + + try { + const q1 = await client.query( + `SELECT name FROM country WHERE population > 8000000;` + ); + console.log("1. Countries > 8M:", q1.rows); + + const q2 = await client.query( + `SELECT name FROM country WHERE name ILIKE '%land%';` + ); + console.log("2. Countries with 'land':", q2.rows); + + const q3 = await client.query( + `SELECT name FROM city WHERE population BETWEEN 500000 AND 1000000;` + ); + console.log("3. Cities 500k–1M:", q3.rows); + + const q4 = await client.query( + `SELECT name FROM country WHERE continent = 'Europe';` + ); + console.log("4. European countries:", q4.rows); + + const q5 = await client.query( + `SELECT name FROM country ORDER BY surfacearea DESC;` + ); + console.log("5. Countries by surface area DESC:", q5.rows); + + const q6 = await client.query( + `SELECT name FROM city WHERE countrycode = 'NLD';` + ); + console.log("6. Cities in Netherlands:", q6.rows); + + const q7 = await client.query( + `SELECT population FROM city WHERE name = 'Rotterdam';` + ); + console.log("7. Population of Rotterdam:", q7.rows); + + const q8 = await client.query(` + SELECT name FROM country ORDER BY surfacearea DESC LIMIT 10; + `); + console.log("8. Top 10 countries by surface area:", q8.rows); + + const q9 = await client.query(` + SELECT name FROM city ORDER BY population DESC LIMIT 10; + `); + console.log("9. Top 10 most populated cities:", q9.rows); + + const q10 = await client.query( + `SELECT SUM(population) AS world_population FROM country;` + ); + console.log("10. World population:", q10.rows[0].world_population); + } catch (err) { + console.error("Query error:", err); + } finally { + await client.end(); + console.log("Connection closed."); + } +} + +runQueries(); diff --git a/Week1/databases/setupMeetup.js b/Week1/databases/setupMeetup.js new file mode 100644 index 000000000..e9bcae8f4 --- /dev/null +++ b/Week1/databases/setupMeetup.js @@ -0,0 +1,97 @@ +import pkg from "pg"; +const { Client } = pkg; + +const defaultClient = new Client({ + user: "hyfuser", + host: "localhost", + database: "postgres", + password: "hyfpassword", + port: 5432, +}); + +async function setupDatabase() { + let client; + try { + await defaultClient.connect(); + + await defaultClient.query(`DROP DATABASE IF EXISTS meetup;`); + await defaultClient.query(`CREATE DATABASE meetup;`); + console.log('Database "meetup" created.'); + + await defaultClient.end(); + + client = new Client({ + user: "hyfuser", + host: "localhost", + database: "meetup", + password: "hyfpassword", + port: 5432, + }); + await client.connect(); + + await client.query(` + CREATE TABLE Invitee ( + invitee_no INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + invitee_name VARCHAR(100), + invited_by VARCHAR(100) + ); + `); + + await client.query(` + CREATE TABLE Room ( + room_no INT PRIMARY KEY, + room_name VARCHAR(64), + floor_number SMALLINT + ); + `); + + await client.query(` + CREATE TABLE Meeting ( + meeting_no INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + meeting_title VARCHAR(64), + starting_time TIMESTAMP, + ending_time TIMESTAMP, + room_no INT REFERENCES Room(room_no) + ); + `); + + console.log("Tables created."); + + await client.query(` + INSERT INTO Invitee (invitee_name, invited_by) VALUES + ('Alice Johnson', 'Bob Smith'), + ('Bob Smith', 'Carol White'), + ('Carol White', 'David Lee'), + ('David Lee', 'Alice Johnson'), + ('Eve Brown', 'Bob Smith'); +`); + + await client.query(` + INSERT INTO Room (room_name, floor_number) VALUES + ('Blue Room', 1), + ('Green Room', 1), + ('Yellow Room', 2), + ('Red Room', 2), + ('Conference Hall', 3); + `); + + await client.query(` + INSERT INTO Meeting (meeting_title, starting_time, ending_time, room_no) VALUES + ('Project Kickoff', '2025-09-01 09:00:00', '2025-09-01 10:00:00', 1), + ('Design Review', '2025-09-02 11:00:00', '2025-09-02 12:30:00', 2), + ('Team Standup', '2025-09-03 09:30:00', '2025-09-03 10:00:00', 3), + ('Client Presentation', '2025-09-04 14:00:00', '2025-09-04 15:30:00', 4), + ('Retrospective', '2025-09-05 16:00:00', '2025-09-05 17:00:00', 5); +`); + + console.log("Sample data inserted."); + } catch (err) { + console.error("Error:", err); + } finally { + if (client) await client.end().catch(() => {}); + await defaultClient.end().catch(() => {}); + console.log("Setup complete (connections closed)."); + } +} + +setupDatabase(); diff --git a/Week1/recipes.sql b/Week1/recipes.sql new file mode 100644 index 000000000..4f45c40bc --- /dev/null +++ b/Week1/recipes.sql @@ -0,0 +1,45 @@ +CREATE TABLE recipes ( + recipe_id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE categories ( + category_id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE ingredients ( + ingredient_id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE steps ( + step_id INT PRIMARY KEY AUTO_INCREMENT, + description TEXT NOT NULL +); + +CREATE TABLE recipe_category ( + recipe_id INT, + category_id INT, + PRIMARY KEY (recipe_id, category_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE CASCADE +); + +CREATE TABLE recipe_ingredient ( + recipe_id INT, + ingredient_id INT, + quantity VARCHAR(50), + PRIMARY KEY (recipe_id, ingredient_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (ingredient_id) REFERENCES ingredients(ingredient_id) ON DELETE CASCADE +); + +CREATE TABLE recipe_step ( + recipe_id INT, + step_id INT, + step_order INT NOT NULL, + PRIMARY KEY (recipe_id, step_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (step_id) REFERENCES steps(step_id) ON DELETE CASCADE +); \ No newline at end of file diff --git a/Week2/databases/connectDatabase.js b/Week2/databases/connectDatabase.js new file mode 100644 index 000000000..ac65e1c17 --- /dev/null +++ b/Week2/databases/connectDatabase.js @@ -0,0 +1,22 @@ +import pkg from 'pg'; +const { Client } = pkg; + + +export async function connectDB(database = 'postgres') { + const client = new Client({ + user: 'hyfuser', + host: 'localhost', + database, + password: 'hyfpassword', + port: 5432, + }); + + try { + await client.connect(); + console.log(`Connected to database: ${database}`); + return client; + } catch (error) { + console.error('Connection error:', error); + throw error; + } +} diff --git a/Week2/databases/exercise 1 Keys.js b/Week2/databases/exercise 1 Keys.js new file mode 100644 index 000000000..11583963c --- /dev/null +++ b/Week2/databases/exercise 1 Keys.js @@ -0,0 +1,52 @@ +import pkg from "pg"; +const { Client } = pkg; + +const client = new Client({ + user: "postgres", + host: "localhost", + database: "hyf_db", + password: "your_password", + port: 5432, +}); + +async function main() { + try { + await client.connect(); + console.log("Connected to the database"); + + await client.query(` + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'gender_type') THEN + CREATE TYPE gender_type AS ENUM ('Male', 'Female', 'Other'); + END IF; + END $$; + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS authors ( + author_id SERIAL PRIMARY KEY, + author_name VARCHAR(100) NOT NULL, + university VARCHAR(100), + date_of_birth DATE, + h_index INT, + gender gender_type, + mentor INT, + CONSTRAINT fk_mentor FOREIGN KEY (mentor) REFERENCES authors(author_id) ON DELETE SET NULL + ); + `); + + console.log( + "Authors table created with self-referencing mentor key and gender ENUM" + ); + } catch (error) { + console.error("Error occurred:", error.message); + } finally { + await client.end(); + console.log("Database connection closed"); + } +} + +main().catch((error) => { + console.error("Main function error:", error.message); +}); diff --git a/Week2/databases/exercise 2 Relationships.js b/Week2/databases/exercise 2 Relationships.js new file mode 100644 index 000000000..f3dffe987 --- /dev/null +++ b/Week2/databases/exercise 2 Relationships.js @@ -0,0 +1,73 @@ +import pkg from "pg"; +const { Client } = pkg; + +const client = new Client({ + user: "postgres", + host: "localhost", + database: "hyf_db", + password: "your_password", + port: 5432, +}); + +async function main() { + try { + await client.connect(); + console.log("Connected to the database"); + + await client.query(` + CREATE TABLE IF NOT EXISTS research_papers ( + paper_id SERIAL PRIMARY KEY, + paper_title VARCHAR(255) NOT NULL, + conference VARCHAR(100), + publish_date DATE + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS author_papers ( + author_id INT REFERENCES authors(author_id), + paper_id INT REFERENCES research_papers(paper_id), + PRIMARY KEY (author_id, paper_id) + ); + `); + + console.log("Research papers and author_papers tables created"); + + await client.query(` + INSERT INTO authors (author_name, university, date_of_birth, h_index, gender) + VALUES + ('Alice Smith', 'MIT', '1980-05-10', 42, 'Female'), + ('Bob Johnson', 'Stanford', '1975-09-20', 55, 'Male'), + ('Carol Lee', 'Harvard', '1985-01-15', 38, 'Female') + ON CONFLICT DO NOTHING; + `); + + await client.query(` + INSERT INTO research_papers (paper_title, conference, publish_date) + VALUES + ('AI in Healthcare', 'NeurIPS', '2020-12-01'), + ('Quantum Computing Advances', 'QCon', '2021-06-15'), + ('Deep Learning Optimization', 'ICML', '2019-07-07') + ON CONFLICT DO NOTHING; + `); + + await client.query(` + INSERT INTO author_papers (author_id, paper_id) + VALUES (1,1), (2,1), (1,2), (3,3) + ON CONFLICT DO NOTHING; + `); + + console.log("Sample authors and papers inserted"); + } catch (error) { + console.error("An error occurred:", error); + throw error; // Re-throw to allow caller to handle if needed + } finally { + await client.end(); + console.log("Database connection closed"); + } +} + +main().catch((error) => { + console.error("Failed to execute main function:", error); + process.exit(1); // Exit with error code +}); diff --git a/Week2/databases/exercise 3 Joins.js b/Week2/databases/exercise 3 Joins.js new file mode 100644 index 000000000..365e177e9 --- /dev/null +++ b/Week2/databases/exercise 3 Joins.js @@ -0,0 +1,43 @@ +import pkg from "pg"; +const { Client } = pkg; + +const client = new Client({ + user: "postgres", + host: "localhost", + database: "hyf_db", + password: "your_password", + port: 5432, +}); + +async function main() { + try { + await client.connect(); + console.log("Connected to the database"); + + const mentors = await client.query(` + SELECT a.author_name AS author, m.author_name AS mentor + FROM authors a + LEFT JOIN authors m ON a.mentor = m.author_id; + `); + console.table(mentors.rows); + + const papers = await client.query(` + SELECT a.author_name, rp.paper_title + FROM authors a + LEFT JOIN author_papers ap ON a.author_id = ap.author_id + LEFT JOIN research_papers rp ON ap.paper_id = rp.paper_id; + `); + console.table(papers.rows); + } catch (error) { + console.error("An error occurred:", error); + throw error; // Re-throw to allow caller to handle if needed + } finally { + await client.end(); + console.log("Database connection closed"); + } +} + +main().catch((error) => { + console.error("Failed to execute main function:", error); + process.exit(1); // Exit with error code +}); diff --git a/Week2/databases/exercise 4 Aggregate functions.js b/Week2/databases/exercise 4 Aggregate functions.js new file mode 100644 index 000000000..5d2626649 --- /dev/null +++ b/Week2/databases/exercise 4 Aggregate functions.js @@ -0,0 +1,66 @@ +import pkg from "pg"; +const { Client } = pkg; + +const client = new Client({ + user: "postgres", + host: "localhost", + database: "hyf_db", + password: "your_password", + port: 5432, +}); + +async function main() { + try { + await client.connect(); + console.log("Connected to the database"); + + const q1 = await client.query(` + SELECT rp.paper_title, COUNT(ap.author_id) AS author_count + FROM research_papers rp + LEFT JOIN author_papers ap ON rp.paper_id = ap.paper_id + GROUP BY rp.paper_title; + `); + console.table(q1.rows); + + const q2 = await client.query(` + SELECT COUNT(DISTINCT ap.paper_id) AS female_paper_count + FROM authors a + JOIN author_papers ap ON a.author_id = ap.author_id + WHERE a.gender = 'Female'; + `); + console.table(q2.rows); + + const q3 = await client.query(` + SELECT university, AVG(h_index) AS avg_hindex + FROM authors + GROUP BY university; + `); + console.table(q3.rows); + + const q4 = await client.query(` + SELECT a.university, COUNT(DISTINCT ap.paper_id) AS paper_count + FROM authors a + LEFT JOIN author_papers ap ON a.author_id = ap.author_id + GROUP BY a.university; + `); + console.table(q4.rows); + + const q5 = await client.query(` + SELECT university, MIN(h_index) AS min_hindex, MAX(h_index) AS max_hindex + FROM authors + GROUP BY university; + `); + console.table(q5.rows); + } catch (error) { + console.error("An error occurred:", error); + throw error; // Re-throw to allow caller to handle if needed + } finally { + await client.end(); + console.log("Database connection closed"); + } +} + +main().catch((error) => { + console.error("Failed to execute main function:", error); + process.exit(1); // Exit with error code +}); diff --git a/Week2/databases/queries.js b/Week2/databases/queries.js new file mode 100644 index 000000000..b1323a743 --- /dev/null +++ b/Week2/databases/queries.js @@ -0,0 +1,40 @@ +import { connectDB } from "./connectDatabase.js"; + +async function runQueries() { + const client = await connectDB("recipes"); + + try { + const res1 = await client.query(` + SELECT r.name + FROM recipes r + JOIN recipe_category rc ON r.recipe_id = rc.recipe_id + JOIN categories c ON rc.category_id = c.category_id + WHERE c.name = 'Vegetarian' + `); + console.log("Vegetarian recipes:", res1.rows); + + const res2 = await client.query(` + SELECT r.name + FROM recipes r + JOIN recipe_category rc ON r.recipe_id = rc.recipe_id + JOIN categories c ON rc.category_id = c.category_id + WHERE c.name = 'No-Bake' + `); + console.log("No-Bake Cakes:", res2.rows); + + const res3 = await client.query(` + SELECT r.name + FROM recipes r + JOIN recipe_category rc ON r.recipe_id = rc.recipe_id + JOIN categories c ON rc.category_id = c.category_id + WHERE c.name IN ('Vegan','Japanese') + `); + console.log("Vegan or Japanese recipes:", res3.rows); + } catch (err) { + console.error("Error running queries:", err); + } finally { + await client.end(); + } +} + +runQueries(); diff --git a/Week2/databases/recipes.sql b/Week2/databases/recipes.sql new file mode 100644 index 000000000..312f9cda6 --- /dev/null +++ b/Week2/databases/recipes.sql @@ -0,0 +1,46 @@ + +CREATE TABLE recipes ( + recipe_id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE categories ( + category_id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE ingredients ( + ingredient_id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL UNIQUE +); + +CREATE TABLE steps ( + step_id SERIAL PRIMARY KEY, + description TEXT NOT NULL +); + +CREATE TABLE recipe_category ( + recipe_id INT, + category_id INT, + PRIMARY KEY (recipe_id, category_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE CASCADE +); + +CREATE TABLE recipe_ingredient ( + recipe_id INT, + ingredient_id INT, + quantity VARCHAR(50), + PRIMARY KEY (recipe_id, ingredient_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (ingredient_id) REFERENCES ingredients(ingredient_id) ON DELETE CASCADE +); + +CREATE TABLE recipe_step ( + recipe_id INT, + step_id INT, + step_order INT NOT NULL, + PRIMARY KEY (recipe_id, step_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (step_id) REFERENCES steps(step_id) ON DELETE CASCADE +); diff --git a/Week2/databases/setupRecipes.js b/Week2/databases/setupRecipes.js new file mode 100644 index 000000000..617ba383d --- /dev/null +++ b/Week2/databases/setupRecipes.js @@ -0,0 +1,309 @@ +import pkg from "pg"; +const { Client } = pkg; + +const defaultClient = new Client({ + user: "hyfuser", + host: "localhost", + database: "postgres", + password: "hyfpassword", + port: 5432, +}); + +async function setupDatabase() { + try { + await defaultClient.connect(); + + await defaultClient.query(`DROP DATABASE IF EXISTS recipes;`); + await defaultClient.query(`CREATE DATABASE recipes;`); + console.log('Database "recipes" created.'); + await defaultClient.end(); + + const client = new Client({ + user: "hyfuser", + host: "localhost", + database: "recipes", + password: "hyfpassword", + port: 5432, + }); + + await client.connect(); + console.log("Connected to database: recipes"); + + await client.query(` + CREATE TABLE IF NOT EXISTS recipes ( + recipe_id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS categories ( + category_id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL UNIQUE + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS ingredients ( + ingredient_id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL UNIQUE + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS steps ( + step_id SERIAL PRIMARY KEY, + description TEXT NOT NULL + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS recipe_category ( + recipe_id INT, + category_id INT, + PRIMARY KEY (recipe_id, category_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE CASCADE + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS recipe_ingredient ( + recipe_id INT, + ingredient_id INT, + quantity VARCHAR(50), + PRIMARY KEY (recipe_id, ingredient_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (ingredient_id) REFERENCES ingredients(ingredient_id) ON DELETE CASCADE + ); + `); + + await client.query(` + CREATE TABLE IF NOT EXISTS recipe_step ( + recipe_id INT, + step_id INT, + step_order INT NOT NULL, + PRIMARY KEY (recipe_id, step_id), + FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE, + FOREIGN KEY (step_id) REFERENCES steps(step_id) ON DELETE CASCADE + ); + `); + + const categories = [ + "Cake", + "No-Bake", + "Vegetarian", + "Vegan", + "Gluten-Free", + "Japanese", + ]; + for (let cat of categories) { + await client.query( + `INSERT INTO categories (name) VALUES ($1) ON CONFLICT DO NOTHING`, + [cat] + ); + } + + const ingredients = [ + "Condensed milk", + "Cream Cheese", + "Lemon Juice", + "Pie Crust", + "Cherry Jam", + "Brussels Sprouts", + "Sesame seeds", + "Pepper", + "Salt", + "Olive oil", + "Macaroni", + "Butter", + "Flour", + "Milk", + "Shredded Cheddar cheese", + "Eggs", + "Soy sauce", + "Sugar", + ]; + for (let ing of ingredients) { + await client.query( + `INSERT INTO ingredients (name) VALUES ($1) ON CONFLICT DO NOTHING`, + [ing] + ); + } + + const allSteps = [ + "Beat Cream Cheese", + "Add condensed Milk and blend", + "Add Lemon Juice and blend", + "Add the mix to the pie crust", + "Spread the Cherry Jam", + "Place in refrigerator for 3h", + "Preheat the oven", + "Mix the ingredients in a bowl", + "Spread the mix on baking sheet", + "Bake for 30'", + "Cook Macaroni for 8'", + "Melt butter in a saucepan", + "Add flour, salt, pepper and mix", + "Add Milk and mix", + "Cook until mix is smooth", + "Add cheddar cheese", + "Add the macaroni", + "Beat the eggs", + "Add soya sauce, sugar and salt", + "Add oil to a sauce pan", + "Bring to medium heat", + "Add some mix to the sauce pan", + "Let is cook for 1'", + "Remove pan from fire", + ]; + for (let step of allSteps) { + await client.query( + `INSERT INTO steps (description) VALUES ($1) ON CONFLICT DO NOTHING`, + [step] + ); + } + + const recipes = [ + "No-Bake Cheesecake", + "Roasted Brussels Sprouts", + "Mac & Cheese", + "Tamagoyaki Japanese Omelette", + ]; + for (let rec of recipes) { + await client.query( + `INSERT INTO recipes (name) VALUES ($1) ON CONFLICT DO NOTHING`, + [rec] + ); + } + + const recipeCategories = { + "No-Bake Cheesecake": ["Cake", "No-Bake", "Vegetarian"], + "Roasted Brussels Sprouts": ["Vegan", "Gluten-Free"], + "Mac & Cheese": ["Vegetarian"], + "Tamagoyaki Japanese Omelette": ["Vegetarian", "Japanese"], + }; + + for (let [rec, cats] of Object.entries(recipeCategories)) { + for (let cat of cats) { + await client.query( + ` + INSERT INTO recipe_category (recipe_id, category_id) + SELECT r.recipe_id, c.category_id + FROM recipes r, categories c + WHERE r.name = $1 AND c.name = $2 + ON CONFLICT DO NOTHING + `, + [rec, cat] + ); + } + } + + const recipeIngredients = { + "No-Bake Cheesecake": [ + "Condensed milk", + "Cream Cheese", + "Lemon Juice", + "Pie Crust", + "Cherry Jam", + ], + "Roasted Brussels Sprouts": [ + "Brussels Sprouts", + "Lemon Juice", + "Sesame seeds", + "Pepper", + "Salt", + "Olive oil", + ], + "Mac & Cheese": [ + "Macaroni", + "Butter", + "Flour", + "Salt", + "Pepper", + "Milk", + "Shredded Cheddar cheese", + ], + "Tamagoyaki Japanese Omelette": [ + "Eggs", + "Soy sauce", + "Sugar", + "Salt", + "Olive oil", + ], + }; + + for (let [rec, ings] of Object.entries(recipeIngredients)) { + for (let ing of ings) { + await client.query( + ` + INSERT INTO recipe_ingredient (recipe_id, ingredient_id, quantity) + SELECT r.recipe_id, i.ingredient_id, 'to taste' + FROM recipes r, ingredients i + WHERE r.name = $1 AND i.name = $2 + ON CONFLICT DO NOTHING + `, + [rec, ing] + ); + } + } + + const recipeSteps = { + "No-Bake Cheesecake": [ + "Beat Cream Cheese", + "Add condensed Milk and blend", + "Add Lemon Juice and blend", + "Add the mix to the pie crust", + "Spread the Cherry Jam", + "Place in refrigerator for 3h", + ], + "Roasted Brussels Sprouts": [ + "Preheat the oven", + "Mix the ingredients in a bowl", + "Spread the mix on baking sheet", + "Bake for 30'", + ], + "Mac & Cheese": [ + "Cook Macaroni for 8'", + "Melt butter in a saucepan", + "Add flour, salt, pepper and mix", + "Add Milk and mix", + "Cook until mix is smooth", + "Add cheddar cheese", + "Add the macaroni", + ], + "Tamagoyaki Japanese Omelette": [ + "Beat the eggs", + "Add soya sauce, sugar and salt", + "Add oil to a sauce pan", + "Bring to medium heat", + "Add some mix to the sauce pan", + "Let is cook for 1'", + "Remove pan from fire", + ], + }; + + for (let [rec, steps] of Object.entries(recipeSteps)) { + for (let i = 0; i < steps.length; i++) { + await client.query( + ` + INSERT INTO recipe_step (recipe_id, step_id, step_order) + SELECT r.recipe_id, s.step_id, $1 + FROM recipes r, steps s + WHERE r.name = $2 AND s.description = $3 + ON CONFLICT DO NOTHING + `, + [i + 1, rec, steps[i]] + ); + } + } + + console.log("Database setup complete!"); + await client.end(); + } catch (err) { + console.error("Connection error:", err); + await defaultClient.end(); + } +} + +setupDatabase(); diff --git a/Week2/package-lock.json b/Week2/package-lock.json new file mode 100644 index 000000000..4d4583c48 --- /dev/null +++ b/Week2/package-lock.json @@ -0,0 +1,162 @@ +{ + "name": "week2", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "week2", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "pg": "^8.16.3" + } + }, + "node_modules/pg": { + "version": "8.16.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", + "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.9.1", + "pg-pool": "^3.10.1", + "pg-protocol": "^1.10.3", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.7" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz", + "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", + "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", + "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + } + } +} diff --git a/Week2/package.json b/Week2/package.json new file mode 100644 index 000000000..795720253 --- /dev/null +++ b/Week2/package.json @@ -0,0 +1,16 @@ +{ + "name": "week2", + "version": "1.0.0", + "type": "module", + "description": "## Agenda", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "pg": "^8.16.3" + } +}