/** * This routine loads the specified relation, which must already have been created, * with data from the specified file * argv[0] - "load" * argv[1] - relation name * argv[2] - data file name (full path) * * @param argc * @param argv * @return OK or NOTOK * @author nithin * * GLOBAL VARIABLES MODIFIED: * g_CheckDuplicateTuples * * ERRORS REPORTED: * DB_NOT_OPEN * METADATA_SECURITY * REL_NOT_EMPTY * INVALID_FILE * * ALGORITHM: * 1. Check if DB is open and if trying to loaf into attrcat ot relcat * 2. Open relation with given name * 3. Check if the relation is empty * 4. Open the file given * 5. Read a byte array of recLength size and call InsertRec() * * IMPLEMENTATION NOTES: * Uses InsertRec(), OpenRel(), FindRelNum() * */ int Load(int argc, char **argv) { if (g_DBOpenFlag != OK) { return ErrorMsgs(DB_NOT_OPEN, g_PrintFlag); } char relName[RELNAME]; strncpy(relName, argv[1], RELNAME); if (strcmp(relName, ATTRCAT) == 0 || strcmp(relName, RELCAT) == 0) { return ErrorMsgs(METADATA_SECURITY, g_PrintFlag); } if (OpenRel(relName) == NOTOK) { return NOTOK; } int relNum = FindRelNum(relName); if (g_CatCache[relNum].numRecs > 0) { return ErrorMsgs(REL_NOT_EMPTY, g_PrintFlag); } int fd = open(argv[2], O_RDONLY); if (fd < 0) { return ErrorMsgs(INVALID_FILE, g_PrintFlag); } int recLength = g_CatCache[relNum].recLength; char *newRec = (char *) calloc(recLength, sizeof(char)); g_CheckDuplicateTuples = NOTOK; while (read(fd, newRec, recLength) == recLength) { if (InsertRec(relNum, newRec) != OK) { return NOTOK; } } g_CheckDuplicateTuples = OK; return OK; /* all's fine */ }
int Select(int argc, char **argv) { if (g_DBOpenFlag != OK) { return ErrorMsgs(DB_NOT_OPEN, g_PrintFlag); } int relNum, newRelNum, numAttrs, count, i, retVal, offset, attrFoundFlag = 0; int attrSize, intVal; float floatVal; struct attrCatalog* head; datatype type; Rid startRid = { 1, 0 }, *foundRid; char **createArgumentList, *recPtr; if (argc < 6) return ErrorMsgs(ARGC_INSUFFICIENT, g_PrintFlag); if (OpenRel(argv[2]) == NOTOK) return ErrorMsgs(RELNOEXIST, g_PrintFlag); /* Finding the relNum of Source Relation */ relNum = FindRelNum(argv[2]); head = g_CatCache[relNum].attrList; numAttrs = g_CatCache[relNum].numAttrs; /* Preparing Argument list which should be passed to Create() */ createArgumentList = malloc(sizeof(char*) * (numAttrs + 1) * 2); createArgumentList[0] = malloc(sizeof(char) * RELNAME); createArgumentList[1] = malloc(sizeof(char) * RELNAME); for (count = 2; count < (numAttrs + 1) * 2; count++) { createArgumentList[count] = malloc(sizeof(char) * RELNAME); createArgumentList[count + 1] = malloc(sizeof(char) * 4); } strcpy(createArgumentList[0], "create"); strcpy(createArgumentList[1], argv[1]); count = 2; while (head != NULL) { strcpy(createArgumentList[count], head->attrName); switch (head->type) { case INTEGER: strcpy(createArgumentList[count + 1], "i"); break; case STRING: sprintf(createArgumentList[count + 1], "s%d", head->length); break; case FLOAT: strcpy(createArgumentList[count + 1], "f"); break; } /* This is to catch the desired attribute's specifications from Source relation. Expected to happen only once in this loop */ if (strcmp(head->attrName, argv[3]) == 0) { attrFoundFlag = 1; offset = head->offset; type = head->type; attrSize = head->length; } head = head->next; count = count + 2; } /* Given attribute name never appeared in attr linkedlist */ if (attrFoundFlag == 0) return ErrorMsgs(ATTRNOEXIST, g_PrintFlag); retVal = Create((numAttrs + 1) * 2, createArgumentList); for (i = 0; i < (numAttrs + 1) * 2; i++) free(createArgumentList[i]); free(createArgumentList); if (retVal == NOTOK) return NOTOK; OpenRel(argv[1]); newRelNum = FindRelNum(argv[1]); switch (type) { case STRING: break; case INTEGER: intVal = atoi(argv[5]); convertIntToByteArray(intVal, argv[5]); break; case FLOAT: floatVal = atof(argv[5]); convertFloatToByteArray(floatVal, argv[5]); break; } /* Finding record from Source, which satisfying given condition, and Adding to Result Relation*/ while (FindRec(relNum, &startRid, &foundRid, &recPtr, type, attrSize, offset, argv[5], readIntFromByteArray(argv[4], 0)) == OK) { InsertRec(newRelNum, recPtr); startRid = (*foundRid); free(foundRid); } return OK; }
int Join(int argc, char **argv) { if (g_DBOpenFlag != OK) { return ErrorMsgs(DB_NOT_OPEN, g_PrintFlag); } int relNum1, relNum2, count, attrFoundFlag = 0, i, retVal, recResultLength; int numAttrsRel1, numAttrsRel2, numAttrsTotal; int offset1, offset2, attrSize1, attrSize2, newRelNum; datatype type1, type2; struct attrCatalog *head; char **argumentList, *recPtr1, *recPtr2, *recResult; Rid startRidRel1 = { 1, 0 }, startRidRel2 = { 1, 0 }, *foundRidRel1, *foundRidRel2; if (argc < 6) return ErrorMsgs(ARGC_INSUFFICIENT, g_PrintFlag); if ((relNum1 = OpenRel(argv[2])) == NOTOK || (relNum2 = OpenRel(argv[4])) == NOTOK) return ErrorMsgs(RELNOEXIST, g_PrintFlag); numAttrsRel1 = g_CatCache[relNum1].numAttrs; numAttrsRel2 = g_CatCache[relNum2].numAttrs; numAttrsTotal = numAttrsRel1 + numAttrsRel2; /* Preparing Argument list which should be passed to Create() */ argumentList = malloc(sizeof(char*) * (numAttrsTotal * 2)); argumentList[0] = malloc(sizeof(char) * RELNAME); argumentList[1] = malloc(sizeof(char) * RELNAME); for (count = 2; count < numAttrsTotal * 2; count++) { argumentList[count] = malloc(sizeof(char) * RELNAME); argumentList[count + 1] = malloc(sizeof(char) * 4); } strcpy(argumentList[0], "create"); strcpy(argumentList[1], argv[1]); count = 2; head = g_CatCache[relNum1].attrList; while (head != NULL) { strcpy(argumentList[count], head->attrName); switch (head->type) { case INTEGER: strcpy(argumentList[count + 1], "i"); break; case STRING: sprintf(argumentList[count + 1], "s%d", head->length); break; case FLOAT: strcpy(argumentList[count + 1], "f"); break; } if (strcmp(head->attrName, argv[3]) == 0) { attrFoundFlag = 1; offset1 = head->offset; type1 = head->type; attrSize1 = head->length; } head = head->next; count = count + 2; } if (attrFoundFlag == 0) return ErrorMsgs(ATTRNOEXIST, g_PrintFlag); /* Next Relation's attribute list */ attrFoundFlag = 0; head = g_CatCache[relNum2].attrList; while (head != NULL) { if (strcmp(head->attrName, argv[5]) == 0) { attrFoundFlag = 1; offset2 = head->offset; type2 = head->type; attrSize2 = head->length; } /* Skipping the join attribute in 2nd relation */ if (strcmp(head->attrName, argv[5]) == 0) { head = head->next; continue; } strcpy(argumentList[count], head->attrName); /* This is to give different name for same attribute names in two Relations */ for (i = 2; i < numAttrsRel1 + 2; i = i + 2) if (strcmp(argumentList[i], head->attrName) == 0) { strcat(argumentList[count], "_2"); } switch (head->type) { case INTEGER: strcpy(argumentList[count + 1], "i"); break; case STRING: sprintf(argumentList[count + 1], "s%d", head->length); break; case FLOAT: strcpy(argumentList[count + 1], "f"); break; } head = head->next; count = count + 2; } if (attrFoundFlag == 0) return ErrorMsgs(ATTRNOEXIST, g_PrintFlag); retVal = Create(numAttrsTotal * 2, argumentList); if (retVal == NOTOK) return NOTOK; OpenRel(argv[1]); newRelNum = FindRelNum(argv[1]); for (i = 0; i < numAttrsTotal * 2; i++) free(argumentList[i]); free(argumentList); if (type1 != type2) return ErrorMsgs(TYPE_MISMATCH, g_PrintFlag); recResultLength = g_CatCache[relNum1].recLength + g_CatCache[relNum2].recLength - attrSize2; recResult = malloc(sizeof(char) * (recResultLength)); while (GetNextRec(relNum1, &startRidRel1, &foundRidRel1, &recPtr1) == OK) { startRidRel2.pid = 1; startRidRel2.slotnum = 0; while (FindRec(relNum2, &startRidRel2, &foundRidRel2, &recPtr2, type2, attrSize2, offset2, recPtr1 + offset1, EQ) == OK) { copyBinaryArray(recResult, recPtr1, g_CatCache[relNum1].recLength); copyBinaryArray(recResult + g_CatCache[relNum1].recLength, recPtr2, offset2); copyBinaryArray(recResult + g_CatCache[relNum1].recLength + offset2, recPtr2 + offset2 + attrSize2, g_CatCache[relNum2].recLength - offset2 - attrSize2); InsertRec(newRelNum, recResult); startRidRel2 = *foundRidRel2; free(foundRidRel2); } startRidRel1 = *foundRidRel1; free(foundRidRel1); } return OK; }
int main() { printf("******************************************\n"); printf("* Record Manager Application *\n"); printf("* Xinyi He *\n"); printf("******************************************\n"); char c; do { printf("\n"); printf("a. Open database\n"); printf("b. Get first record\n"); printf("c. Get next record \n"); printf("d. Get previous record\n"); printf("e. Get Nth record\n"); printf("f. Insert record\n"); printf("g. Bulk insert records in file\n"); printf("h. Delete record\n"); printf("i. Update record\n"); printf("j. Find record with first attribute value\n"); printf("k. Show catalog file\n"); printf("l. Get first page\n"); printf("m. Get next page\n"); printf("n. Show buf stats\n"); printf("o. Commit changes\n"); printf("p. Exit\n"); printf("Please press letter to choose an action.\n"); c = getchar(); fflush(stdin); char filename[100]; switch (c) { //a. Open database case 'a': { printf("Please input the database name (don't include extension): "); gets(filename); OpenStore(filename); break; } //b. Get first record case 'b': { Output(FirstRec()); break; } //c. Get next record case 'c': { Output(NextRec()); break; } //d. Get previous record case 'd': { Output(PriorRec()); break; } //e. Get Nth record case 'e': { printf("\nInput N: "); int n; scanf("%d", &n); Output(NRec(n)); fflush(stdin); break; } //f. Insert record case 'f': { printf("\nInput a comma-delimited Record:\n"); char statement[100]; scanf("%s", &statement); fflush(stdin); InsertRec(statement); break; } //g. Bulk insert records in file case 'g': { printf("\nInput the filename(include extension): "); char file[100]; scanf("%s", &file); InsertRecFromFile(file); fflush(stdin); break; } //h. Delete record case 'h': { DeleteRec(); break; } //i. Update record case 'i': { printf("\nInput a comma-delimited Record:\n"); char statement[100]; scanf("%s", &statement); fflush(stdin); UpdateRec(statement); break; } //j. Find record with first attribute value case 'j': { printf("\nInput value:\n"); char statement[100]; scanf("%s", &statement); fflush(stdin); SearchRec(statement); break; } //k. Show catalog file case 'k': { DisplyCatFile(filename); break; } //l. Get first page case 'l': { GetPage(0); break; } //m. Get next page case 'm': { GetPage(1); break; } //n. Show buf stats case 'n': { ShowBuf(); break; } //o. Commit changes case 'o': { Commit(filename); break; } //p. Exit case 'p': { CloseStore(filename); } }; }while(c != 'p'); return 0; }