Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 7 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
# DBNormalizer
Minimal command line python program to help you normalise your relational database design.

## Before you Run:
Modify the portion indicated in the main.py file according to comment (YES pls modify inside the source code).
The modification basically gives the following inputs:
1. Set of variables in your database.
2. List of functional dependencies implied in your database (You don't have to list trivial ones).
3. Set the normal form you want to test/achieve.

An example of the inputs will be:
```
R = ['A','B', 'C']
FD = [
[['A', 'B'], ['C']],
[['A'], ['B']],
[['B'], ['A']]
]
normalform = normalforms.threenf
```

## How to Run:
python main.py
`python main.py`

The program will prompt you to enter the **attributes**, **FDs** and the **normal form type**.

## Output:
(Note: Output is formated using python3. For best experience pls use python3.)
(Note: Output is formatted using python3. For best experience pls use python3.)

Following the previous example, the output will be:
```
Expand Down Expand Up @@ -62,9 +46,9 @@ already in 3NF
* The 1st section gives you all possible candidate keys
* The 2nd section computes the minimal cover
* The 3rd section checks if the supplied functional dependencies are normalized.
* The 4th section trys to achieve required normalization by decomposition method (can loose some dependencies).
* The 5th section trys to achieve 3NF by synthesis method (only 3NF is guaranteed, and all dependencies preserved).
* The 4th section tries to achieve required normalization by the decomposition method (can lose some dependencies).
* The 5th section tries to achieve 3NF by synthesis method (only 3NF is guaranteed, and all dependencies preserved).

Unless you must achieve BCNF, synthesis method is more popular because it at least gives you 3NF and preserves
Unless you must achieve BCNF, the synthesis method is more popular because it at least gives you 3NF and preserves
all original dependencies. And mostly likely, it gives you BCNF as well.

64 changes: 42 additions & 22 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,38 @@
###########################################

# Modify from this line onwards to suit your needs
R = ['A', 'B', 'C']
FD = [[['A', 'B'], ['C']], [['A'], ['B']], [['B'], ['A']]]
normalform = normalforms.threenf

R = input("Enter the list of unique variables of R separated by commas (e.g. a,b,c,d): ").split(",")
FD = []
while True:
dep = input("Enter a functional dependency (e.g. a,b->c) or enter nothing to stop: ")
if not dep:
break
try:
lhs, rhs = dep.split("->")
FD.append([lhs.split(","), rhs.split(",")])
except ValueError:
print("Invalid functional dependency! Reenter the functional dependency.")
while True:
normalform_name = input("Enter the normal form you want to achieve (2nf, 3nf, or bcnf): ")
if normalform_name == "2nf":
normalform = normalforms.twonf
break
elif normalform_name == "3nf":
normalform = normalforms.threenf
break
elif normalform_name == "bcnf":
normalform = normalforms.bcnf
break
else:
print("Invalid normal form! Reenter the normal form.")

# Do not modify anything from this line onwards

###########################################
# find all candidate keys
###########################################
print('all candiate keys:')
print('all candidate keys:')
print(api.candidate_keys(R, FD))

###########################################
Expand All @@ -34,46 +57,43 @@
print('')
print('')
print('a minimal cover:')
minCover = api.min_cover(R,FD)
minCover = api.min_cover(R, FD)
for F in minCover:
print(F[0],'->',F[1])
print(F[0], '->', F[1])

###########################################
# check all F in FD for violation of given normal form
###########################################
print('')
print('')
print('check normal form:',normalform.__name__)
FDsimplified = api.min_cover_step1(R,FD)
print('')
print('check normal form:', normalform.__name__)
FDsimplified = api.min_cover_step1(R, FD)
for F in FDsimplified:
print(F[0],'->',F[1],normalform(R,FDsimplified,F))

print(F[0], '->', F[1], normalform(R, FDsimplified, F))

###########################################
# decomposition to given normal form
# also check wether decomposition is dependency-preserving
# also check whether decomposition is dependency-preserving
# if not show which dependency is lost
# also verify result against given normal form
###########################################
useSigmaPlus = True
printStep = False # if true will print steps invovled in deriving the answer
printStep = False # if true will print steps involved in deriving the answer
print('')
print('')
print('decomposition:',normalform.__name__, 'showStep' if printStep else '')
fragments = decomposition.decompose(R,FD,normalform,useSigmaPlus,printStep)
decomposition.print_fragments(fragments,normalform)
print('decomposition:', normalform.__name__, 'showStep' if printStep else '')
fragments = decomposition.decompose(R, FD, normalform, useSigmaPlus, printStep)
decomposition.print_fragments(fragments, normalform)

###########################################
# synthesize to 3NF (not any form)
# also check wether synthesize is dependency-preserving
# also check whether synthesize is dependency-preserving
# if not show which dependency is lost
# also verify result against 3NF
###########################################
printStep = False # if true will print steps invovled in deriving the answer
printStep = False # if true will print steps involved in deriving the answer
print('')
print('')
print('synthesis: threenf', 'showStep' if printStep else '')
fragments = decomposition.simple_synthesis(R,FD,printStep)
decomposition.print_fragments(fragments,normalform)


fragments = decomposition.simple_synthesis(R, FD, printStep)
decomposition.print_fragments(fragments, normalform)