Algebra Layer Stub Code
Algebra.cpp
int Algebra::insert(char relName[ATTR_SIZE], int nAttrs, char record[][ATTR_SIZE]){
// if relName is equal to "RELATIONCAT" or "ATTRIBUTECAT"
// return E_NOTPERMITTED;
// get the relation's rel-id using OpenRelTable::getRelId() method
int relId = OpenRelTable::getRelId(relName);
// if relation is not open in open relation table, return E_RELNOTOPEN
// (check if the value returned from getRelId function call = E_RELNOTOPEN)
// get the relation catalog entry from relation cache
// (use RelCacheTable::getRelCatEntry() of Cache Layer)
/* if relCatEntry.numAttrs != numberOfAttributes in relation,
return E_NATTRMISMATCH */
// let recordValues[numberOfAttributes] be an array of type union Attribute
/*
Converting 2D char array of record values to Attribute array recordValues
*/
// iterate through 0 to nAttrs-1: (let i be the iterator)
{
// get the attr-cat entry for the i'th attribute from the attr-cache
// (use AttrCacheTable::getAttrCatEntry())
// let type = attrCatEntry.attrType;
if (type == NUMBER)
{
// if the char array record[i] can be converted to a number
// (check this using isNumber() function)
{
/* convert the char array to numeral and store it
at recordValues[i].nVal using atof() */
}
// else
{
return E_ATTRTYPEMISMATCH;
}
}
else if (type == STRING)
{
// copy record[i] to recordValues[i].sVal
}
}
// insert the record by calling BlockAccess::insert() function
// let retVal denote the return value of insert call
return retVal;
}
int Algebra::select(char srcRel[ATTR_SIZE], char targetRel[ATTR_SIZE], char attr[ATTR_SIZE], int op, char strVal[ATTR_SIZE]) {
// get the srcRel's rel-id (let it be srcRelid), using OpenRelTable::getRelId()
// if srcRel is not open in open relation table, return E_RELNOTOPEN
// get the attr-cat entry for attr, using AttrCacheTable::getAttrCatEntry()
// if getAttrcatEntry() call fails return E_ATTRNOTEXIST
/*** Convert strVal to an attribute of data type NUMBER or STRING ***/
Attribute attrVal;
int type = attrCatEntry.attrType;
if (type == NUMBER)
{
// if the input argument strVal can be converted to a number
// (check this using isNumber() function)
{
// convert strVal to double and store it at attrVal.nVal using atof()
}
// else
{
return E_ATTRTYPEMISMATCH;
}
}
else if (type == STRING)
{
// copy strVal to attrVal.sVal
}
/*** Creating and opening the target relation ***/
// Prepare arguments for createRel() in the following way:
// get RelcatEntry of srcRel using RelCacheTable::getRelCatEntry()
int src_nAttrs = /* the no. of attributes present in src relation */ ;
/* let attr_names[src_nAttrs][ATTR_SIZE] be a 2D array of type char
(will store the attribute names of rel). */
// let attr_types[src_nAttrs] be an array of type int
/*iterate through 0 to src_nAttrs-1 :
get the i'th attribute's AttrCatEntry using AttrCacheTable::getAttrCatEntry()
fill the attr_names, attr_types arrays that we declared with the entries
of corresponding attributes
*/
/* Create the relation for target relation by calling Schema::createRel()
by providing appropriate arguments */
// if the createRel returns an error code, then return that value.
/* Open the newly created target relation by calling OpenRelTable::openRel()
method and store the target relid */
/* If opening fails, delete the target relation by calling Schema::deleteRel()
and return the error value returned from openRel() */
/*** Selecting and inserting records into the target relation ***/
/* Before calling the search function, reset the search to start from the
first using RelCacheTable::resetSearchIndex() */
Attribute record[src_nAttrs];
/*
The BlockAccess::search() function can either do a linearSearch or
a B+ tree search. Hence, reset the search index of the relation in the
relation cache using RelCacheTable::resetSearchIndex().
Also, reset the search index in the attribute cache for the select
condition attribute with name given by the argument `attr`. Use
AttrCacheTable::resetSearchIndex().
Both these calls are necessary to ensure that search begins from the
first record.
*/
RelCacheTable::resetSearchIndex(/* fill arguments */);
AttrCacheTable::resetSearchIndex(/* fill arguments */);
// read every record that satisfies the condition by repeatedly calling
// BlockAccess::search() until there are no more records to be read
while (/* BlockAccess::search() returns success */) {
// ret = BlockAccess::insert(targetRelId, record);
// if (insert fails) {
// close the targetrel(by calling Schema::closeRel(targetrel))
// delete targetrel (by calling Schema::deleteRel(targetrel))
// return ret;
// }
}
// Close the targetRel by calling closeRel() method of schema layer
// return SUCCESS.
}
int Algebra::project(char srcRel[ATTR_SIZE], char targetRel[ATTR_SIZE], int tar_nAttrs, char tar_Attrs[][ATTR_SIZE]) {
int srcRelId = /*srcRel's rel-id (use OpenRelTable::getRelId() function)*/
// if srcRel is not open in open relation table, return E_RELNOTOPEN
// get RelCatEntry of srcRel using RelCacheTable::getRelCatEntry()
// get the no. of attributes present in relation from the fetched RelCatEntry.
// declare attr_offset[tar_nAttrs] an array of type int.
// where i-th entry will store the offset in a record of srcRel for the
// i-th attribute in the target relation.
// let attr_types[tar_nAttrs] be an array of type int.
// where i-th entry will store the type of the i-th attribute in the
// target relation.
/*** Checking if attributes of target are present in the source relation
and storing its offsets and types ***/
/*iterate through 0 to tar_nAttrs-1 :
- get the attribute catalog entry of the attribute with name tar_attrs[i].
- if the attribute is not found return E_ATTRNOTEXIST
- fill the attr_offset, attr_types arrays of target relation from the
corresponding attribute catalog entries of source relation
*/
/*** Creating and opening the target relation ***/
// Create a relation for target relation by calling Schema::createRel()
// if the createRel returns an error code, then return that value.
// Open the newly created target relation by calling OpenRelTable::openRel()
// and get the target relid
// If opening fails, delete the target relation by calling Schema::deleteRel()
// and return the error value from openRel()
/*** Inserting projected records into the target relation ***/
// Take care to reset the searchIndex before calling the project function
// using RelCacheTable::resetSearchIndex()
Attribute record[src_nAttrs];
while (/* BlockAccess::project(srcRelId, record) returns SUCCESS */) {
// the variable `record` will contain the next record
Attribute proj_record[tar_nAttrs];
//iterate through 0 to tar_attrs-1:
// proj_record[attr_iter] = record[attr_offset[attr_iter]]
// ret = BlockAccess::insert(targetRelId, proj_record);
if (/* insert fails */) {
// close the targetrel by calling Schema::closeRel()
// delete targetrel by calling Schema::deleteRel()
// return ret;
}
}
// Close the targetRel by calling Schema::closeRel()
// return SUCCESS.
}
int Algebra::project(char srcRel[ATTR_SIZE], char targetRel[ATTR_SIZE]) {
int srcRelId = /*srcRel's rel-id (use OpenRelTable::getRelId() function)*/
// if srcRel is not open in open relation table, return E_RELNOTOPEN
// get RelCatEntry of srcRel using RelCacheTable::getRelCatEntry()
// get the no. of attributes present in relation from the fetched RelCatEntry.
// attrNames and attrTypes will be used to store the attribute names
// and types of the source relation respectively
char attrNames[numAttrs][ATTR_SIZE];
int attrTypes[numAttrs];
/*iterate through every attribute of the source relation :
- get the AttributeCat entry of the attribute with offset.
(using AttrCacheTable::getAttrCatEntry())
- fill the arrays `attrNames` and `attrTypes` that we declared earlier
with the data about each attribute
*/
/*** Creating and opening the target relation ***/
// Create a relation for target relation by calling Schema::createRel()
// if the createRel returns an error code, then return that value.
// Open the newly created target relation by calling OpenRelTable::openRel()
// and get the target relid
// If opening fails, delete the target relation by calling Schema::deleteRel() of
// return the error value returned from openRel().
/*** Inserting projected records into the target relation ***/
// Take care to reset the searchIndex before calling the project function
// using RelCacheTable::resetSearchIndex()
Attribute record[numAttrs];
while (/* BlockAccess::project(srcRelId, record) returns SUCCESS */)
{
// record will contain the next record
// ret = BlockAccess::insert(targetRelId, proj_record);
if (/* insert fails */) {
// close the targetrel by calling Schema::closeRel()
// delete targetrel by calling Schema::deleteRel()
// return ret;
}
}
// Close the targetRel by calling Schema::closeRel()
// return SUCCESS.
}
int join(char srcRelation1[ATTR_SIZE], char srcRelation2[ATTR_SIZE], char targetRelation[ATTR_SIZE], char attribute1[ATTR_SIZE], char attribute2[ATTR_SIZE]) {
// get the srcRelation1's rel-id using OpenRelTable::getRelId() method
// get the srcRelation2's rel-id using OpenRelTable::getRelId() method
// if either of the two source relations is not open
// return E_RELNOTOPEN
AttrCatEntry attrCatEntry1, attrCatEntry2;
// get the attribute catalog entries for the following from the attribute cache
// (using AttrCacheTable::getAttrCatEntry())
// - attrCatEntry1 = attribute1 of srcRelation1
// - attrCatEntry2 = attribute2 of srcRelation2
// if attribute1 is not present in srcRelation1 or attribute2 is not
// present in srcRelation2 (getAttrCatEntry() returned E_ATTRNOTEXIST)
// return E_ATTRNOTEXIST.
// if attribute1 and attribute2 are of different types return E_ATTRTYPEMISMATCH
// iterate through all the attributes in both the source relations and check if
// there are any other pair of attributes other than join attributes
// (i.e. attribute1 and attribute2) with duplicate names in srcRelation1 and
// srcRelation2 (use AttrCacheTable::getAttrCatEntry())
// If yes, return E_DUPLICATEATTR
// get the relation catalog entries for the relations from the relation cache
// (use RelCacheTable::getRelCatEntry() function)
int numOfAttributes1 = /* number of attributes in srcRelation1 */;
int numOfAttributes2 = /* number of attributes in srcRelation2 */;
// if rel2 does not have an index on attr2
// create it using BPlusTree:bPlusCreate()
// if call fails, return the appropriate error code
// (if your implementation is correct, the only error code that will
// be returned here is E_DISKFULL)
int numOfAttributesInTarget = numOfAttributes1 + numOfAttributes2 - 1;
// Note: The target relation has number of attributes one less than
// nAttrs1+nAttrs2 (Why?)
// declare the following arrays to store the details of the target relation
char targetRelAttrNames[numOfAttributesInTarget][ATTR_SIZE];
int targetRelAttrTypes[numOfAttributesInTarget];
// iterate through all the attributes in both the source relations and
// update targetRelAttrNames[],targetRelAttrTypes[] arrays excluding attribute2
// in srcRelation2 (use AttrCacheTable::getAttrCatEntry())
// create the target relation using the Schema::createRel() function
// if createRel() returns an error, return that error
// Open the targetRelation using OpenRelTable::openRel()
// if openRel() fails (No free entries left in the Open Relation Table)
{
// delete target relation by calling Schema::deleteRel()
// return the error code
}
Attribute record1[numOfAttributes1];
Attribute record2[numOfAttributes2];
Attribute targetRecord[numOfAttributesInTarget];
// this loop is to get every record of the srcRelation1 one by one
while (BlockAccess::project(srcRelId1, record1) == SUCCESS) {
// reset the search index of `srcRelation2` in the relation cache
// using RelCacheTable::resetSearchIndex()
// reset the search index of `attribute2` in the attribute cache
// using AttrCacheTable::resetSearchIndex()
// this loop is to get every record of the srcRelation2 which satisfies
//the following condition:
// record1.attribute1 = record2.attribute2 (i.e. Equi-Join condition)
while (BlockAccess::search(
srcRelId2, record2, attribute2, record1[attrCatEntry1.offset], EQ
) == SUCCESS ) {
// copy srcRelation1's and srcRelation2's attribute values(except
// for attribute2 in rel2) from record1 and record2 to targetRecord
// insert the current record into the target relation by calling
// BlockAccess::insert()
if(/* insert fails (insert should fail only due to DISK being FULL) */) {
// close the target relation by calling OpenRelTable::closeRel()
// delete targetRelation (by calling Schema::deleteRel())
return E_DISKFULL;
}
}
}
// close the target relation by calling OpenRelTable::closeRel()
return SUCCESS;
}