Status Operators::Join(const string& result, // Name of the output relation const int projCnt, // Number of attributes in the projection const attrInfo projNames[], // List of projection attributes const attrInfo* attr1, // Left attr in the join predicate const Operator op, // Predicate operator const attrInfo* attr2) // Right attr in the join predicate { /* Your solution goes here */ Status prep_status; int rec_len = 0; AttrDesc output_attrs[projCnt]; for (int i = 0; i < projCnt; i++) { prep_status = attrCat->getInfo(projNames[i].relName, projNames[i].attrName, output_attrs[i]); if (prep_status != OK) { return prep_status; } rec_len += output_attrs[i].attrLen; } AttrDesc attrdesc1, attrdesc2; prep_status = attrCat->getInfo(attr1->relName, attr1->attrName, attrdesc1); if (prep_status != OK) { return prep_status; } prep_status = attrCat->getInfo(attr2->relName, attr2->attrName, attrdesc2); if (prep_status != OK) { return prep_status; } Status status; if (op != EQ) { // non-equi join status = SNL(result, projCnt, output_attrs, attrdesc1, op, attrdesc2, rec_len); } else { if (attrdesc1.indexed) { status = INL(result, projCnt, output_attrs, attrdesc2, op, attrdesc1, rec_len); } else if (attrdesc2.indexed) { status = INL(result, projCnt, output_attrs, attrdesc1, op, attrdesc2, rec_len); } else { status = SMJ(result, projCnt, output_attrs, attrdesc1, op, attrdesc2, rec_len); } } if (status != OK) { return status; } return OK; }
Status Operators::Join(const string& result, // Name of the output relation const int projCnt, // Number of attributes in the projection const attrInfo projNames[], // List of projection attributes const attrInfo* attr1, // Left attr in the join predicate const Operator op, // Predicate operator const attrInfo* attr2) // Right attr in the join predicate { Status status; /* Minirel guarantees there will be a Join Condition => Populate the attr_desc objects */ AttrDesc attr_desc1, attr_desc2; status = attrCat->getInfo(attr1->relName, attr1->attrName, attr_desc1); if(status != OK) return status; status = attrCat->getInfo(attr2->relName, attr2->attrName, attr_desc2); if(status != OK) return status; /* Find the length of a resulting record and populate the proj_names array */ int reclen; AttrDesc *proj_names = new AttrDesc[projCnt]; status = ConvertInfoToDesc(projNames, projCnt, proj_names, reclen); if(status != OK) { delete [] proj_names; return status; } if(op != EQ) SNL(result, projCnt, proj_names, attr_desc1, op, attr_desc2, reclen); else { if(attr_desc1.indexed) INL(result, projCnt, proj_names, attr_desc2, negate_operator(op), attr_desc1, reclen); else if(attr_desc1.indexed) INL(result, projCnt, proj_names, attr_desc1, op, attr_desc2, reclen); else SMJ(result, projCnt, proj_names, attr_desc1, op, attr_desc2, reclen); } return OK; }
Status Operators::Join(const string& result, // Name of the output relation const int projCnt, // Number of attributes in the projection const attrInfo projNames[], // List of projection attributes const attrInfo* attr1, // Left attr in the join predicate const Operator op, // Predicate operator const attrInfo* attr2) // Right attr in the join predicate { // Fetch attribute descriptions string relation1 = attr1->relName; string relation2 = attr2->relName; AttrDesc* inputDescs1, * inputDescs2; int attrCnt1, attrCnt2; Status status = attrCat->getRelInfo(relation1, attrCnt1, inputDescs1); if (status != OK) { return status; } status = attrCat->getRelInfo(relation2, attrCnt2, inputDescs2); if (status != OK) { return status; } // Construct list of projected attribute descriptions AttrDesc* projAttrDescs = new AttrDesc[projCnt]; int reclen = 0; //search through the first relation for an attribute match for (int i = 0; i < projCnt; ++i) { bool found = false; int j; for (j = 0; j < attrCnt1; ++j) { if (!strcmp(projNames[i].attrName, inputDescs1->attrName) && !strcmp(projNames[i].relName, inputDescs1->relName)) { *projAttrDescs++ = *inputDescs1; reclen += inputDescs1->attrLen; found = true; break; } inputDescs1++; } inputDescs1 -= j; if (found) { continue; } //If not found in the first relation, search for the attribute in the second relation for (j = 0; j < attrCnt2; ++j) { if (!strcmp(projNames[i].attrName, inputDescs2->attrName) && !strcmp(projNames[i].relName, inputDescs2->relName)) { *projAttrDescs++ = *inputDescs2; reclen += inputDescs2->attrLen; found = true; break; } inputDescs2++; } inputDescs2 -= j; assert(found); } projAttrDescs -= projCnt; // Convert criterion attributes to AttrDesc AttrDesc cDesc1, cDesc2; status = attrCat->getInfo(relation1, attr1->attrName, cDesc1); if (status != OK) { return status; } status = attrCat->getInfo(relation2, attr2->attrName, cDesc2); if (status != OK) { return status; } // Delegate sub-join operations if (op != EQ) { //Perform SNL. Might have to switch relation 1 and relation2 //based on which is more efficient as the outer relation HeapFileScan hfs1(relation1, status); if(status != OK) { return status; } HeapFileScan hfs2(relation2, status); if(status != OK) { return status; } //Get num tuples for each file int numTuples1 = hfs1.getRecCnt(); int numTuples2 = hfs2.getRecCnt(); int relSize1 = 0, relSize2 = 0; for (int i = 0; i < attrCnt1; ++i) { relSize1 += (inputDescs1 + i)->attrLen; } for (int i = 0; i < attrCnt1; ++i) { relSize2 += (inputDescs2 + i)->attrLen; } //Calculate num pages for each file int relPages1 = ceil((numTuples1*relSize1)*1.0/PAGESIZE); int relPages2 = ceil((numTuples2*relSize2)*1.0/PAGESIZE); //Use formula to calculate total IOs, to decide in which order to send //SNL the two AttrDesc structs (first parameter is outer, second is inner) if(relPages1 + numTuples1*relPages2 <= relPages2 + numTuples2*relPages1) { return SNL( result, projCnt, projAttrDescs, cDesc1, op, cDesc2, reclen); } else { //Operator needs to be flipped if the order is switched Operator op2; switch(op) { case LT: op2 = GT; break; case GT: op2 = LT; break; case LTE: op2 = GTE; break; case GTE: op2 = LTE; break; default: break; } return SNL( result, projCnt, projAttrDescs, cDesc2, op2, cDesc1, reclen); } } if (cDesc1.indexed || cDesc2.indexed) { return INL( result, projCnt, projAttrDescs, cDesc1, op, cDesc2, reclen); } return SMJ( result, projCnt, projAttrDescs, cDesc1, op, cDesc2, reclen); }