/*dbms:								*/
/*	This is a database management system deal with rela-    */
/*tional database.  It provides the following operations:	*/
/* 	-create relation					*/
/*	-delete relation					*/
/*	-add tuples to a relation				*/
/*	-delete tuples from a relation				*/
/*	-select tuples according to given condition		*/
/*	-project attributes					*/
/*	-join two relations according to a given conditon	*/
/*	-display relation					*/
/*--------------------------------------------------------------*/

#include 
#include 
#include 
#include 
#define TRUE 1
#define FALSE 0
#define  MAX_ATTRI_NUM   20
#define  MAX_TUPLE_NUM 1000
#define SIZE 300
FILE     *fp, *fp_out;
char     relation_name[20], output_file_name[20];
int      attri_num, attri_num_2;
char     attri_name[40], attri_type[10];
typedef struct {
      char att_name[40];
      char att_type[10];
    } attri_headers;
attri_headers attri_head[MAX_ATTRI_NUM];
attri_headers attri_head_2[MAX_ATTRI_NUM];
char buf[SIZE], buff[SIZE];    
char p[21][40], s[21][40];

/*-----------------------main()------------------------------------*/

main()
{
 int i,option;

 for(;;) {
 main_menu();
 gets(buf);
 sscanf(buf,"%d",&option);
 switch(option){
 case 1: 
	create();
	break;
 case 2:  
	delete_rel();
        break;
 case 3:  
	add_tup();
        break;
 case 4:
	delete_tup();
        break;
 case 5: 
	select();
        break;
 case 6: 
	project();
        break;
 case 7: 
	join();
        break;
 case 8: 
	display();
        break;
 case 9:
	return;
 default: 
        printf("\nYou must select option among 1-9\n");
	break;
 }
}
}

/* ------------------ main_menu() --------------------------------------*/
/* The purpose of this function is to display the menu and		*/
/*  accept an option  for the relational database management system	*/
/*----------------------------------------------------------------------*/

int main_menu ()
{
system("clear");
printf("       Ingrass Relational Database Management System\n");
printf("       =============================================\n\n");
printf("                 1 Create relation\n");
printf("                 2 Delete relation\n");
printf("                 3 Add tuple\n");
printf("                 4 Delete tuple\n");
printf("                 5 Select\n");
printf("                 6 Project\n");
printf("                 7 Join\n");
printf("                 8 Display\n");
printf("                 9 Quit\n\n");
printf("                 Option ? (1-9) ");
return TRUE;
}          

/* ---------------------------- rest() ---------------------------------*/
/* This function is to allow the user to check the results before	*/
/*   show the next menu on window					*/
/*----------------------------------------------------------------------*/

int rest()
{
printf("Press return key to continue. ");
gets(buf);
}


/* ----------------------------- create() ------------------------------*/
/* The purpose of this function is to create a relation with its	*/
/* attribute name and its attribute type for all the attributes.	*/
/*----------------------------------------------------------------------*/

int create ()
{
 int  i;				/*counter for number of attribute*/

 		
 printf("The relation's name: ");	/*get relation name*/
 gets(relation_name);

 if((fp = fopen(relation_name, "r")) != NULL)
   { 
     printf("%s already existed. \n", relation_name);
     fclose(fp);
     rest();
     return TRUE;
    }
 
 fp = fopen (relation_name, "a");	/*create a relation file	*/
 printf("Number of attributes: ");	/*get number of attritubes to 	*/
 gets(buf);				/*be built in a relation	*/
			
 sscanf(buf,"%d", &attri_num);		/*convert the number from buf	*/
					/*to the variable attri_num	*/

 i = 1;

 while (i <= attri_num )
  {
    printf("Enter the %dth attribute's name: ", i);
    gets(attri_name);			/*get attribute name		*/
    fprintf(fp, "%s ", attri_name);  	/*output to a relation file	*/
					/*use space as a delimiter	*/
					/*between name and type		*/
    printf("Please enter the attribute type (text or int): ");
    gets(attri_type);			/*get attribute type		*/
    fprintf(fp, "%s ", attri_type);	/*output to the relation file	*/
					/*use space as a delimeter 	*/
					/*name and type			*/
    i++;				/*count number of attritubes	*/
   }

 printf("\n\n%s is created!\n", relation_name);
 
/* the format of header record is: "name type name type .. name type \n"*/
/* NOTE: There is a space before \n, so in join header1, header2, NO    */
/*       space	needed between two headers. 				*/

 rest();
 fprintf(fp, "\n");
 fclose(fp);

 return  TRUE;

}



/* ------------------------------ add_tup() --------------------------  */
/*add one or more tuple to a relation					*/
/*----------------------------------------------------------------------*/

int add_tup ()
{ 
 int   i;		
 char ch, ch1[2], ch2[2], tuple[100];
 char input_file_name[20];
 FILE *fp_in;
 int no_tuples=1;
 
 
 /*get header and the number of the relation which wants to add tuples	*/

 if( attri_header(&attri_num, 1) == FALSE) return FALSE;

 fp = fopen(relation_name, "a");

 /*get tuple from keyoard or file					*/

 printf("Enter a tuple from a keyboard or from a file ( k or f )? ");
 gets(buf);
 
 /*if a tuple is entered from keyboard					*/

 if((buf[0] == 'k') || (buf[0] == 'K'))
  { 
    
    buff[0]='y';			/*flag to continue adding tuples*/
    while(no_tuples <= MAX_TUPLE_NUM && buff[0]=='y')
     { 
       for(i=1; i<= attri_num; i++)	/*show information of header    */
        { 
         if(i== 1)
           printf("The 1st attribute \"%s\" with type \"%s\": ", 
                        attri_head[1].att_name, attri_head[1].att_type);
         else if(i== 2)
           printf("The 2nd attribute \"%s\" with type \"%s\": ",
                        attri_head[2].att_name, attri_head[2].att_type); 
         else if(i== 3)
           printf("The 3rd attribute \"%s\" with type \"%s\": ",
                        attri_head[3].att_name, attri_head[3].att_type);
         else
           printf("The %dth attribute \"%s\" with type \"%s\": ",
                    i, attri_head[i].att_name, attri_head[i].att_type);
      	
         gets(buf);			/*get an attribute data		*/
         
         if(i< attri_num)
          fprintf(fp, "%s\t", buf);	/*if not the last attritube, put*/
					/*tab at end of it		*/ 
         else 
          fprintf(fp, "%s\n", buf);	/*if the last attribute, put	*/
					/*new line at end of it		*/
          } /* for loop */

       printf("Tuple is added. \n");
         printf("You have added %d tuples in the %s relation.\n ",
                   no_tuples++, relation_name);   
       printf("Would you add a new tuple ( y or n): ");/*add more tuples?*/
	gets(buff);
      }/* while */
     fclose(fp);

     /* the format of tuple is : field\tfield\tfield\tfield\n */
     /* Note: last field followed by \n only, no \t */
   }

 /*if tuples are added from a data file	: read all tuples at once       */

  else if((buf[0] == 'f') || (buf[0] == 'F'))
   {

     fp_in = NULL;
     while (fp_in == NULL) {
     	printf("The input file name: ");
     	gets(input_file_name);
 
        fp_in = fopen(input_file_name, "r");	/*open the data file	*/
	if (fp_in == NULL)
        	printf("%s does not exist. \n", input_file_name);
     }
	
 /*check if the data file contains a header				*/

     printf("Does the data have header with it (y or n): ");

     gets(buff);
     if ((buff[0] == 'y') || (buf[0] == 'Y'))
	 fgets(buf,SIZE,fp_in); /* skip the data definition header 	*/
     
     while(fgets(buf,SIZE,fp_in)!=NULL)
        	fprintf(fp, "%s", buf);
     fclose(fp_in);
     fclose(fp);
 printf("Relation %s is added to relation %s\n",input_file_name,relation_name); 
    }
 rest();
 return TRUE;
}


/* ------------------- attri_header() ---------------------------------	 */
/* get header from the relation file					*/
/*----------------------------------------------------------------------*/


int attri_header (n,pos)
int *n;				/*number of attritubes in a relation	*/
int pos;			/*nth  relation: pos = 1, relation 1	*/
				/*		 pos = 2, relation 2	*/
{
 char  ch; 
 int   i, k, nt;		/*k: control char to read in each 	*/
				/*attribute name or type from the header*/	
				/*nt: nth element of the header		*/

 if(pos==1) printf("The relation's name? ");
  else printf("The 2nd relation's name? ");
 gets(relation_name);
 if((fp = fopen(relation_name, "r")) == NULL)
  { 
   printf("\n %s does not exist. \n", relation_name);
   rest();
   return FALSE;
   }
 i = k = nt = 0;		/*nt: if nt = 0, attribute name		*/
				/*	 nt = 1, attribute type		*/
				/*keep track of attribute to decide if	*/
				/*it is a name or type when read from 	*/
				/*the relation				*/

 while((ch = fgetc(fp)) != '\n')
  {
   while(ch != ' ')
    { 				/*store header information into temp	*/
	attri_name[k] = ch;	/*array attri_name[k]			*/
 	ch = fgetc(fp);
      	k++;
     }
     attri_name[k] = '\0';

 /*get attribute name and put in structure attri_head[i].att_name	*/				
       if(nt==0) {	
	i++;				/*count number of attributes	*/
	if(pos==1)strcpy(attri_head[i].att_name, attri_name);
	else strcpy(attri_head_2[i].att_name, attri_name);
	nt=1; 
	}

 /*get attribute type and put in structure attri_head[i].att_type	*/			
	else {
         if(pos==1) strcpy(attri_head[i].att_type, attri_name);
         else strcpy(attri_head_2[i].att_type, attri_name);
	 nt=0; 
	 }
      k = 0;
     }
	fclose(fp);
	*n = i;				/*return number of attributes	*/
	return TRUE;
}




/* ----------------------------- delete_rel() ------------------------- */
/*Delete or remove a relation from the system				*/
/*----------------------------------------------------------------------*/

int delete_rel ()
{
  char  buf[80];


  printf("The relation name : ");
  gets(relation_name);

  if((fp = fopen(relation_name, "r")) == NULL)
   {
     printf("The relation %s does not exist.\n", relation_name);
	rest();
	return TRUE;
    }
 
   printf("Do you want to delete relation %s (y or n)? ", relation_name);
   gets(buf);
   
   if((buf[0] == 'y') || (buf[0] == 'Y'))
    {
	remove (relation_name);		/*remove the specified relation*/
      	printf("The relation %s is deleted!\n", relation_name);
     }
   rest(); 
   return TRUE;
}


/* --------------------------- delete() ------------------------------- */
/*delete one or more tuples from the relation based on the setup	*/
/*criteria.								*/
/*--------------------------------------------------------------------- */

int delete_tup ()
{
 static char relation[6][3]={"","=",">","<",">=","<="};
 int  count[MAX_ATTRI_NUM], i,  num;  /*num: nth attributes(one or more)*/
 int choice;				 /*choice of condition operator */
 time_t  Start, End;		/*for count time to process delete tuples*/
 int ti;
 
 /*read attributes of header into memory structure			*/
 if(attri_header(&attri_num,1) == FALSE) return FALSE;

 fp = fopen(relation_name, "r");
 
 /*get output file to store result after tuples are deleted and return	*/
 /*attribute number							*/

 printf("\nPlease enter the file name for storing the left tuples: ");
 while(gets(output_file_name)!=NULL) {
 if ((fp_out = fopen(output_file_name, "r")) != NULL)
    printf("Output file %s already exists. ", output_file_name);
 else break;
 }

 fp_out = fopen(output_file_name, "a");
  fgets(buf,SIZE,fp);			/*read header from the relation */
  fprintf(fp_out, "%s",buf);		/*copy to the result file	*/

  printf("The %s has %d following attribute(s):\n", relation_name, attri_num);

 /*display header information for user to refer to			*/

 for(i=1; i<=attri_num; i++)
  printf("Attribute %d: %s \t ( %s )\n", i, attri_head[i].att_name, 
                                    attri_head[i].att_type);

 num = 0;
 i = 0;

	/*get attribute number to specify condition			*/

	num=0;
	while(num<1 || num>attri_num) {
	printf("Enter the attribute number: ");
	gets(buf);
	sscanf(buf,"%d", &num);
  	}

 /*display information of the attribute to be deleted			*/

 printf("\n%d -- %s ( %s )\n", num, attri_head[num].att_name, 
                                  attri_head[num].att_type);

 /*decide condition operator =, >, <, >=, <=				*/

 printf("Enter comparison codition number:\n");
 choice = 0;
 while(choice < 1 || choice > 5) {
 printf("1 Equal (%s)\n",relation[1]);
 printf("2 Greater than (%s)\n",relation[2]);
 printf("3 Less than (%s)\n",relation[3]);
 printf("4 Greater or equal (%s)\n",relation[4]);
 printf("5 Less than or equal (%s)\n",relation[5]);
 gets(buf);
 sscanf(buf,"%d", &choice);
 }

 /*display the selected attribute name and selected condition operator	*/
 
 printf("%s %s ",attri_head[num].att_name, relation[choice]);
 gets(buf);					/*get condition		*/
 if(attri_head[num].att_type[0] == 't'){
	ti=0; 					/*text type of the selected
						 attribute		 */
  }
 else if(attri_head[num].att_type[0] == 'i') {
	ti=1; 					/* integer type of the selected
						   sttribute		*/
 }
 
 /*count process time for delete a tuple				*/
  Start = time(NULL); 
 
  del_tuple(num,ti,choice); 

  End = time(NULL);

 printf("\nDeleteing tuple is finished and the deleteed tuples ");
 printf("are stored into ");
 printf("\n%s. \n", output_file_name);

 printf("\nThe Delete time is %ld seconds.\n", End - Start);


       fclose (fp);
       fclose (fp_out); 
 rest();
 return TRUE;
}

/* -------------------------------- del_tuple() ------------------------*/
/*function called by del_tup() to delete tuple				*/
/*----------------------------------------------------------------------*/

int del_tuple (n,ti,relation)
int n;				/*nth attribute				*/
int ti;				/*attritube type			*/
int relation;			/*condition operator			*/

{
 int i;
 int cond_int;			/*condition (if the attribute type=int) */
 char cond_str[40]; 		/*	(if the attribute type = text)  */
  
 if(ti==0)
     strcpy(cond_str,buf);
 else 
     sscanf(buf,"%d", &cond_int);/* convert string type of condition to 
					integer				*/

while(fgets(buf,SIZE,fp)!=NULL)
{
 get_fields(1); 		/* break buf into fields s[1],s[2],.... */
 if(ti==0) {			/* attribute type = text		*/
   switch(relation) {		/* if condition does meet, copy the tuple
				       to the result file 		*/
   case 1:
	if(strcmp(s[n],cond_str)==0) ;
		else fprintf(fp_out,"%s",buf);
	break;
   case 2:
	if(strcmp(s[n],cond_str)>0) ;
		else fprintf(fp_out,"%s",buf);
	break;
   case 3:
	if(strcmp(s[n],cond_str)<0) ;
		else fprintf(fp_out,"%s",buf);
	break;
   case 4:
	if(strcmp(s[n],cond_str)>=0) ;
		else fprintf(fp_out,"%s",buf);
	break;
   case 5:
	if(strcmp(s[n],cond_str)<=0) ;
		else fprintf(fp_out,"%s",buf);
	break;
	}
 }
 else {				/*attribute type = integer		*/
  switch(relation) {
  case 1:
	if(atoi(s[n])==cond_int)  ;
		else fprintf(fp_out,"%s",buf);
	break;
  case 2:
	if(atoi(s[n])>cond_int) ;
		else fprintf(fp_out,"%s",buf);
	break;
  case 3:
	if(atoi(s[n])=cond_int) ;
		else fprintf(fp_out,"%s",buf);
	break;
  case 5:
	if(atoi(s[n])<=cond_int) ;
		else fprintf(fp_out,"%s",buf);
	break;
  }
 }
 }
}
/* --------------------------------- display() ------------------------ */
/* The purpose of this function is to display the data definition and	*/
/* its contents of a relation						*/
/*----------------------------------------------------------------------*/

int display()
{ 
 char  i;
 int   head_flag;
 
 if( attri_header(&attri_num, 1) == FALSE) return FALSE;
 
 if((fp = fopen(relation_name, "r")) == NULL )
  { printf("%s does not exist. \n", relation_name);
   return FALSE;
   }

 printf("\n Relation:  %s\n", relation_name);
 fgets(buf,SIZE,fp);			/*skip header			*/
 printf("Attribute numbers=%d\n",attri_num);
 for(i=1;i<=attri_num;i++)		/*display attribute header	*/
    printf("%s\t",attri_head[i].att_name);
 printf("\n");
 printf("---------------------------------\n");
 while(fgets(buf,SIZE, fp)!=NULL)
 	printf("%s",buf);		/*display tuples		*/
    fclose(fp);
 rest();
 return TRUE;

}
 
/* --------------------------------- join() --------------------------- */
/*Join two relations. 							*/
/*Uncondition: cartesian product operation				*/
/*Condition: equaljoin- join two relation according to their common 	*/
/*		common attributes which have the same domain		*/
/*----------------------------------------------------------------------*/

int join ()
{
 char  relation_name_1[20], relation_name_2[20];/*relation 1 & 2 for join*/
 FILE  *fp_1, *fp_2;			/*file pointer for relation 1& 2*/
 int   i, attr_1, attr_2;		/*the attribute to be joined 	*/
					/*from two relations		*/
 time_t Start, End;			/* count process time		*/
 int f2_pos;				
 char *newl;

 printf("The output relation file name: ");/* get result file name	*/
  gets( output_file_name);
   if((fp_out = fopen(output_file_name, "r")) != NULL)
       { 
	printf("%s already existed. \n", output_file_name);
	rest();
	return FALSE;
       } 
 
 fp_out = fopen(output_file_name, "w");	
 printf("Unconditional join (y or n)? ");
 gets(buf);

 /*unconditional join							*/

 if((buf[0] == 'y') || (buf[0] == 'Y'))
  
{	/*get 1st relation						*/
 	printf("The 1st relation name: ");
 	gets( relation_name_1);
 	if((fp_1 = fopen(relation_name_1, "r")) == NULL)
  	{
   		printf("The relation %s does not exist. \n", relation_name_1);
   		rest();
		return FALSE;
   	}

	 printf("The 2nd relation name: ");
	/*get 2nd relation						*/
 	gets( relation_name_2);
 	if((fp_2 = fopen(relation_name_2, "r")) == NULL)
  	{
   		printf("The relation %s does not exist. \n", relation_name_2);
		rest();
		return FALSE;
   	}
 	fgets(buf,SIZE,fp_1);		/*get 1st header		*/
 	newl = strchr(buf,'\n');	/*when combining header from two
						relatons, change the newline
						at the end of the 1st header
						to null			*/
 
 	*newl = '\0';
 	fgets(buff,SIZE,fp_2);		/*get 2nd header		*/
 	fprintf(fp_out,"%s%s",buf,buff); /* header end with space \n    */
 				/* so, we do NOT need space between %s%s*/


	f2_pos = ftell(fp_2);   /*remember the current position after 	*/
				/*reading header			*/

	/*count process time						*/

     	Start = time(NULL);    

	/*get tuple in 1st relation					*/

	while(fgets(buf,SIZE,fp_1)!=NULL) {/*get tuple from 1st relation*/
		newl = strchr(buf,'\n');/*search \n			*/
		*newl = '\0';	 	/*	replace with null	*/
		fseek(fp_2,f2_pos,0);	/*start from begining		*/	
					
					/*get tuple from 2nd relation   */	
		while(fgets(buff,SIZE,fp_2)!=NULL)
			fprintf(fp_out,"%s\t%s",buf,buff);/*put them together*/
	}
      	End = time(NULL);
    }
 /*conditional join						 	*/
   else
    {
	/*get the numbers of attribute from relation 1 & 2		*/

      	attri_header(&attri_num,1);
      	strcpy(relation_name_1,relation_name);
      	attri_header(&attri_num_2,2); 
      	strcpy(relation_name_2,relation_name);
      	printf("The 1st relation file %s's attributes:\n", relation_name_1);

	/*display attribute information of the 1st relation		*/

      	for(i=1; i<=attri_num; i++)
       	printf("Attribute %d : %s ( %s )\n", i, attri_head[i].att_name, 
                                        attri_head[i].att_type);
      	printf("The 2nd relation file %s's attributes:\n", relation_name_2);

	/*display attribute information of the 2nd relation		*/

      	for(i=1; i<=attri_num_2; i++)
        printf("Attribute %d : %s ( %s )\n", i, attri_head_2[i].att_name,
                                         attri_head_2[i].att_type);

 /*open the 2 relations							*/

 	if((fp_1 = fopen(relation_name_1, "r")) == NULL)
  	{
   		printf("The relation %s does not exist. \n", relation_name_1);
   		rest();
		return FALSE;
   	}

 	if((fp_2 = fopen(relation_name_2, "r")) == NULL)
  	{
   		printf("The relation %s does not exist. \n", relation_name_2);
		rest();
		return FALSE;
 	}
	
	/*get header from 2 relations and put together			*/

 	fgets(buf,SIZE,fp_1);
 	newl = strchr(buf,'\n');
 	*newl = '\0';
 	fgets(buff,SIZE,fp_2);
 	fprintf(fp_out,"%s%s",buf,buff);
 	f2_pos = ftell(fp_2);

    /*get the attribute to be the key to be joined with from both relationa*/

     	printf("The 1st relation's attribute number: ");
	gets(buf);
     	sscanf(buf,"%d", &attr_1);
     	printf("The 2nd relation's attribute number: ");
	gets(buf);
     	sscanf(buf,"%d", &attr_2);
    
	/*count process time						*/

     	Start = time(NULL);

	while(fgets(buf,SIZE,fp_1)!=NULL) {
		newl = strchr(buf,'\n');
		*newl = '\0';
		fseek(fp_2,f2_pos,0);
		while(fgets(buff,SIZE,fp_2)!=NULL)
		{
			get_fields(1); /* break buf into fields s[1],s[2],.. */
			get_fields(2); /* break buff into fields p[1],p[2],..*/

			/*if the data of the attribute from both relationa   */
			/*are equal, it is saves in the result file          */
			if(strcmp(s[attr_1],p[attr_2])==0)
				fprintf(fp_out,"%s\t%s",buf,buff);
		}
	}

	End = time(NULL);
   }
   fclose(fp_1);
   fclose(fp_2);
   fclose(fp_out);
   printf("The join time is %ld seconds.\n", End-Start);
   printf("Join is finished.\n");
   rest();
   return TRUE;
}      
 

               

/* ----------------------------------- project() -----------------------*/
/*project the specified attributes from a relation and save the result 	*/
/*in a result file							*/
/*----------------------------------------------------------------------*/

int project ()
{
  int   num,  i, j;		/*num: nth attributes (one or more)	*/
  int   pitem[20];		/*array to store the attributes to be	*/
				/*projected in an array			*/
  time_t Start, End;

  
  if ( attri_header (&attri_num,1) == FALSE) return FALSE;
  fp = fopen(relation_name, "r");

  printf("The filename for storing project : ");
    gets(output_file_name);		/*get result file name		*/

  if ((fp_out = fopen(output_file_name, "r")) != NULL)
    { 
      printf("%s already existed. \n", output_file_name);
      printf("The filename for storing project : ");
      gets(output_file_name);
     }

  fp_out = fopen(output_file_name, "w");
  
   printf("The %s has %d following attributes:\n",relation_name,attri_num); 

  for(i=1; i<=attri_num; i++)		/*display attribute information  */
    printf("Attribute %d : %s (%s)\n", i, attri_head[i].att_name,
					attri_head[i].att_type);

  i = 0;
  buf[0] = 'y';
  while ( buf[0]== 'y' && i< attri_num)
  {
   printf("Attribute number to be projected: ");
   gets(buf);				/*get nth attributes to be projected*/
   sscanf(buf,"%d", &num);
   if((num < 1) || (num > attri_num))
    { 
      printf("Attribute number out of range.\n");/*if nth attr > attr number*/
      continue;
     }				
				/*display information of the attributes */
   fprintf(fp_out, "%s %s ",attri_head[num].att_name,attri_head[num].att_type);
   pitem[i] = num;		/*store attribute index to be projected*/
				/*in order in the pitem array		*/
   i++;
      buf[0] = ' ';			/*project more			*/
      while(buf[0]!= 'y' && buf[0] != 'n') {
      if(i==attri_num) break;
      printf("More attributes for projecting? (y or n): ");
      gets(buf); 
      }
  }
  fprintf(fp_out, "\n");

  fgets(buf,SIZE,fp);

  Start = time(NULL);
  
  while(fgets(buf,SIZE,fp)!=NULL) {
	get_fields(1); 	/* break buf into fields s[1],s[2],... */
	for(j=0;j","<",">=","<="};/*condition operator*/
 int  count[MAX_ATTRI_NUM], i,  num;	/*num: nth attribute		*/
 int choice;				/*choice of condition operator	*/
 time_t  Start, End;
 int ti; 				/*attribute type: 0=text,1=int	*/

 if(attri_header(&attri_num,1) == FALSE) return FALSE;

 fp = fopen(relation_name, "r");

 /*get result file							*/
 printf("The file name for storing the left tuples: ");
 while(gets(output_file_name)!=NULL) {
 if ((fp_out = fopen(output_file_name, "r")) != NULL)
    printf("Output file %s already exists. ", output_file_name);
 else break;
 }

 fp_out = fopen(output_file_name, "a");
  fgets(buf,SIZE,fp);
  fprintf(fp_out, "%s",buf);

  printf("The %s has %d following attribute(s):\n", relation_name, attri_num);

 /*display header information						*/

 for(i=1; i<=attri_num; i++)
  printf("Attribute %d: %s \t ( %s )\n", i, attri_head[i].att_name, 
                                    attri_head[i].att_type);

 num = 0;
 i = 0;
	/*get the number of attribute to be selected to setup condition	*/
	num=0;
	while(num<1 || num>attri_num) {
	printf("Enter the attribute number: ");
	gets(buf);
	sscanf(buf,"%d", &num);
  	}

 /*display information of the attribute					*/
 printf("Attribute %d :  %s ( %s )\n", num, attri_head[num].att_name, 
                                  attri_head[num].att_type);

 printf("Enter comparison codition number:\n");
 choice = 0;
 while(choice < 1 || choice > 5) {		/*decide conditon operator*/
 printf("1 Equal (%s)\n",relation[1]);
 printf("2 Greater than (%s)\n",relation[2]);
 printf("3 Less than (%s)\n",relation[3]);
 printf("4 Greater or equal (%s)\n",relation[4]);
 printf("5 Less than or equal (%s)\n",relation[5]);
 gets(buf);
 sscanf(buf,"%d", &choice);
 }

 printf("%s %s ",attri_head[num].att_name, relation[choice]);
 gets(buf);				/*get condition		 */
 if(attri_head[num].att_type[0] == 't'){
	ti=0; 					/* text type	 */
  }
 else if(attri_head[num].att_type[0] == 'i') {
	ti=1; 					/* integer type	 */
  }
  
 /*count process time						 */
  Start = time(NULL); 
 
  sel_tuple(num,ti,choice); 

  End = time(NULL);

 printf("\nSelecting tuple is finished and the selected tuples ");
 printf("are stored into ");
 printf("\n%s. \n", output_file_name);

 printf("\nThe Select time is %ld seconds.\n", End - Start);


       fclose (fp);
       fclose (fp_out);
 
 rest();
 return TRUE;
}

/* -------------------------------- sel_tuple() ----------------------- */
/*It is called by sel_tup() to perform selecting tuples			*/
/*----------------------------------------------------------------------*/

int sel_tuple (n,ti,relation)
int n;					/*nth attribute			*/
int ti;					/*attribute type		*/
int relation;				/*condition operator		*/

{
 int i;
 int cond_int;				/*condition with int type in the
						attribute		*/
 char cond_str[40];			/*condition with text type in the
						attribute		*/		 

 if(ti==0)				/*text type			*/
     strcpy(cond_str,buf);
 else 	
     sscanf(buf,"%d", &cond_int);	/*int type			*/

while(fgets(buf,SIZE,fp)!=NULL)
{
 get_fields(1); 		/* break buf into fields s[1], s[2], .. */
 if(ti==0) {			/*for text type of attribute to be set 	*/
				/*with condtion				*/
				/*if the condition meets, the tuple is	*/
				/*saved in the result file		*/
   switch(relation) {
   case 1:
	if(strcmp(s[n],cond_str)==0) 
		fprintf(fp_out,"%s",buf);
	break;
   case 2:
	if(strcmp(s[n],cond_str)>0) 
		fprintf(fp_out,"%s",buf);
	break;
   case 3:
	if(strcmp(s[n],cond_str)<0) 
		fprintf(fp_out,"%s",buf);
	break;
   case 4:
	if(strcmp(s[n],cond_str)>=0) 
		fprintf(fp_out,"%s",buf);
	break;
   case 5:
	if(strcmp(s[n],cond_str)<=0) 
		fprintf(fp_out,"%s",buf);
	break;
	}
 }
 else {
  switch(relation) {		/*for int type	*/
  case 1:
	if(atoi(s[n])==cond_int) 
		fprintf(fp_out,"%s",buf);
	break;
  case 2:
	if(atoi(s[n])>cond_int) 
		fprintf(fp_out,"%s",buf);
	break;
  case 3:
	if(atoi(s[n])=cond_int) 
		fprintf(fp_out,"%s",buf);
	break;
  case 5:
	if(atoi(s[n])<=cond_int) 
		fprintf(fp_out,"%s",buf);
	break;
  }
 }
 }
}

/*------------------------get_fields()----------------------------------*/
/*break a tuple into attributes to be able to find which number of 	*/
/*of attributes in a tuple to do project, join, and select operation	*/
/*----------------------------------------------------------------------*/

get_fields(n)
int n;			/*which number of relation		*/
{
int i;
int m;
int k;

m=1;
k=0;
for(i=0;i<=SIZE; i++) {
	if(n==1) 

	{ /* break buf into s[1], s[2], .... */

		if(buf[i]=='\t' || buf[i]=='\n') {
			s[m][k] = '\0';
			if(buf[i]=='\n') return;
			k=0;
			m++;
			}
		else {
			s[m][k] = buf[i];
			k++; 
			}
	}
	else { /* break buff into p[1], p[2], .. */
		if(buff[i]=='\t' || buff[i]=='\n') {
			p[m][k] = '\0';
			if(buff[i]=='\n') return;
			k=0;
			m++;
			}
		else {
			p[m][k] = buff[i];
			k++; 
			}
	}
}
}


    Source: geocities.com/hsvfapa