|
|
|
|
|
|
I.e.:
|
Open( )
{
Open target relation R;
Allocate 1 block buffer space at b;
b = read first block of R;
t = points to first tuple in block b;
}
|
getNext( )
{
/* ==============================================================
Make sure t points to a valide tuple before proceeding
============================================================== */
if ( tuple t has passed the last tuple in block b )
{
/* -------------------------------------------------
Re-position t to be the first tuple of next block
------------------------------------------------- */
Read the next block into b;
if ( there is no next block )
{
return NotFound;
}
else
{
t = first tuple in block b;
}
}
/* ===========================================
Here: t points to a valid next tuple
=========================================== */
curr_t = t; // Save the return value
increment t to the next tuple in block b;
return curr_t;
}
|
Close( )
{
free buffer;
close file;
}
|
|
The implementation of BagUnion will illustrate the pipelining effect :
|
ScanTable R, S = input relations to BagUnion
Open( )
{
R.Open(); // Call the Open() method in ScanTable !!!
CurrRel = R;
}
|
getNext()
{
if ( currRel == R )
{
t = R.getNext(); // Call ScanTable to get next tuple
if ( t ≠ NotFound )
{
/* ------------------------------
We read a valid tuple from R
------------------------------ */
return t;
}
else
{
/* ===========================
R is done, we read S next
=========================== */
S.Open(); // Call ScanTable's Open()
currRel = S; // Make this if-statement stop executing
}
}
/* =============================================
We will only reach here if R is exhausted...
============================================= */
return S.getNext();
}
|
Close( )
{
R.Close( );
S.Close( );
}
|
|
|
|
The implementation of Sort-scan will illustrate that iterator is not always the most suitable approach to implement the operator
Open( )
{
Open target relation R;
Read all tuples of R into memory;
Sort the tuples;
b = points to first block of R;
t = points to first tuple in block b;
}
|
getNext( )
{
/* ==============================================================
Make sure t points to a valide tuple before proceeding
============================================================== */
if ( tuple t has passed the last tuple in block b )
{
/* -------------------------------------------------
Re-position t to be the first tuple of next block
------------------------------------------------- */
Make b point to the next block of R;
if ( there is no next block )
{
return NotFound;
}
else
{
t = first tuple in block b;
}
}
/* ===========================================
Here: t points to a valid next tuple
=========================================== */
curr_t = t; // Save the return value
increment t to the next tuple in block b;
return curr_t;
}
|
Close( )
{
free buffers;
close file;
}
|
|
|
class ScanTable
{
public:
FILE *fp;
int fd;
char TableName[33]; // Name of the relation
DataDescription DataDes[10]; /* Holds data descriptions
for upto 10 fields */
int n_fields; /* Actual # fields */
int record_size;
char buf[1000]; // Buffer to store tuples
int Open(char *relname);
int GetNext();
void Close();
int getAttrType( char *attrName ); // Get data type of attr attrName
int getAttrSize( char *attrName ); // Get size of attr attrName
void *getAttrPtr( char *attrName ); // Get pointer to attrName in buf[1000]
void PrintTuple();
void PrintRelationInfo();
};
|
int ScanTable::Open(char *relname)
{
/* ------------------------------------------------
Open the catalog to file the relation definition
------------------------------------------------ */
if ( (fp = fopen("catalog", "r")) == NULL )
{
cout << "Error: cannot open database catalog `./catalog'" << endl;
return 0;
}
n_fields = 0;
record_size = 0;
/* ==================================================
Read attribute information on relation "relname"
================================================== */
while ( fscanf(fp, "%s %s %c %d %d",
DataDes[n_fields].relname, DataDes[n_fields].fieldname,
&DataDes[n_fields].fieldtype, &DataDes[n_fields].startpos,
&DataDes[n_fields].fieldsize) > 0 )
{
if ( strcmp( DataDes[n_fields].relname, relname ) == 0 )
{
/* =========================================
This field belongs to the relation !
Adjust the computation of the record size
========================================= */
if ( DataDes[n_fields].startpos
+ DataDes[n_fields].fieldsize > record_size )
{
record_size = DataDes[n_fields].startpos
+ DataDes[n_fields].fieldsize;
}
n_fields++; // Accept this field
}
}
fclose(fp); // Close the catalog
/* -----------------------------------------
Check if the relation "relname" was found
----------------------------------------- */
if ( n_fields > 0 )
{
/* =======================================
Found: open the data file
======================================= */
if ( (fd = open(relname, O_RDONLY)) == -1 )
{
cout << "Error: canot open relation file " << relname << endl;
return 0;
}
strcpy( TableName, relname);
return 1; // Return success code
}
else
{
return 0; // Return error code
}
}
|
Note:
|
int ScanTable::GetNext()
{
int n;
n = read(fd, buf, record_size+1);
/* ----------------------------------------
Return a success or error code
---------------------------------------- */
if ( n == record_size+1 )
{
return 1;
}
else
{
return 0;
}
}
|
void ScanTable::Close()
{
close(fd); // Close relation file
}
|
ScanTable *f = new ScanTable();
if ( f->Open( "relationName" ) == 0 )
{
cout << "Relation not found !" << endl;
exit(1);
}
while ( f->GetNext() != 0 )
{
/* ------------------
Print it...
------------------ */
f->PrintTuple(); // I added a print tuple method in the class....
}
f->Close();
|
How to run the program:
|