forked from HackYourFuture/databases
-
Notifications
You must be signed in to change notification settings - Fork 3
Oleksandr Starshynov w3 databases #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aleksandrstarshynov
wants to merge
3
commits into
HackYourAssignment:main
Choose a base branch
from
aleksandrstarshynov:oleksandr_starshynov-w3-databases
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # Exercise 1: SQL Normalization – Dinner Club | ||
|
|
||
| ## Step 1: Violation of 1NF (First Normal Form) | ||
|
|
||
| **1NF Rule**: Each field must contain only **atomic** (indivisible) values. | ||
|
|
||
| ### ❌ Violations of 1NF: | ||
| - **`food_code`** and **`food_description`** contain **multiple values** separated by commas (e.g., `"C1, C2"`, `"Curry, Cake"`). | ||
| - **`dinner_date`** has **inconsistent formats** (e.g., `"2020-03-15"`, `"20-03-2020"`, `"Mar 25 '20"`), violating domain consistency. | ||
|
|
||
| --- | ||
|
|
||
| ## Step 2: Recognized Entities | ||
|
|
||
| Based on the table, we can identify the following entities: | ||
|
|
||
| 1. **Member** – identified by `member_id`. | ||
| 2. **Dinner** – identified by `dinner_id`. | ||
| 3. **Venue** – identified by `venue_code`. | ||
| 4. **Food** – identified by `food_code`. | ||
| 5. **Dinner Participation** – mapping between members and dinners (many-to-many). | ||
| 6. **Dinner Food** – mapping between dinners and foods served (many-to-many). | ||
|
|
||
| --- | ||
|
|
||
| ## Step 3: 3NF-Compliant Tables and Attributes | ||
|
|
||
| ### 1. **Members** | ||
| | Column Name | Type | | ||
| |-----------------|-------------| | ||
| | member_id (PK) | INTEGER | | ||
| | member_name | TEXT | | ||
| | member_address | TEXT | | ||
|
|
||
| --- | ||
|
|
||
| ### 2. **Venues** | ||
| | Column Name | Type | | ||
| |---------------------|---------| | ||
| | venue_code (PK) | TEXT | | ||
| | venue_description | TEXT | | ||
|
|
||
| --- | ||
|
|
||
| ### 3. **Dinners** | ||
| | Column Name | Type | | ||
| |-----------------|-----------| | ||
| | dinner_id (PK) | TEXT | | ||
| | dinner_date | DATE | | ||
| | venue_code (FK) | TEXT | | ||
|
|
||
| --- | ||
|
|
||
| ### 4. **Foods** | ||
| | Column Name | Type | | ||
| |--------------------|---------| | ||
| | food_code (PK) | TEXT | | ||
| | food_description | TEXT | | ||
|
|
||
| --- | ||
|
|
||
| ### 5. **Dinner_Participation** (Many-to-Many: members attend multiple dinners) | ||
| | Column Name | Type | | ||
| |--------------------|---------| | ||
| | member_id (FK) | INTEGER | | ||
| | dinner_id (FK) | TEXT | | ||
|
|
||
| **Primary Key**: (member_id, dinner_id) | ||
|
|
||
| --- | ||
|
|
||
| ### 6. **Dinner_Food** (Many-to-Many: dinners serve multiple foods) | ||
| | Column Name | Type | | ||
| |--------------------|---------| | ||
| | dinner_id (FK) | TEXT | | ||
| | food_code (FK) | TEXT | | ||
|
|
||
| **Primary Key**: (dinner_id, food_code) | ||
|
|
||
| --- | ||
|
|
||
| ## Summary of Normalization | ||
|
|
||
| - The **original table** violates **1NF** due to multi-valued fields and inconsistent formats. | ||
| - We **decomposed** the table into **six 3NF-compliant tables** by: | ||
| - Ensuring atomicity of values, | ||
| - Removing transitive and partial dependencies, | ||
| - Isolating repeating groups into separate relations. |
73 changes: 73 additions & 0 deletions
73
Week3/assignmentWeek3/ex2 - SQL Transactions/transaction.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import mysql from "mysql2/promise"; | ||
|
|
||
| async function performTransfer() { | ||
| const connection = await mysql.createConnection({ | ||
| host: "localhost", | ||
| user: "hyfuser", | ||
| password: "hyfpassword", | ||
| database: "w3_assignment", | ||
| }); | ||
|
|
||
| const fromAccount = 101; | ||
| const toAccount = 102; | ||
| const amount = 1000; | ||
| const date = "2025-06-02"; | ||
|
|
||
| try { | ||
| // Start transaction | ||
| await connection.beginTransaction(); | ||
| console.log("Transaction started"); | ||
|
|
||
| const transactionFrom = { | ||
| account_number: fromAccount, | ||
| amount: -amount, | ||
| changed_date: date, | ||
| remark: `Transfer to account #${toAccount}`, | ||
| }; | ||
|
|
||
| const transactionTo = { | ||
| account_number: toAccount, | ||
| amount: amount, | ||
| changed_date: date, | ||
| remark: `Transfer from account #${fromAccount}`, | ||
| }; | ||
|
|
||
| const [availableBalanceResult] = await connection.query( | ||
| "SELECT balance FROM account WHERE account_number = ?", | ||
| [fromAccount] | ||
| ); | ||
|
|
||
| const availableBalance = availableBalanceResult[0]?.balance; | ||
|
|
||
| if (availableBalance < amount) { | ||
| throw new Error("Insufficient balance to perform the transfer"); | ||
| } | ||
|
|
||
| console.log(`Account #${fromAccount} available balance: ${availableBalance}`); | ||
|
|
||
| // Deduct from sender | ||
| await connection.query("INSERT INTO account_changes SET ?", transactionFrom); | ||
| await connection.query( | ||
| "UPDATE account SET balance = balance + ? WHERE account_number = ?", | ||
| [transactionFrom.amount, fromAccount] | ||
| ); | ||
| console.log(`$${amount} deducted from account #${fromAccount}`); | ||
|
|
||
| // Add to receiver | ||
| await connection.query("INSERT INTO account_changes SET ?", transactionTo); | ||
| await connection.query( | ||
| "UPDATE account SET balance = balance + ? WHERE account_number = ?", | ||
| [transactionTo.amount, toAccount] | ||
| ); | ||
| console.log(`$${amount} added to account #${toAccount}`); | ||
|
|
||
| await connection.commit(); | ||
| console.log("Transaction completed successfully."); | ||
| } catch (error) { | ||
| await connection.rollback(); | ||
| console.error("Transaction failed:", error.message); | ||
| } finally { | ||
| await connection.end(); | ||
| console.log("Connection closed"); | ||
| } | ||
| } |
42 changes: 42 additions & 0 deletions
42
Week3/assignmentWeek3/ex2 - SQL Transactions/transactions-create-tables.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import mysql from 'mysql2/promise'; | ||
|
|
||
| async function createTables() { | ||
| const connection = await mysql.createConnection({ | ||
| host: 'localhost', | ||
| user: 'hyfuser', | ||
| password: 'hyfpassword', | ||
| database: 'w3_assignment', | ||
| }); | ||
|
|
||
| try { | ||
| await connection.beginTransaction(); | ||
|
|
||
| await connection.query(` | ||
| CREATE TABLE IF NOT EXISTS account ( | ||
| account_number INT PRIMARY KEY, | ||
| balance DECIMAL(12, 2) NOT NULL | ||
| ) | ||
| `); | ||
|
|
||
| await connection.query(` | ||
| CREATE TABLE IF NOT EXISTS account_changes ( | ||
| change_number INT AUTO_INCREMENT PRIMARY KEY, | ||
| account_number INT, | ||
| amount DECIMAL(12, 2) NOT NULL, | ||
| changed_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| remark TEXT, | ||
| FOREIGN KEY (account_number) REFERENCES account(account_number) | ||
| ) | ||
| `); | ||
|
|
||
| await connection.commit(); | ||
| console.log('Tables created successfully'); | ||
| } catch (err) { | ||
| await connection.rollback(); | ||
| console.error('Error creating tables:', err); | ||
| } finally { | ||
| await connection.end(); | ||
| } | ||
| } | ||
|
|
||
| createTables(); | ||
36 changes: 36 additions & 0 deletions
36
Week3/assignmentWeek3/ex2 - SQL Transactions/transactions-insert-values.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import mysql from 'mysql2/promise'; | ||
|
|
||
| async function insertValues() { | ||
| const connection = await mysql.createConnection({ | ||
| host: 'localhost', | ||
| user: 'hyfuser', | ||
| password: 'hyfpassword', | ||
| database: 'w3_assignment', | ||
| }); | ||
|
|
||
| try { | ||
| await connection.beginTransaction(); | ||
|
|
||
| await connection.query(` | ||
| INSERT INTO account (account_number, balance) VALUES | ||
| (101, 5000.00), | ||
| (102, 3000.00) | ||
| `); | ||
|
|
||
| await connection.query(` | ||
| INSERT INTO account_changes (account_number, amount, remark) VALUES | ||
| (101, 5000.00, 'Initial deposit'), | ||
| (102, 3000.00, 'Initial deposit') | ||
| `); | ||
|
|
||
| await connection.commit(); | ||
| console.log('Values inserted successfully'); | ||
| } catch (err) { | ||
| await connection.rollback(); | ||
| console.error('Error inserting values:', err); | ||
| } finally { | ||
| await connection.end(); | ||
| } | ||
| } | ||
|
|
||
| insertValues(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| 1. - 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) | ||
| - answer: | ||
| - SELECT Population FROM Countries WHERE Name = '' OR '1'='1' and code = '' OR '1'='1' | ||
| - I think it would work sinse '1'='1' is always true the query will return all rows in the table, ignoring filtering by name and code. | ||
|
|
||
| 2. | ||
| ``` | ||
| function getPopulation(Country, name, code, cb) { | ||
| const allowedTables = ['Countries', 'OtherValidTable']; | ||
| if (!allowedTables.includes(Country)) { | ||
| return cb(new Error("Invalid table name")); | ||
| } | ||
|
|
||
| const sql = `SELECT Population FROM ${Country} WHERE Name = ? AND code = ?`; | ||
|
|
||
| conn.query(sql, [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); | ||
| }); | ||
| } | ||
| ``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A 100 billion is a nice big number for this, well done!