forked from MIT-DB-Class/simple-db-hw-2022
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
9,488 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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,29 @@ | ||
package simpledb.execution; | ||
|
||
import simpledb.common.DbException; | ||
import simpledb.transaction.TransactionAbortedException; | ||
|
||
import java.util.NoSuchElementException; | ||
|
||
/** | ||
* IndexDBIterator is the interface that index access methods | ||
* implement in SimpleDb. | ||
*/ | ||
public interface IndexOpIterator extends OpIterator { | ||
/** | ||
* Open the access method such that when getNext is called, it | ||
* iterates through the tuples that satisfy ipred. | ||
* | ||
* @param ipred The predicate that is used to scan the index. | ||
*/ | ||
void open(IndexPredicate ipred) | ||
throws NoSuchElementException, DbException, TransactionAbortedException; | ||
|
||
/** | ||
* Begin a new index scan with the specified predicate. | ||
* | ||
* @param ipred The predicate that is used to scan the index. | ||
*/ | ||
void rewind(IndexPredicate ipred) | ||
throws DbException, TransactionAbortedException; | ||
} |
This file contains 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,54 @@ | ||
package simpledb.execution; | ||
|
||
import simpledb.storage.Field; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* IndexPredicate compares a field which has index on it against a given value | ||
* | ||
* @see IndexOpIterator | ||
*/ | ||
public class IndexPredicate implements Serializable { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
private final Predicate.Op op; | ||
private final Field fieldvalue; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param fvalue The value that the predicate compares against. | ||
* @param op The operation to apply (as defined in Predicate.Op); either | ||
* Predicate.Op.GREATER_THAN, Predicate.Op.LESS_THAN, Predicate.Op.EQUAL, | ||
* Predicate.Op.GREATER_THAN_OR_EQ, or Predicate.Op.LESS_THAN_OR_EQ | ||
* @see Predicate | ||
*/ | ||
public IndexPredicate(Predicate.Op op, Field fvalue) { | ||
this.op = op; | ||
this.fieldvalue = fvalue; | ||
} | ||
|
||
public Field getField() { | ||
return fieldvalue; | ||
} | ||
|
||
public Predicate.Op getOp() { | ||
return op; | ||
} | ||
|
||
/** | ||
* Return true if the fieldvalue in the supplied predicate | ||
* is satisfied by this predicate's fieldvalue and | ||
* operator. | ||
* | ||
* @param ipd The field to compare against. | ||
*/ | ||
public boolean equals(IndexPredicate ipd) { | ||
if (ipd == null) | ||
return false; | ||
return (op.equals(ipd.op) && fieldvalue.equals(ipd.fieldvalue)); | ||
} | ||
|
||
} |
This file contains 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,132 @@ | ||
package simpledb.index; | ||
|
||
import simpledb.common.DbException; | ||
import simpledb.common.Permissions; | ||
import simpledb.storage.Field; | ||
import simpledb.storage.Page; | ||
import simpledb.storage.PageId; | ||
import simpledb.transaction.TransactionAbortedException; | ||
import simpledb.transaction.TransactionId; | ||
|
||
import java.io.IOException; | ||
import java.util.Iterator; | ||
import java.util.Map; | ||
|
||
/** | ||
* Created by orm on 10/7/15. | ||
*/ | ||
public class BTreeChecker { | ||
|
||
/** | ||
* This class is only used for error-checking code. | ||
*/ | ||
static class SubtreeSummary { | ||
public int depth; | ||
public BTreePageId ptrLeft; | ||
public BTreePageId leftmostId; | ||
public BTreePageId ptrRight; | ||
public BTreePageId rightmostId; | ||
|
||
SubtreeSummary() { | ||
} | ||
|
||
SubtreeSummary(BTreeLeafPage base, int depth) { | ||
this.depth = depth; | ||
|
||
this.leftmostId = base.getId(); | ||
this.rightmostId = base.getId(); | ||
|
||
this.ptrLeft = base.getLeftSiblingId(); | ||
this.ptrRight = base.getRightSiblingId(); | ||
} | ||
|
||
static SubtreeSummary checkAndMerge(SubtreeSummary accleft, SubtreeSummary right) { | ||
assert (accleft.depth == right.depth); | ||
assert (accleft.ptrRight.equals(right.leftmostId)); | ||
assert (accleft.rightmostId.equals(right.ptrLeft)); | ||
|
||
SubtreeSummary ans = new SubtreeSummary(); | ||
ans.depth = accleft.depth; | ||
|
||
ans.ptrLeft = accleft.ptrLeft; | ||
ans.leftmostId = accleft.leftmostId; | ||
|
||
ans.ptrRight = right.ptrRight; | ||
ans.rightmostId = right.rightmostId; | ||
return ans; | ||
} | ||
} | ||
|
||
/** | ||
* checks the integrity of the tree: | ||
* 1) parent pointers. | ||
* 2) sibling pointers. | ||
* 3) range invariants. | ||
* 4) record to page pointers. | ||
* 5) occupancy invariants. (if enabled) | ||
*/ | ||
public static void checkRep(BTreeFile bt, TransactionId tid, Map<PageId, Page> dirtypages, | ||
boolean checkOccupancy) throws | ||
DbException, IOException, TransactionAbortedException { | ||
BTreeRootPtrPage rtptr = bt.getRootPtrPage(tid, dirtypages); | ||
|
||
if (rtptr.getRootId() == null) { // non existent root is a legal state. | ||
} else { | ||
SubtreeSummary res = checkSubTree(bt, tid, dirtypages, | ||
rtptr.getRootId(), null, null, rtptr.getId(), checkOccupancy, 0); | ||
assert (res.ptrLeft == null); | ||
assert (res.ptrRight == null); | ||
} | ||
} | ||
|
||
static SubtreeSummary checkSubTree(BTreeFile bt, TransactionId tid, Map<PageId, Page> dirtypages, | ||
BTreePageId pageId, Field lowerBound, Field upperBound, | ||
BTreePageId parentId, boolean checkOccupancy, int depth) throws | ||
TransactionAbortedException, DbException { | ||
BTreePage page = (BTreePage) bt.getPage(tid, dirtypages, pageId, Permissions.READ_ONLY); | ||
assert (page.getParentId().equals(parentId)); | ||
|
||
if (page.getId().pgcateg() == BTreePageId.LEAF) { | ||
BTreeLeafPage bpage = (BTreeLeafPage) page; | ||
bpage.checkRep(bt.keyField(), lowerBound, upperBound, checkOccupancy, depth); | ||
return new SubtreeSummary(bpage, depth); | ||
} else if (page.getId().pgcateg() == BTreePageId.INTERNAL) { | ||
|
||
BTreeInternalPage ipage = (BTreeInternalPage) page; | ||
ipage.checkRep(lowerBound, upperBound, checkOccupancy, depth); | ||
|
||
SubtreeSummary acc = null; | ||
BTreeEntry prev = null; | ||
Iterator<BTreeEntry> it = ipage.iterator(); | ||
|
||
prev = it.next(); | ||
{ // init acc and prev. | ||
acc = checkSubTree(bt, tid, dirtypages, prev.getLeftChild(), lowerBound, prev.getKey(), ipage.getId(), | ||
checkOccupancy, depth + 1); | ||
lowerBound = prev.getKey(); | ||
} | ||
|
||
assert (acc != null); | ||
BTreeEntry curr = prev; // for one entry case. | ||
while (it.hasNext()) { | ||
curr = it.next(); | ||
SubtreeSummary currentSubTreeResult = | ||
checkSubTree(bt, tid, dirtypages, curr.getLeftChild(), lowerBound, curr.getKey(), ipage.getId(), | ||
checkOccupancy, depth + 1); | ||
acc = SubtreeSummary.checkAndMerge(acc, currentSubTreeResult); | ||
|
||
// need to move stuff for next iter: | ||
lowerBound = curr.getKey(); | ||
} | ||
|
||
SubtreeSummary lastRight = checkSubTree(bt, tid, dirtypages, curr.getRightChild(), lowerBound, upperBound, | ||
ipage.getId(), checkOccupancy, depth + 1); | ||
acc = SubtreeSummary.checkAndMerge(acc, lastRight); | ||
|
||
return acc; | ||
} else { | ||
assert (false); // no other page types allowed inside the tree. | ||
return null; | ||
} | ||
} | ||
} |
This file contains 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,144 @@ | ||
package simpledb.index; | ||
|
||
import simpledb.storage.Field; | ||
import simpledb.storage.RecordId; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* Each instance of BTreeEntry stores one key and two child page ids. It is used | ||
* by BTreeInternalPage as an abstraction to iterate through the entries stored inside. | ||
* All of the entries or tuples in the left child page should be less than or equal to | ||
* the key, and all of the entries or tuples in the right child page should be greater | ||
* than or equal to the key. | ||
* <p> | ||
* Note that updating a BTreeEntry does not actually change the data stored on the page | ||
* identified by its recordId. After updating a BTreeEntry object, you must call | ||
* BTreeInternalPage.updateEntry() in order for the changes to take effect. | ||
* | ||
* @see BTreeInternalPage | ||
* @see BTreeInternalPage#updateEntry(BTreeEntry) | ||
*/ | ||
public class BTreeEntry implements Serializable { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
/** | ||
* The key of this entry | ||
*/ | ||
private Field key; | ||
|
||
/** | ||
* The left child page id | ||
*/ | ||
private BTreePageId leftChild; | ||
|
||
/** | ||
* The right child page id | ||
*/ | ||
private BTreePageId rightChild; | ||
|
||
/** | ||
* The record id of this entry | ||
*/ | ||
private RecordId rid; // null if not stored on any page | ||
|
||
/** | ||
* Constructor to create a new BTreeEntry | ||
* | ||
* @param key - the key | ||
* @param leftChild - page id of the left child | ||
* @param rightChild - page id of the right child | ||
*/ | ||
public BTreeEntry(Field key, BTreePageId leftChild, BTreePageId rightChild) { | ||
this.key = key; | ||
this.leftChild = leftChild; | ||
this.rightChild = rightChild; | ||
} | ||
|
||
/** | ||
* @return the key | ||
*/ | ||
public Field getKey() { | ||
return key; | ||
} | ||
|
||
/** | ||
* @return the left child page id | ||
*/ | ||
public BTreePageId getLeftChild() { | ||
return leftChild; | ||
} | ||
|
||
/** | ||
* @return the right child page id | ||
*/ | ||
public BTreePageId getRightChild() { | ||
return rightChild; | ||
} | ||
|
||
/** | ||
* @return the record id of this entry, representing the location of this entry | ||
* in a BTreeFile. May be null if this entry is not stored on any page in the file | ||
*/ | ||
public RecordId getRecordId() { | ||
return rid; | ||
} | ||
|
||
/** | ||
* Set the key for this entry. Note that updating a BTreeEntry does not | ||
* actually change the data stored on the page identified by its recordId. After | ||
* calling this method, you must call BTreeInternalPage.updateEntry() in order for | ||
* it to take effect. | ||
* | ||
* @param key - the new key | ||
* @see BTreeInternalPage#updateEntry(BTreeEntry) | ||
*/ | ||
public void setKey(Field key) { | ||
this.key = key; | ||
} | ||
|
||
/** | ||
* Set the left child id for this entry. Note that updating a BTreeEntry does not | ||
* actually change the data stored on the page identified by its recordId. After | ||
* calling this method, you must call BTreeInternalPage.updateEntry() in order for | ||
* it to take effect. | ||
* | ||
* @param leftChild - the new left child | ||
* @see BTreeInternalPage#updateEntry(BTreeEntry) | ||
*/ | ||
public void setLeftChild(BTreePageId leftChild) { | ||
this.leftChild = leftChild; | ||
} | ||
|
||
/** | ||
* Set the right child id for this entry. Note that updating a BTreeEntry does not | ||
* actually change the data stored on the page identified by its recordId. After | ||
* calling this method, you must call BTreeInternalPage.updateEntry() in order for | ||
* it to take effect. | ||
* | ||
* @param rightChild - the new right child | ||
* @see BTreeInternalPage#updateEntry(BTreeEntry) | ||
*/ | ||
public void setRightChild(BTreePageId rightChild) { | ||
this.rightChild = rightChild; | ||
} | ||
|
||
/** | ||
* set the record id for this entry | ||
* | ||
* @param rid - the new record id | ||
*/ | ||
public void setRecordId(RecordId rid) { | ||
this.rid = rid; | ||
} | ||
|
||
/** | ||
* Prints a representation of this BTreeEntry | ||
*/ | ||
public String toString() { | ||
return "[" + leftChild.getPageNumber() + "|" + key + "|" + rightChild.getPageNumber() + "]"; | ||
} | ||
|
||
} | ||
|
Oops, something went wrong.