📄 sm_manager.cpp
字号:
if (ret < 1) { break; } //printf ("int = %d\n", j); T.SetValue (i, &j); break; case TYPE_FLOAT: float f; ret = fscanf (ifp, " %f ", &f); if (ret < 1) { break; } //printf ("float = %f\n", f); T.SetValue (i, &f); break; case TYPE_STRING: char s[MAXSTRINGLEN+1]; memset (s, 0, MAXSTRINGLEN+1); ret = fscanf (ifp, " '%[^'\n]' ", s); if (ret < 1) { break; } //printf ("string = %s\n", s); T.SetValue (i, s); break; } /* Check if an error occured */ /* If we reached end of file exit the loop */ if (ret == -1 && i==0) { break; } /* If we encountered an error, clean up and return */ else if (ret < 1) { fprintf (stderr, "*** Error reading attribute ***"); fprintf (stderr, " %s at line %d ***\n", info[i].attrName, lineNum); fprintf (stderr, "Saving the %d tuples read so far..\n", lineNum-1); /* Save records read so far */ fileHandle.ForceAllPages (); /* Free up memory */ free (info); fclose (ifp); /* Close file */ rmm.CloseFile (fileHandle); /* Return error */ return SM_BADINPUT; } } /* Exit loop if an error has occured */ if (ret < 1) { break; } /* Get the tuple's contents */ T.GetData (pData); /* Insert record */ RID rid; rc = fileHandle.InsertRec (pData, rid); if (rc != SUCCESS) { free (info); fclose (ifp); return rc; } /* free up memory now (after inserting record) */ free (pData); pData = NULL; /* Increment line number */ lineNum++; } /* Close the input file */ fclose (ifp); /* Free allocated memory */ free (info); /* Flush dirty pages to disk */ rc = fileHandle.ForceAllPages (); if (rc != SUCCESS) { return rc; } /* Close the file handle */ rc = rmm.CloseFile (fileHandle); if (rc != SUCCESS) { return rc; } printf ("%d tuples read\n", lineNum-1); /* Successfully loaded data into the file */ return SUCCESS;}RC SM_Manager::Help () { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } printf ("Tables in this database:\n"); return Print (relName_relcat);}RC SM_Manager::Help (const char *relName) { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } DataAttrInfo *info; int attrCount; RC rc; /* Determine the structure of the relation */ rc = GetDataAttrInfo (relName, info, attrCount); if (rc != SUCCESS) { return rc; } printf ("Help for %s:\n", relName); /* Print the tuple header */ PrintTupleHeader (dataAttrInfo_attrcat, 5); /* Print out the structure */ for (int i = 0; i < attrCount; i++) { SM_Tuple T (dataAttrInfo_attrcat, 5, info[i].relName, info[i].attrName, info[i].offset, info[i].attrType, info[i].attrLength); T.PrintData (); } /* Free up memory allocated to info */ free (info); /* Successfully printed help */ return SUCCESS;}RC SM_Manager::CrossProduct (const char *rel1, const char *rel2) { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } const char *relName_outer = rel1; const char *relName_inner = rel2; RC rc; RM_FileHandle fileHandle_outer, fileHandle_inner; /* Get a handle to the outer relation */ rc = rmm.OpenFile (relName_outer, fileHandle_outer); if (rc != SUCCESS) { return rc; } /* Get a handle to the inner relation */ rc = rmm.OpenFile (relName_inner, fileHandle_inner); if (rc != SUCCESS) { return rc; } RM_FileScan fileScan_outer, fileScan_inner; /* Open a file scan on the outer relation */ rc = fileScan_outer.OpenScan (fileHandle_outer, TYPE_STRING, MAXNAME, 0, /* <-- Doesn't matter what these 3 values are because the scan is based on NO_OP */ NO_OP, NULL, NO_HINT); if (rc != SUCCESS) { return rc; } /* Open a file scan on the inner relation */ rc = fileScan_inner.OpenScan (fileHandle_inner, TYPE_STRING, MAXNAME, 0, /* <-- Doesn't matter what these 3 values are because the scan is based on NO_OP */ NO_OP, NULL, NO_HINT); if (rc != SUCCESS) { return rc; } /* Determine the attributes present in each relation */ DataAttrInfo *info_outer, *info_inner; int attrCount_outer, attrCount_inner; /* Get attribute information for the outer relation */ rc = GetDataAttrInfo (relName_outer, info_outer, attrCount_outer); if (rc != SUCCESS) { return rc; } /* Get attribute information for the inner relation */ rc = GetDataAttrInfo (relName_inner, info_inner, attrCount_inner); if (rc != SUCCESS) { free (info_outer); return rc; } RM_Record rec_outer, rec_inner; char *pData; int nRecords = 0; /* # of records in cross-product */ /* Do the cross product */ while (fileScan_outer.FetchPages() == SUCCESS) { while (fileScan_inner.FetchPages() == SUCCESS) { while (fileScan_outer.GetNextRecInMem(rec_outer) == SUCCESS) { /* Build an SM_Tuple object from the outer record */ rec_outer.GetData (pData); SM_Tuple T_outer (info_outer, attrCount_outer, pData); while (fileScan_inner.GetNextRecInMem(rec_inner) == SUCCESS) { /* Build an SM_Tuple object from the inner record */ rec_inner.GetData (pData); SM_Tuple T_inner (info_inner, attrCount_inner, pData); /* Combine the two tuples */ SM_Tuple T = T_outer + T_inner; /* Print the tuple */ T.PrintData (); /* Increment count */ nRecords++; } fileScan_inner.JumpToFirstRecInMem(); } fileScan_outer.JumpToFirstRecInMem(); } /* Re-open a file scan on the inner relation */ fileScan_inner.CloseScan(); rc = fileScan_inner.OpenScan (fileHandle_inner, TYPE_STRING, MAXNAME, 0, NO_OP, NULL, NO_HINT); if (rc != SUCCESS) { free (info_outer); free (info_inner); return rc; } } /* Print # of records in the cross-product */ printf ("%d records in cross-product\n", nRecords); /* Free up attribute information for the inner relation */ free (info_inner); /* Free up attribute information for the outer relation */ free (info_outer); /* Close the inner file scan */ rc = fileScan_inner.CloseScan (); if (rc != SUCCESS) { return rc; } /* Close the outer file scan */ rc = fileScan_outer.CloseScan (); if (rc != SUCCESS) { return rc; } /* Close the inner file handle */ rc = rmm.CloseFile (fileHandle_inner); if (rc != SUCCESS) { return rc; } /* Close the outer file handle */ rc = rmm.CloseFile (fileHandle_outer); if (rc != SUCCESS) { return rc; } /* Successfully joined relations */ return SUCCESS;}RC SM_Manager::EquiJoin (const char *rel1, const char *rel2, const int *attrList1, const int *attrList2, int condCount) { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } /* // Uncomment these lines const char *relName_outer = rel1; const char *relName_inner = rel2; const int *attrList_outer = attrList1; const int *attrList_inner = attrList2; */ /* ---- Write your equi-join code here ---- */ /* Successfully joined relations */ return SUCCESS;}RC SM_Manager::EquiJoin_Opt (const char *rel1, const char *rel2, const int *attrList1, const int *attrList2, int condCount) { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } /* // Uncomment these lines const char *relName_outer = rel1; const char *relName_inner = rel2; const int *attrList_outer = attrList1; const int *attrList_inner = attrList2; */ /* ---- Write your optimized equi-join code here ---- */ /* Successfully joined relations */ return SUCCESS;}RC SM_Manager::Print (const char *relName) { /* Check if we are not connected to a database */ if (!bOpen) { return SM_DBCLOSED; } /* Step 1 */ RC rc; /* Determine the structure of the relation */ DataAttrInfo *info; int attrCount; rc = GetDataAttrInfo (relName, info, attrCount); if (rc != SUCCESS) { return rc; } /* Step 2 */ /* Scan the relation and print its tuples */ RM_FileHandle fileHandle; /* Get a handle to the file first */ rc = rmm.OpenFile (relName, fileHandle); if (rc != SUCCESS) { free (info); return rc; } RM_FileScan fileScan; /* Open a file scan using the file handle */ rc = fileScan.OpenScan (fileHandle, TYPE_STRING, MAXNAME, 0, /* <-- Doesn't matter what these values are because the scan is based on NO_OP */ NO_OP, NULL, NO_HINT); if (rc != SUCCESS) { free (info); return rc; } /* Print the tuple header */ PrintTupleHeader (info, attrCount); RM_Record rec; /* Get each record from the file */ while (fileScan.GetNextRec(rec) == SUCCESS) { char *pData; /* Get the record's contents (data) */ rc = rec.GetData (pData); /* Clean up before returning from an error */ if (rc != SUCCESS) { free (info); fileScan.CloseScan (); return rc; } /* Create a tuple from the record */ SM_Tuple T (info, attrCount, pData); /* Print the tuple to the standard output */ T.PrintData (); } /* Free up relation structure information */ free (info); /* Close the scan */ rc = fileScan.CloseScan (); if (rc != SUCCESS) { return rc; } /* Print info about relation */ int nRecords, nPages; rc = fileHandle.GetNumRecords(nRecords); if (rc != SUCCESS) { return rc; } rc = fileHandle.GetNumPages(nPages); if (rc != SUCCESS) { return rc; } fprintf (stdout, "%d tuples occupying %d pages\n", nRecords, nPages); /* Close the file handle */ rc = rmm.CloseFile (fileHandle); if (rc != SUCCESS) { return rc; } /* Successfully printed relation */ return SUCCESS;}RC SM_Manager::GetDataAttrInfo (const char *relName, DataAttrInfo *&info, int &attrCount) const { /* Pad relName because we are going to use it in a file scan. */ char rName[MAXNAME+1]; memset (rName, 0, MAXNAME+1); strcpy (rName, relName); /* Step 1 */ /* Use the relation catalog to verify that the relation exists */ RM_FileScan fileScan; RM_Record rec; RC rc; /* Open a scan on relcat */ rc = fileScan.OpenScan (fileHandle_relcat, /* dataAttrInfo_relcat[0] corresponds to attribute relName of relation relcat */ dataAttrInfo_relcat[0].attrType, dataAttrInfo_relcat[0].attrLength, dataAttrInfo_relcat[0].offset, EQ_OP, rName, NO_HINT); /* If there are no records corresponding to this relation, flag an * error */ if (fileScan.GetNextRec(rec) != SUCCESS) { fileScan.CloseScan (); return SM_RELNOTFOUND; } /* Close the scan */ rc = fileScan.CloseScan (); if (rc != SUCCESS) { return rc; } /* Step 2 */ /* We now know that the relation exists. Use the attribute catalog to determine the structure of the relation. */ /* Open a scan on attrcat */ rc = fileScan.OpenScan (fileHandle_attrcat, /* dataAttrInfo_attrcat[0] corresponds to attribute relName of relation attrcat */ dataAttrInfo_attrcat[0].attrType, dataAttrInfo_attrcat[0].attrLength, dataAttrInfo_attrcat[0].offset, EQ_OP, rName, NO_HINT); /* initialise attrCount and info */ attrCount = 0; info = NULL; /* get the structure of each attribute */ while (fileScan.GetNextRec(rec) == SUCCESS) { char *pData; /* Get the content's of the record */ rec.GetData (pData); /* Build a tuple from the retrieved record */ SM_Tuple T (dataAttrInfo_attrcat, 5, pData); /* Retrieve the name,type,offset,length of each attribute */ DataAttrInfo d; strcpy (d.relName, rName); T.GetValue(1, d.attrName); T.GetValue(2, &d.offset); T.GetValue(3, &d.attrType); T.GetValue(4, &d.attrLength); /* Increase size of structure by 1 */ attrCount++; info = (DataAttrInfo *) realloc (info, attrCount*sizeof(DataAttrInfo)); /* Copy structure information into info */ info[attrCount-1] = d; } /* Close the scan */ rc = fileScan.CloseScan (); if (rc != SUCCESS) { return rc; } return SUCCESS;}void SM_Manager::PrintTupleHeader (const DataAttrInfo *info, int attrCount) const { /* Print out the attribute names */ for (int i = 0; i < attrCount; i++) { if (info[i].attrType == TYPE_STRING) { printf ("%-*s|", info[i].attrLength, info[i].attrName); } else { printf ("%*s|", 10, info[i].attrName); } } printf ("\n"); for (int i = 0; i < attrCount; i++) { int d; switch (info[i].attrType) { case TYPE_INT: case TYPE_FLOAT: d = 10; break; case TYPE_STRING: d = info[i].attrLength; break; } for (int j = 0; j < d; j++) { putchar ('-'); } putchar ('+'); } printf ("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -