From e6dd0c347b9249f7aa02630664c5199fd4f845c5 Mon Sep 17 00:00:00 2001 From: Ilias Khugaev Date: Wed, 4 Jun 2025 15:52:42 +0200 Subject: [PATCH 1/2] finale commit --- Week3/assignment/answers.md | 12 ++ Week3/assignment/injection.js | 29 ++++ Week3/assignment/package-lock.json | 143 ++++++++++++++++++ Week3/assignment/package.json | 15 ++ Week3/assignment/transaction.js | 25 +++ .../assignment/transactions-create-tables.js | 30 ++++ .../assignment/transactions-insert-values.js | 25 +++ Week3/homework/mongodb/index.js | 63 +++++--- Week3/homework/mongodb/package-lock.json | 28 ++++ Week3/homework/mongodb/package.json | 15 ++ Week3/homework/mongodb/seedDatabase.js | 11 +- Week3/input-demo.js | 1 + 12 files changed, 370 insertions(+), 27 deletions(-) create mode 100644 Week3/assignment/answers.md create mode 100644 Week3/assignment/injection.js create mode 100644 Week3/assignment/package-lock.json create mode 100644 Week3/assignment/package.json create mode 100644 Week3/assignment/transaction.js create mode 100644 Week3/assignment/transactions-create-tables.js create mode 100644 Week3/assignment/transactions-insert-values.js create mode 100644 Week3/homework/mongodb/package-lock.json create mode 100644 Week3/homework/mongodb/package.json diff --git a/Week3/assignment/answers.md b/Week3/assignment/answers.md new file mode 100644 index 000000000..32bc9947e --- /dev/null +++ b/Week3/assignment/answers.md @@ -0,0 +1,12 @@ +1. **What columns violate 1NF?** + Columns: `member_address`, `dinner_date`, `food_code`, `food_description` violate 1NF, because each column should be single-valued. + +2. **What entities do you recognize that could be extracted?** + - **Member**: `member_id`, `member_name`, `member_address` + - **Dinner**: `dinner_id`, `dinner_date` + - **Venue**: `venue_code`, `venue_description` + - **Food**: `food_code`, `food_description` + +3. **Name all the tables and columns that would make a 3NF compliant solution.** + - `member_id` and `member_name` + - `venue_code` and `venue_description` \ No newline at end of file diff --git a/Week3/assignment/injection.js b/Week3/assignment/injection.js new file mode 100644 index 000000000..28a47f997 --- /dev/null +++ b/Week3/assignment/injection.js @@ -0,0 +1,29 @@ +// Give an example of a value that can be passed as name and code that would take advantage of SQL-injection and ( fetch all the records in the database) +function getPopulation(Country, name, code, cb) { + // assuming that connection to the database is established and stored as conn + conn.query( + `SELECT Population FROM ${Country} WHERE Name = '${name}' and code = '${code}'`, + function (err, result) { + if (err) cb(err); + if (result.length == 0) cb(new Error("Not found")); + cb(null, result[0].name); + } + ); +} +// we can pass name as ('' OR '1'='1), or code as ('' OR '1'='1) +// SELECT Population FROM Countries WHERE Name = '' OR '1'='1' and code = '' OR '1'='1'; + + +// Rewrite the function so that it is no longer vulnerable to SQL injection + +function getPopulation(Country, name, code, cb) { + conn.query( + `SELECT Population FROM ?? WHERE Name = ? AND code = ?`, + [Country, name, code], + function (err, result) { + if (err) return cb(err); + if (result.length === 0) return cb(new Error("Not found")); + cb(null, result[0].Population); // исправлено: result[0].name → result[0].Population + } + ); +} \ No newline at end of file diff --git a/Week3/assignment/package-lock.json b/Week3/assignment/package-lock.json new file mode 100644 index 000000000..cd5647e44 --- /dev/null +++ b/Week3/assignment/package-lock.json @@ -0,0 +1,143 @@ +{ + "name": "assignment", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "assignment", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "mysql2": "^3.14.1" + } + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/mysql2": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz", + "integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + } + } +} diff --git a/Week3/assignment/package.json b/Week3/assignment/package.json new file mode 100644 index 000000000..8a78d83a7 --- /dev/null +++ b/Week3/assignment/package.json @@ -0,0 +1,15 @@ +{ + "name": "assignment", + "version": "1.0.0", + "type": "module", + "main": "transactions-create-tables.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "mysql2": "^3.14.1" + } +} diff --git a/Week3/assignment/transaction.js b/Week3/assignment/transaction.js new file mode 100644 index 000000000..94eb1d620 --- /dev/null +++ b/Week3/assignment/transaction.js @@ -0,0 +1,25 @@ +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + host: 'localhost', + user: 'hyfuser', + password : 'hyfpassword', +}); + +try { + await connection.query(`USE Transactions`) + await connection.query(`START TRANSACTION`); + await connection.query(`UPDATE account SET balance = balance - 1000 WHERE account_number = 1001`); + await connection.query(`UPDATE account SET balance = balance + 1000 WHERE account_number = 1002`); + await connection.query(` + INSERT INTO account_changes(account_number, amount, changed_date, remark) + VALUES + (1001, -1000, '2020-01-01', 'transaction'), + (1002, 1000, '2020-01-02', 'deposit') + `); + await connection.query(`COMMIT`); +} catch (err) { + console.log(err); +} finally { + connection.end(); +} \ No newline at end of file diff --git a/Week3/assignment/transactions-create-tables.js b/Week3/assignment/transactions-create-tables.js new file mode 100644 index 000000000..7a6655df0 --- /dev/null +++ b/Week3/assignment/transactions-create-tables.js @@ -0,0 +1,30 @@ +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + host: 'localhost', + user: 'hyfuser', + password : 'hyfpassword', +}); + +try { + await connection.query(`DROP DATABASE IF EXISTS Transactions`); + await connection.query(`CREATE DATABASE IF NOT EXISTS Transactions`); + await connection.query(`USE Transactions`) + await connection.query(`CREATE TABLE IF NOT EXISTS account( + account_number INT AUTO_INCREMENT PRIMARY KEY, + balance INT NOT NULL DEFAULT 0)` + ); + + await connection.query(`CREATE TABLE IF NOT EXISTS account_changes( + change_number INT AUTO_INCREMENT PRIMARY KEY, + account_number INT, + amount INT, + changed_date DATETIME, + remark TEXT, + FOREIGN KEY (account_number) REFERENCES account(account_number))` + ); +} catch (err) { + console.log(err); +} finally { + connection.end(); +} \ No newline at end of file diff --git a/Week3/assignment/transactions-insert-values.js b/Week3/assignment/transactions-insert-values.js new file mode 100644 index 000000000..209bd3410 --- /dev/null +++ b/Week3/assignment/transactions-insert-values.js @@ -0,0 +1,25 @@ +import mysql from 'mysql2/promise'; + +const connection = await mysql.createConnection({ + host: 'localhost', + user: 'hyfuser', + password : 'hyfpassword', +}); + +try { + await connection.query(`USE Transactions`); + await connection.query(`INSERT INTO account(account_number, balance) + VALUES (1001, 5000), + (1002, 3000), + (1003, 7000)` + ); + await connection.query(`INSERT INTO account_changes(account_number, amount, changed_date, remark) + VALUES (1001, 1000, '2020-01-01', 'Initial deposit'), + (1002, -1000, '2020-01-02', 'Initial deposit'), + (1003, 1000, '2020-01-03', 'Initial deposit')` + ); +} catch (err) { + console.log(err); +} finally { + connection.end(); +} \ No newline at end of file diff --git a/Week3/homework/mongodb/index.js b/Week3/homework/mongodb/index.js index 41ee8b618..ce1dd1bd9 100644 --- a/Week3/homework/mongodb/index.js +++ b/Week3/homework/mongodb/index.js @@ -1,6 +1,6 @@ -const { MongoClient, ServerApiVersion } = require("mongodb"); - -const { seedDatabase } = require("./seedDatabase.js"); +import { MongoClient, ServerApiVersion } from 'mongodb'; +import 'dotenv/config'; +import { seedDatabase } from './seedDatabase.js'; async function createEpisodeExercise(client) { /** @@ -12,40 +12,52 @@ async function createEpisodeExercise(client) { */ // Write code that will add this to the collection! + const doc = { + episode: "S09E13", + title: "MOUNTAIN HIDE-AWAY", + elements: ["CIRRUS", "CLOUDS", "CONIFER", "DECIDIOUS", "GRASS", "MOUNTAIN", "MOUNTAINS", "RIVER", "SNOWY_MOUNTAIN", "TREE", "TREES"] + }; + const result = await client.db('databaseWeek3').collection('bob_ross_episodes').insertOne({doc}); console.log( - `Created season 9 episode 13 and the document got the id ${"TODO: fill in variable here"}` + `Created season 9 episode 13 and the document got the id ${result.insertedId}` ); } async function findEpisodesExercises(client) { - /** - * Complete the following exercises. - * The comments indicate what to do and what the result should be! - */ + const doc = {episode: "S02E02"}; - // Find the title of episode 2 in season 2 [Should be: WINTER SUN] + const result = await client.db('databaseWeek3').collection('bob_ross_episodes').findOne(doc); console.log( - `The title of episode 2 in season 2 is ${"TODO: fill in variable here"}` + `The title of episode 2 in season 2 is ${result.title}` ); // Find the season and episode number of the episode called "BLACK RIVER" [Should be: S02E06] - + const result1 = await client.db('databaseWeek3').collection('bob_ross_episodes').findOne({ title: "BLACK RIVER"}); console.log( - `The season and episode number of the "BLACK RIVER" episode is ${"TODO: fill in variable here"}` + `The season and episode number of the "BLACK RIVER" episode is ${result1.episode}` ); // Find all of the episode titles where Bob Ross painted a CLIFF [Should be: NIGHT LIGHT, EVENING SEASCAPE, SURF'S UP, CLIFFSIDE, BY THE SEA, DEEP WILDERNESS HOME, CRIMSON TIDE, GRACEFUL WATERFALL] - + const result2 = await client.db('databaseWeek3').collection('bob_ross_episodes').find({ elements: "CLIFF"}); + const allCLIFFEpisodes = []; + for await (const doc of result2) { + allCLIFFEpisodes.push(doc.title); + } console.log( - `The episodes that Bob Ross painted a CLIFF are ${"TODO: fill in variable here"}` + `The episodes that Bob Ross painted a CLIFF are ${allCLIFFEpisodes.join(', ')}` ); // Find all of the episode titles where Bob Ross painted a CLIFF and a LIGHTHOUSE [Should be: NIGHT LIGHT] + const result3 = await client.db('databaseWeek3').collection('bob_ross_episodes').find({ elements: { $all: ["CLIFF", "LIGHTHOUSE"] } }); + const allCLIFFandLIGHTHOUSEEpisodes = []; + for await (const doc of result3) { + allCLIFFandLIGHTHOUSEEpisodes.push(doc.title); + } console.log( - `The episodes that Bob Ross painted a CLIFF and a LIGHTHOUSE are ${"TODO: fill in variable here"}` + `The episodes that Bob Ross painted a CLIFF and a LIGHTHOUSE are ${allCLIFFandLIGHTHOUSEEpisodes.join(', ')}` ); } @@ -57,18 +69,27 @@ async function updateEpisodeExercises(client) { * Note: do NOT change the data.json file */ - // Episode 13 in season 30 should be called BLUE RIDGE FALLS, yet it is called BLUE RIDGE FALLERS now. Fix that + // Episode 13 in season 30 should be called BLUE RIDGE FALLS, yet it is called BLUE RIDGE FALLERS now. Fix that + const updateDoc = { + $set: { + title: "BLUE RIDGE FALLS", + }, + }; + + const result = await client.db('databaseWeek3').collection('bob_ross_episodes').updateOne({episode: "S30E13"}, updateDoc); console.log( - `Ran a command to update episode 13 in season 30 and it updated ${"TODO: fill in variable here"} episodes` + `Ran a command to update episode 13 in season 30 and it updated ${result.modifiedCount} episodes` ); // Unfortunately we made a mistake in the arrays and the element type called 'BUSHES' should actually be 'BUSH' as sometimes only one bush was painted. // Update all of the documents in the collection that have `BUSHES` in the elements array to now have `BUSH` // It should update 120 episodes! + const result2 = await client.db('databaseWeek3').collection('bob_ross_episodes').updateMany({elements: "BUSHES"}, { $set: {elements: "BUSH"}}); + console.log( - `Ran a command to update all the BUSHES to BUSH and it updated ${"TODO: fill in variable here"} episodes` + `Ran a command to update all the BUSHES to BUSH and it updated ${result2.modifiedCount} episodes` ); } @@ -78,8 +99,12 @@ async function deleteEpisodeExercise(client) { * This is episode 14 in season 31. Please remove it and verify that it has been removed! */ + const doc = {episode: "S31E14"}; + + const result = await client.db('databaseWeek3').collection('bob_ross_episodes').deleteOne(doc); + console.log( - `Ran a command to delete episode and it deleted ${"TODO: fill in variable here"} episodes` + `Ran a command to delete episode and it deleted ${result.deletedCount} episodes` ); } diff --git a/Week3/homework/mongodb/package-lock.json b/Week3/homework/mongodb/package-lock.json new file mode 100644 index 000000000..aaa95e343 --- /dev/null +++ b/Week3/homework/mongodb/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "mongodb", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mongodb", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "dotenv": "^16.5.0" + } + }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + } + } +} diff --git a/Week3/homework/mongodb/package.json b/Week3/homework/mongodb/package.json new file mode 100644 index 000000000..1f2b72f1a --- /dev/null +++ b/Week3/homework/mongodb/package.json @@ -0,0 +1,15 @@ +{ + "name": "mongodb", + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "dotenv": "^16.5.0" + } +} diff --git a/Week3/homework/mongodb/seedDatabase.js b/Week3/homework/mongodb/seedDatabase.js index 99be6b3d8..19cfb6f08 100644 --- a/Week3/homework/mongodb/seedDatabase.js +++ b/Week3/homework/mongodb/seedDatabase.js @@ -1,12 +1,11 @@ -const data = require("./data.json"); - -/** +import data from "./data.json" with {type : 'json'}; + /** * This function will drop and recreate the collection of sample data in our csv file. * By doing this we ensure that your functions are working on the same data, very similar to how you would set up a test environment. * * @param {MongoClient} client - The client that is connected to your database */ -const seedDatabase = async (client) => { +export const seedDatabase = async (client) => { const hasCollection = await client .db("databaseWeek3") .listCollections({ name: "bob_ross_episodes" }) @@ -45,7 +44,3 @@ const seedDatabase = async (client) => { throw Error("The collection `bob_ross_episodes` does not exist!"); } }; - -module.exports = { - seedDatabase, -}; diff --git a/Week3/input-demo.js b/Week3/input-demo.js index 65855ba40..ee5d93a16 100644 --- a/Week3/input-demo.js +++ b/Week3/input-demo.js @@ -11,3 +11,4 @@ prompt.get(['username', 'email'], function (err, result) { console.log(' email: ' + result.email); } ); + From 054a20d6839e4d787a52ad1d66a405116dd90011 Mon Sep 17 00:00:00 2001 From: Ilias Khugaev Date: Mon, 23 Jun 2025 16:09:01 +0200 Subject: [PATCH 2/2] last commit --- Week3/assignment/answers.md | 50 +++++++++++++++++++++++++++------ Week3/assignment/transaction.js | 3 +- Week3/homework/mongodb/index.js | 40 ++++++++++++++------------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/Week3/assignment/answers.md b/Week3/assignment/answers.md index 32bc9947e..f0cf62eec 100644 --- a/Week3/assignment/answers.md +++ b/Week3/assignment/answers.md @@ -1,12 +1,44 @@ -1. **What columns violate 1NF?** - Columns: `member_address`, `dinner_date`, `food_code`, `food_description` violate 1NF, because each column should be single-valued. +1. **Which columns break 1NF?** +- Each cell must have one single value (atomic). +- No lists or repeated values in one cell. +
**These columns break 1NF:** +
`food_code → example: C1, C2` +
`food_description → example: Curry, Cake` -2. **What entities do you recognize that could be extracted?** - - **Member**: `member_id`, `member_name`, `member_address` - - **Dinner**: `dinner_id`, `dinner_date` - - **Venue**: `venue_code`, `venue_description` - - **Food**: `food_code`, `food_description` + +2. **What entities can we extract?** + We can create 5 entities (tables): + +- Members → `people who join the dinner.` + +- Dinners → `dinner events.` + +- Venues → `places where dinners happen.` + +- Foods → `food items served.` + +Connections → who ate what, where, and when. 3. **Name all the tables and columns that would make a 3NF compliant solution.** - - `member_id` and `member_name` - - `venue_code` and `venue_description` \ No newline at end of file + - Members + `member_id Primary Key` + `member_name Text` + `member_address Text` + + - Dinners + `dinner_id Primary Key` + `dinner_date Date` + `venue_code Foreign Key → Venues.venue_code` + + - Venues + `venue_code Primary Key` + `venue_description Text` + + - Foods + `food_code Primary Key` + `food_description Text` + + - Member_Dinner + `member_id Foreign Key → Members.member_id` + `dinner_id Foreign Key → Dinners.dinner_id` + diff --git a/Week3/assignment/transaction.js b/Week3/assignment/transaction.js index 94eb1d620..918f7253d 100644 --- a/Week3/assignment/transaction.js +++ b/Week3/assignment/transaction.js @@ -19,7 +19,8 @@ try { `); await connection.query(`COMMIT`); } catch (err) { - console.log(err); + console.error("Transaction failed, rolling back:", err); + await connection.query(`ROLLBACK`); } finally { connection.end(); } \ No newline at end of file diff --git a/Week3/homework/mongodb/index.js b/Week3/homework/mongodb/index.js index ce1dd1bd9..ebce54062 100644 --- a/Week3/homework/mongodb/index.js +++ b/Week3/homework/mongodb/index.js @@ -11,14 +11,15 @@ async function createEpisodeExercise(client) { * elements: ["CIRRUS", "CLOUDS", "CONIFER", "DECIDIOUS", "GRASS", "MOUNTAIN", "MOUNTAINS", "RIVER", "SNOWY_MOUNTAIN", "TREE", "TREES"] */ - // Write code that will add this to the collection! - const doc = { - episode: "S09E13", - title: "MOUNTAIN HIDE-AWAY", - elements: ["CIRRUS", "CLOUDS", "CONIFER", "DECIDIOUS", "GRASS", "MOUNTAIN", "MOUNTAINS", "RIVER", "SNOWY_MOUNTAIN", "TREE", "TREES"] - }; + const dataBaseName = 'databaseWeek3'; + const collectionName = 'bob_ross_episodes'; - const result = await client.db('databaseWeek3').collection('bob_ross_episodes').insertOne({doc}); + // Write code that will add this to the collection! + const result = await client.db(dataBaseName).collection(collectionName).insertOne({ + episode: "S09E13", + title: "MOUNTAIN HIDE-AWAY", + elements: ["CIRRUS", "CLOUDS", "CONIFER", "DECIDIOUS", "GRASS", "MOUNTAIN", "MOUNTAINS", "RIVER", "SNOWY_MOUNTAIN", "TREE", "TREES"] + }); console.log( `Created season 9 episode 13 and the document got the id ${result.insertedId}` ); @@ -27,20 +28,20 @@ async function createEpisodeExercise(client) { async function findEpisodesExercises(client) { const doc = {episode: "S02E02"}; - const result = await client.db('databaseWeek3').collection('bob_ross_episodes').findOne(doc); + const result = await client.db(dataBaseName).collection(collectionName).findOne(doc); console.log( `The title of episode 2 in season 2 is ${result.title}` ); // Find the season and episode number of the episode called "BLACK RIVER" [Should be: S02E06] - const result1 = await client.db('databaseWeek3').collection('bob_ross_episodes').findOne({ title: "BLACK RIVER"}); + const result1 = await client.db(dataBaseName).collection(collectionName).findOne({ title: "BLACK RIVER"}); console.log( `The season and episode number of the "BLACK RIVER" episode is ${result1.episode}` ); // Find all of the episode titles where Bob Ross painted a CLIFF [Should be: NIGHT LIGHT, EVENING SEASCAPE, SURF'S UP, CLIFFSIDE, BY THE SEA, DEEP WILDERNESS HOME, CRIMSON TIDE, GRACEFUL WATERFALL] - const result2 = await client.db('databaseWeek3').collection('bob_ross_episodes').find({ elements: "CLIFF"}); + const result2 = await client.db(dataBaseName).collection(collectionName).find({ elements: "CLIFF"}); const allCLIFFEpisodes = []; for await (const doc of result2) { allCLIFFEpisodes.push(doc.title); @@ -50,11 +51,9 @@ async function findEpisodesExercises(client) { ); // Find all of the episode titles where Bob Ross painted a CLIFF and a LIGHTHOUSE [Should be: NIGHT LIGHT] - const result3 = await client.db('databaseWeek3').collection('bob_ross_episodes').find({ elements: { $all: ["CLIFF", "LIGHTHOUSE"] } }); - const allCLIFFandLIGHTHOUSEEpisodes = []; - for await (const doc of result3) { - allCLIFFandLIGHTHOUSEEpisodes.push(doc.title); - } + const result3 = await client.db(dataBaseName).collection(collectionName).find({ elements: { $all: ["CLIFF", "LIGHTHOUSE"] } }.toArray()); + + const allCLIFFandLIGHTHOUSEEpisodes = result3.map(doc => doc.title); console.log( `The episodes that Bob Ross painted a CLIFF and a LIGHTHOUSE are ${allCLIFFandLIGHTHOUSEEpisodes.join(', ')}` @@ -76,7 +75,7 @@ async function updateEpisodeExercises(client) { }, }; - const result = await client.db('databaseWeek3').collection('bob_ross_episodes').updateOne({episode: "S30E13"}, updateDoc); + const result = await client.db(dataBaseName).collection(collectionName).updateOne({episode: "S30E13"}, updateDoc); console.log( `Ran a command to update episode 13 in season 30 and it updated ${result.modifiedCount} episodes` @@ -86,7 +85,12 @@ async function updateEpisodeExercises(client) { // Update all of the documents in the collection that have `BUSHES` in the elements array to now have `BUSH` // It should update 120 episodes! - const result2 = await client.db('databaseWeek3').collection('bob_ross_episodes').updateMany({elements: "BUSHES"}, { $set: {elements: "BUSH"}}); + const result2 = await client + .db(dataBaseName) + .collection(collectionName) + .updateMany( + { elements: "BUSHES" }, [{$set: {elements: {$map: {input: "$elements", as: "el", in: {$cond: [{ $eq: ["$$el", "BUSHES"] }, "BUSH", "$$el"]}}}}}] + ); console.log( `Ran a command to update all the BUSHES to BUSH and it updated ${result2.modifiedCount} episodes` @@ -101,7 +105,7 @@ async function deleteEpisodeExercise(client) { const doc = {episode: "S31E14"}; - const result = await client.db('databaseWeek3').collection('bob_ross_episodes').deleteOne(doc); + const result = await client.db(dataBaseName).collection(collectionName).deleteOne(doc); console.log( `Ran a command to delete episode and it deleted ${result.deletedCount} episodes`