Skip to main content

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;
}