ΣΥΣΤΗΜΑΤΑ ΔΙΑΧΕΙΡΙΣΗΣ ΒΑΣΕΩΝ ΔΕΔΟΜΕΝΩΝ - Π20201, Π20195, Π20174 #210
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.
Documentation εργασίας:
miniDB.pdf
Μέλη Ομάδας:
Μαριάμ Φωτοπούλου - Π20201
Ελένη Αλεξάνδρα Τσιωτάκη - Π20195
Ελένη Σίμου - Π20174
ΘΕΜΑ 1:
a)NOT and BETWEEN operators:
Για την υλοποίηση του NOT operator προσθέσαμε την εξής συνθήκη στο αρχείο misc.py:
Εάν υπάρχει το not στο condition, αυτό που γίνεται είναι να αφαιρεθεί από τη συνθήκη, και στη συνέχεια γίνεται αντιστροφή της συνθήκης μέσω της παρακάτω συνάρτησης not_op():
Ακολουθεί screenshot εκτέλεσης query με not operator:
Για την υλοποίηση του BETWEEN operator, έγινε η εξής προσθήκη στο αρχείο misc.py:
Εάν υπάρχει το between στο condition, γίνεται split και παίρνουμε το όνομα της στήλης πάνω στην οποία υπάρχει η συνθήκη. Στη συνέχεια, υπάρχει η εξής τροποποίηση κώδικα στο αρχείο table.py:
Σύμφωνα με τα παραπάνω, εάν υπάρχει το between στη συνθήκη, αυτό που γίνεται είναι να την χωρίζουμε σε δύο υποσυνθήκες, και να κάνουμε έπειτα ξεχωριστούς ελέγχους με την _parse_condition().
Ακολουθεί screenshot εκτέλεσης query με between operator:
(b)AND and OR operators:
Για την υλοποίηση του AND operator προσθέσαμε στη συνάρτηση _select_where() του αρχείου table.py τον εξής κώδικα, ο οποίος κάνει split τη συνθήκη με βάση το “and” και τη διασπάει σε 2 υποσυνθήκες, τις οποίες χειρίζεται μετά ξεχωριστά σαν κανονικές συνθήκες, χρησιμοποιώντας την _parse_condition(). Τέλος συνδέει τις δύο συνθήκες αναδεικνύοντας τα «κοινά» τους, μέσω της συνάρτησης intersect:
Έγινε επίσης η εξής προσθήκη στη συνάρτηση select του αρχείου database.py:
Ακολουθούν screenshots εκτέλεσης query με τη χρήση του and operator:
Για την υλοποίηση του or operator ακολουθήσαμε λογική παρόμοια με αυτή του and. Προσθέσαμε στη συνάρτηση _select_where() του αρχείου table.py τον εξής κώδικα, ο οποίος κάνει split τη συνθήκη με βάση το “or” και τη διασπάει σε 2 υποσυνθήκες, τις οποίες χειρίζεται μετά ξεχωριστά σαν κανονικές συνθήκες, χρησιμοποιώντας την _parse_condition(). Αντίστοιχα με το “and” συνδέονται οι δύο συνθήκες αυτή τη φορά μέσω της συνάρτησης union, και όχι της intersect γιατί πρέπει να αναδειχθεί η ένωση των δύο συνθηκών, και όχι τα κοινά τους:
Παράλληλα, έγινε η προσθήκη που αναφέρουμε πιο πάνω στη συνάρτηση select του αρχείου database.py.
Ακολουθούν screenshots εκτέλεσης query με τη χρήση του or operator:
ΘΕΜΑ 2
Πριν προχωρήσουμε στην υλοποίηση των BTREE και HASH indexes, έπρεπε να προσθέσουμε τη λειτουργία του UNIQUE constraint.
Συγκεκριμένα, στη συνάρτηση create_table() του αρχείου database.py έγινε η προσθήκη του unique_cols ορίσματος, που αντιπροσωπεύει τις στήλες που θα οριστούν ως unique. Η ίδια προσθήκη έγινε και στη συνάρτηση init() του αρχείου table.py, ενώ στο ίδιο αρχείο προστέθηκε και ο εξής κώδικας:
Στον παραπάνω κώδικα ελέγχουμε εάν η στήλη έχει το unique constraint και αν ταυτόχρονα η τιμή που προσπαθούμε να εισάγουμε στο πεδίο υπάρχει ήδη στον πίνακα. Εάν συμβαίνει κάτι τέτοιο, εμφανίζεται το κατάλληλο μήνυμα και η εισαγωγή αποτυγχάνει. Έπρεπε, επίσης, να προσθέσουμε άλλον έναν έλεγχο για να εξασφαλίσουμε ότι η στήλη πάνω στην οποία γίνεται ο έλεγχος δεν αφορά metadata.
Έγινε επίσης η εξής τροποποίηση όσον αφορά τον meta_indexes πίνακα, γι΄αυτό και απαιτήθηκε στη συνέχεια η κατασκευή καινούργιας βάσης test2:
Ακολουθεί screenshot δημιουργίας πίνακα με UNIQUE constraint και προσπάθειας εισαγωγής διπλοτύπου στη unique column:
(a)BTREE INDEX:
Αρχικά, προσθέσαμε στη συνάρτηση interpret(query) του αρχείου mdb.py το κλειδί ‘create index’ στο λεξικό kw_per_action, ώστε να αναγνωρίζεται το query δημιουργίας ευρετηρίου. Στο ίδιο αρχείο, στη συνάρτηση create_query_plan() προστέθηκε ο εξής κώδικας, όπου προσθέτουμε στο κατάλληλο λεξικό το όνομα του πίνακα πάνω στον οποίο δημιουργείται index, τη στήλη και τον τύπο του ευρετηρίου που χρησιμοποιήσαμε:
Στο αρχείο database.py στη συνάρτηση create_index() προσθέσαμε το όρισμα column_name, που αφορά τη στήλη πάνω στην οποία θέλουμε να δημιουργήσουμε ευρετήριο. Στη συνέχεια, μέσα στο σώμα της ίδιας συνάρτησης τροποποιήσαμε τον κώδικα έτσι ώστε να ελέγχεται εάν η στήλη έχει unique ή primary key constraint και στη συνέχεια, ανάλογα με τον index_type που δηλώνουμε, δημιουργείται btree ή hash index. Σε αντίθετη περίπτωση, δημιουργείται ένα Exception και δε δημιουργείται ευρετήριο, ή αν δεν υπάρχει unique constraint, δημιουργείται ευρετήριο πάνω στο primary key.
Στη συνάρτηση _construct_index() προσθέσαμε τα ορίσματα column_name και index_type, για να προσδιορίσουμε τη στήλη που θα δημιουργήσουμε ευρετήριο και τον τύπο του ευρετηρίου. Στη συνέχεια προσθέσαμε τον εξής κώδικα, ο οποίος ελέγχει εάν η στήλη έχει unique ή primary key, και στη συνέχεια φτιάχνει το ευρετήριο, δημιουργώντας ένα αντικείμενο της κλάσης Btree.
Ακολουθεί screenshot δημιουργίας btree index πάνω στη unique στήλη username του πίνακα account που δημιουργήσαμε προηγουμένως.
Όσον αφορά στη συνέχεια την τροποποίηση της μεθόδου select, ώστε να χρησιμοποιείται επιλογή μέσω ευρετηρίου, εάν αυτό είναι εφικτό, τροποποιήσαμε την μέθοδο select() του αρχείου database.py, προσθέτοντας τον εξής κώδικα για την επιλογή του select μέσω btree, εάν η στήλη της συνθήκης έχει unique ή primary key constraint.
Ακολουθούν screenshots αναζήτησης με και χωρίς Btree:
(b)HASH INDEX:
Δημιουργήσαμε αρχικά τις κλάσεις Hash και Bucket στο αρχείο hash.py για τη δημιουργία hash index χρησιμοποιώντας τον επεκτάσιμο κατακερματισμό με LSB και το modulo % για τη συνάρτηση κατακερματισμού.
Κλάση Hash:
Όταν εισάγεται ένα νέο ζεύγος κλειδιού-τιμής στον πίνακα κατακερματισμού χρησιμοποιώντας τη μέθοδο insert(), η κλάση Hash υπολογίζει πρώτα την τιμή κατακερματισμού για το δοσμένο κλειδί χρησιμοποιώντας τη μέθοδο hash_function(). Η τιμή κατακερματισμού χρησιμοποιείται ως δείκτης για να αποκτηθεί πρόσβαση στο αντίστοιχο κάδο στη λίστα. Εάν ο κάδος είναι άδειος, δημιουργείται μια νέα περίπτωση της κλάσης Bucket στον κάδο. Το ζεύγος κλειδιού-τιμής εισάγεται στον κάδο χρησιμοποιώντας τη μέθοδο insert() της κλάσης Bucket.
Όταν ζητείται ένα κλειδί χρησιμοποιώντας τη μέθοδο select(), η κλάση Hash υπολογίζει την τιμή κατακερματισμού για το κλειδί και τη χρησιμοποιεί ως δείκτη για να αποκτήσει πρόσβαση στον αντίστοιχο κάδο στη λίστα. Εάν ο κάδος δεν είναι άδειος, καλείται η μέθοδος select() της κλάσης Bucket για να ανακτηθεί η τιμή που συσχετίζεται με το κλειδί.
Αντίστοιχα, όταν διαγράφεται ένα κλειδί χρησιμοποιώντας τη μέθοδο delete(), η κλάση Hash υπολογίζει την τιμή κατακερματισμού για το κλειδί και τη χρησιμοποιεί ως δείκτη για να αποκτήσει πρόσβαση στο αντίστοιχο κάδο στη λίστα. Εάν ο κάδος δεν είναι κενός, καλείται η μέθοδος delete() της κλάσης Bucket για την αφαίρεση του ζευγαριού κλειδιού-τιμής από τον κάδο.
Επιπλέον, η μέθοδος show() της κλάσης Hash χρησιμοποιείται για την εμφάνιση των περιεχομένων του πίνακα κατακερματισμού, όπου κάθε μη-κενός κάδος εμφανίζεται ως μια λίστα ζευγαριών κλειδιού-τιμής.
Τέλος, η μέθοδος get() έχει προστεθεί στην κλάση Hash για τη δυνατότητα άμεσης πρόσβασης στις τιμές του πίνακα κατακερματισμού χρησιμοποιώντας έναν δείκτη κλειδιού, όπου ο δείκτης βασίζεται στην τιμή κατακερματισμού του κλειδιού. Η μέθοδος get() χρησιμοποιεί τη μέθοδο get() της κλάσης Bucket για την ανάκτηση της τιμής στο συγκεκριμένο δείκτη.
Κλάση Bucket:
Η κλάση Bucket είναι μια βοηθητική κλάση που χρησιμοποιείται από την κλάση Hash για την αποθήκευση ζευγαριών κλειδιού-τιμής σε ένα κάδο. Η κλάση Bucket διαθέτει τις ακόλουθες μεθόδους:
Η μέθοδος insert() λαμβάνει ένα ζευγάρι κλειδιού-τιμής και το προσθέτει στο τέλος της λίστας αντικειμένων στον κάδο.
Η μέθοδος delete() λαμβάνει ένα κλειδί και αναζητά το ζευγάρι κλειδιού-τιμής με αυτό το κλειδί στη λίστα αντικειμένων. Αν βρεθεί, η μέθοδος αφαιρεί το ζευγάρι κλειδιού-τιμής από τη λίστα και επιστρέφει True. Αν το κλειδί δεν βρεθεί, η μέθοδος επιστρέφει False.
Η μέθοδος select() λαμβάνει ένα κλειδί και αναζητά το ζευγάρι κλειδιού-τιμής με αυτό το κλειδί στη λίστα αντικειμένων. Αν βρεθεί, η μέθοδος επιστρέφει την τιμή που συσχετίζεται με το κλειδί. Αν το κλειδί δεν βρεθεί, επιστρέφεται None.
Η μέθοδος get() παίρνει ένα δείκτη και επιστρέφει την τιμή του ζευγαριού κλειδιού-τιμής σε αυτόν τον δείκτη στη λίστα στοιχείων. Εάν ο δείκτης είναι εκτός ορίων, η μέθοδος επιστρέφει None.
Συνολικά, η κλάση Bucket παρέχει έναν τρόπο στην κλάση Hash για να αποθηκεύσει τα ζευγάρια κλειδιού-τιμής σε ένα κάδο και να εκτελεί αποτελεσματικά λειτουργίες πάνω σε αυτά.
Όσον αφορά τα υπόλοιπα αρχεία, έχουν γίνει αλλαγές παρόμοιες με αυτές που απαιτούνταν για το Btree index.
Στο αρχείο database.py στη συνάρτηση create_index() προσθέσαμε κώδικα αντίστοιχο με αυτόν του btree, για να δημιουργείται hash index σε unique ή primary key, εφόσον έχουμε δηλώσει το index_type να είναι hash:
Αντίστοιχες αλλαγές υπάρχουν και στη συνάρτηση _construct_index():
Ακολουθεί screenshot δημιουργίας hash ευρετηρίου στο unique πεδίο username του πίνακα account:
Όσον αφορά στη συνέχεια την τροποποίηση της μεθόδου select, ώστε να χρησιμοποιείται επιλογή μέσω ευρετηρίου, εάν αυτό είναι εφικτό, τροποποιήσαμε την μέθοδο select() του αρχείου database.py, προσθέτοντας τον εξής κώδικα για την επιλογή του select μέσω hash index, εάν η στήλη της συνθήκης έχει unique ή primary key constraint.
Στο αρχείο table.py, τέλος, δημιουργήσαμε τη συνάρτηση _select_where_with_hash(), η οποία έχει παρόμοια υλοποίηση με αυτή του Btree, προκειμένου να υλοποιηθεί η δυνατότητα επιλογής μέσω hash ευρετηρίου. Υπάρχει, ωστόσο, η διαφορά ότι εάν ο operator της συνθήκης δεν είναι “=”. τότε να πραγματοποιείται σειριακή αναζήτηση, καθώς τα ευρετήρια κατακερματισμού δεν υποστηρίζουν ερωτήσεις διαστήματος.
Ακολουθούν screenshots αναζήτησης με και χωρίς Hash index: