📄 selectexe.c
字号:
for (i=0;i<TabMax;i++)
if (stringcmp(tname,TabDic[i].tab_name)==0)
{
j = TabDic[i].row_len;
break;
}
return(j);
}
//从表字典表得到表名
char * GetTabName(int tid)
{
int i;
for (i=0;i<TabMax;i++)
if (TabDic[i].tab_id == tid)
return(TabDic[i].tab_name);
return(NULL);
}
//从列字典表得到字段id
int GetColID(char *fname)
{
int i,j=0;
for (i=0;i<ColMax;i++)
if (stringcmp(fname,ColDic[i].col_name)==0)
{
j = ColDic[i].col_id;
break;
}
return(j);
}
//从列字典表得到字段类型
int GetColType(int fid)
{
int i,j;
for (i=0;i<ColMax;i++)
if (ColDic[i].col_id == fid)
{
j = ColDic[i].col_type;
break;
}
return(j);
}
//从列字典表得到字段所在表的表id
int GetColTabID(int fid)
{
int i,j=0;
for (i=0;i<ColMax;i++)
if (ColDic[i].col_id == fid)
{
j = ColDic[i].tab_id;
break;
}
return(j);
}
//从列字典表得到字段名
char * GetColName(int fid)
{
int i;
for (i=0;i<ColMax;i++)
if (ColDic[i].col_id == fid)
return(ColDic[i].col_name);
return(0);
}
//得到字段在Tfield重的位置
int LocateTField(int fid)
{
int i;
for(i=0;i<ColNum;i++)
{
if (Tfield[i].col_id == fid) return (i);
}
return(0);
}
//返回临时文件名
FILE *CreateTmpFile(char *tname)
{
int i;
int TabID;
char Tmp[24];
char TmpFileName[50]="Data";
FILE *tmpp;
//把表中的字段放到Tfield
TabID = GetTabID(tname);
for (i=0;i<ColMax;i++)
{
if (ColDic[i].tab_id==TabID)
{
Tfield[ColNum].col_id = ColDic[i].col_id;
Tfield[ColNum].type = ColDic[i].col_type;
Tfield[ColNum].length = ColDic[i].col_length;
ColNum++;
//write template table dictionary
TTabDic2.col_num++;
TTabDic2.row_len += ColDic[i].col_length+1 ;
}
}
//创建临时文件
itoa(TfileNum++,Tmp,10);
strcat(TmpFileName,Tmp);
strcat(TmpFileName,".tmp"); //template table name will like "Data0.tmp"
strcpy(TTabDic2.tab_name,TmpFileName);
if ((tmpp=fopen(TmpFileName,"wb+"))==NULL)
{
printf("Can't open %s file\n",TmpFileName);
exit(3);
}
//写临时文件头:列数、列id
//fwrite(ColNum,4,1,tmpp);
for (i=0;i<ColNum;i++)
{
//fwrite(Tfield[i].col_id,4,1,tmpp);
}
return(tmpp);
}
//单表优化
int Pretreat(char *tname)
{
int i;
long BufSize;
int BlockNum;
FILE *tmpfp;
char Buf1[BUFSIZE];
// char Buff[10240];
int *NextBlock;
int *NextAddr;
int EndSpace=0;
//写临时文件
tmpfp = CreateTmpFile(tname); //write tmp table head infomation
//BufSize = GetTabRowLen(tname)*GetTabRowNum(tname);
BlockNum = GetTabAddr(tname);
EndSpace = (BUFSIZE-24) % GetTabRowLen(tname);
do
{
fseek(fp,BlockNum*BUFSIZE,0);
fread(Buf1,BUFSIZE,1,fp);
NextBlock = (int *)Buf1;
BlockNum = *NextBlock;
NextAddr = (int *)(Buf1+4);
if (*NextBlock != -1)
{
fwrite(Buf1+24,BUFSIZE-24-EndSpace,1,tmpfp);
}
else
{
fwrite(Buf1+24,(*NextAddr) % BUFSIZE,1,tmpfp);
}
}while (*NextBlock != -1);
// rewind(tmpfp);
// fread(Buff,BUFSIZE*4,1,tmpfp);
for (i=0;i<TabMax;i++)
{
if (stringcmp(TabDic[i].tab_name,tname)==0)
{
TTabDic2.row_num = TabDic[i].row_num ;
break;
}
}
TTabDic1 = TTabDic2;
fclose(tmpfp);
}
//对两个表做连接操作
char *MergeTab(char *tname,char *tname1)
{
int i,j;
int BlockNum;
long Len,Num;
char TmpBuf[BUFSIZE];
char Buf1[BUFSIZE];
int pBuf1;
char TmpFileName[50]="Data";
FILE *fp1,*fp2;
int *NextBlock, EndSpace;
//open 临时文件1
if ((fp1=fopen(tname1,"r+"))==NULL)
{
printf("Can't open %s file\n",tname1);
exit(3);
}
//创建临时文件2
fp2 = CreateTmpFile(tname); //write tmp table head infomation
//做两个表的笛卡尔乘积
//先从tname取一条纪录,然后与临时表tname1的所有记录连接,输出到tname2
Len = GetTabRowLen(tname);
Num = GetTabRowNum(tname);
TTabDic2.row_num = 0;
BlockNum = GetTabAddr(tname);
fseek(fp,BlockNum*BUFSIZE,0);
fread(Buf1,BUFSIZE,1,fp);
NextBlock = (int *)Buf1;
pBuf1 = 24;
EndSpace = (BUFSIZE-24) % GetTabRowLen(tname);
for(j=0;j<Num;j++)
{
if (pBuf1 > BUFSIZE - EndSpace -24)
{
BlockNum = *NextBlock;
fseek(fp,BlockNum*BUFSIZE,0);
fread(Buf1,BUFSIZE,1,fp);
NextBlock = (int *)Buf1;
pBuf1 = 24;
}
// Buf1+pBuf1
for(i=0;i<Len;i++)
TmpBuf[TTabDic1.row_len+i] = Buf1[pBuf1++];
rewind(fp1);
for(i=0;i<TTabDic1.row_num;i++)
{
fread(TmpBuf,TTabDic1.row_len,1,fp1);
fwrite(TmpBuf,TTabDic2.row_len,1,fp2);
TTabDic2.row_num ++;
}
}
TTabDic1 = TTabDic2;
fclose(fp1);
fclose(fp2);
return(TTabDic2.tab_name);
}
//字符串比较
int stringcmp(const char *s1, const char *s2)
{
int i=0;
while (s1[i]!=NULL && s2[i]!=NULL)
{
if (s1[i]!=s2[i]) break;
i++;
}
if (s1[i] == s2[i])
return(0);
else
if (s1[i] > s2[i])
return(1);
else
return(-1);
}
/******************************************************************************
处理where子句
采用后序扁历的方法,用S[]栈存储节点(指针),Tval[]存储计算的结果,Tmp[]来标示
左右子女是否已处理过。sp为S[]和Tmp[]的指针,tp为Tval[]的指针。
*******************************************************************************/
int dCondition()
{
struct _conditions *S[CONNUM];
struct _fval Tval[CONNUM];
int sp=0,tp=-1,Tmp[CONNUM];
int i;
//没有条件
if (Tdelete.cons == NULL) return(1);
//有条件: 后续遍历
S[sp]=Tdelete.cons;
Tmp[sp] = 2;
while (sp>=0)
{
if (Tmp[sp] == 2) //未处理节点,左子女进栈
{
Tmp[sp] = 1;
S[sp+1] = S[sp]->left ;
sp++;
if (S[sp]->left == NULL)
Tmp[sp] = 0;
else
Tmp[sp] =2;
continue;
}
else if (Tmp[sp] == 1) //右子女进栈
{
Tmp[sp] = 0;
S[sp+1] = S[sp]->right ;
sp++;
if (S[sp]->left == NULL)
Tmp[sp] = 0;
else
Tmp[sp] =2;
continue;
}
else //处理节点
{
/* 先判断comp_op操作符: 'a'(表示AND)、'o'(表示OR)、d'='、'<'、'>'等
如果是叶节点则判断type:'3'表示子段、'1'表示字符串值、'0'表示整型值*/
switch (S[sp]->comp_op)
{
case 'a':
{
tp--;
if ((Tval[tp].iVal !=0) && (Tval[tp+1].iVal !=0))
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
Tval[tp].type = 1;
break;
}
case 'o':
{
tp--;
if ((Tval[tp].iVal !=0) || (Tval[tp+1].iVal !=0))
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
Tval[tp].type = 1;
break;
}
case '=':
{
tp--;
if (Tval[tp].type != Tval[tp+1].type) printf("Error:'=' 类型不符!\n");
switch (Tval[tp].type)
{
case 1:
{
if (stringcmp(Tval[tp].szVal,Tval[tp+1].szVal) == 0)
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
case 0:
{
if (Tval[tp].iVal == Tval[tp+1].iVal )
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
default: break;
}
Tval[tp].type = 1;
break;
}
case '>':
{
tp--;
if (Tval[tp].type != Tval[tp+1].type) printf("Error:'>' 类型不符!\n");
switch (Tval[tp].type)
{
case 1:
{
if (stringcmp(Tval[tp].szVal,Tval[tp+1].szVal) > 0)
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
case 0:
{
if (Tval[tp].iVal > Tval[tp+1].iVal )
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
default: break;
}
Tval[tp].type = 1;
break;
}
case '<':
{
tp--;
if (Tval[tp].type != Tval[tp+1].type) printf("Error:'<' 类型不符!\n");
switch (Tval[tp].type)
{
case 1:
{
if (stringcmp(Tval[tp].szVal,Tval[tp+1].szVal) < 0)
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
case 0:
{
if (Tval[tp].iVal < Tval[tp+1].iVal )
Tval[tp].iVal = 1;
else
Tval[tp].iVal =0;
break;
}
default: break;
}
Tval[tp].type = 1;
break;
}
default: //叶节点,把值保存下来,入Tval[]
{
tp++;
switch (S[sp]->type)
{
case '2': //field:把子段名称换成相应的值
{
i = GetColID(S[sp]->value);
i = LocateTField(i);
if (GetColType(GetColID(S[sp]->value))==1)
{
Tval[tp].type = 1;
strcpy(Tval[tp].szVal,Tfield[i].charval);
// Tval[tp].szVal = Tfield[i].charval;
}
else
{
Tval[tp].type = 0;
Tval[tp].iVal = Tfield[i].intval;
}
break;
}
case '1': //string
{
Tval[tp].type =1;
strcpy(Tval[tp].szVal,S[sp]->value);
break;
}
case '0': //int
{
Tval[tp].type =0;
Tval[tp].iVal = S[sp]->intval ;
break;
}
default: break;
}
}
}
sp--; //出栈
}
}
return(Tval[0].iVal);
}
void del(_deletestruct_type *ds) //用来检测delete语句的语法树是否正确
{
int i,j,k;
int RecordLen;
int BlockNum;
int RecInBlock,offset;
int TabID;
int *NextAddr,*NextBlock;
int DelFlag=0;
long lfp;
int ConsRecNum;
int RecordNum;
int ddd;
fp = NULL; //数据文件指针
TfileNum=0; //临时文件的数量
TabNum=0; //涉及的表的数量
RecNum=0; //临时表的记录数
ColNum=0; //涉及的表的列数
TabMax = 0;
ColMax = 0;
for (i=0;i<BUFSIZE;i++) Buf[i]=0;
for (i=0;i<TABNUM;i++) strcpy(TabName[i],"");//涉及的表的名称
read_dic(TabDic,&TabMax,ColDic,&ColMax);
Tdelete = *ds;
//open data file
if ((fp=fopen("DATABASE","rb+"))==NULL)
{
printf("Can't open data file\n");
exit(1);
}
//把表中的字段放到Tfield
TabID = GetTabID(Tdelete.table);
for (i=0;i<ColMax;i++)
{
if (ColDic[i].tab_id==TabID)
{
Tfield[ColNum].col_id = ColDic[i].col_id;
Tfield[ColNum].type = ColDic[i].col_type;
Tfield[ColNum].length = ColDic[i].col_length;
Tfield[ColNum].charval = ColDic[i].col_name;
ColNum++;
//write template table dictionary
}
}
//删除字段
BlockNum = GetTabAddr(Tdelete.table);
RecInBlock = (int)((BUFSIZE-24)/GetTabRowLen(Tdelete.table));
offset = 24;
RecordNum = GetTabRowNum(Tdelete.table);
ConsRecNum =0;
do
{
lfp = BlockNum*BUFSIZE;
fseek(fp,BlockNum*BUFSIZE,0);
fread(Buf,24,1,fp);
lfp += 24;
NextBlock = (int *)Buf;
ddd = BlockNum;
BlockNum = *NextBlock;
NextAddr = (int *)(Buf+4);
if (BlockNum != -1)
k = RecInBlock;
else
k = (int)(((*NextAddr)% BUFSIZE-24)/GetTabRowLen(Tdelete.table));
for(i=0;i<k;i++)
{
//fp1 = fp2;
ConsRecNum++;
fread(Buf,GetTabRowLen(Tdelete.table),1,fp);
lfp += GetTabRowLen(Tdelete.table);
ReadARecord(Buf,Tfield);
offset+=GetTabRowLen(Tdelete.table);
if (dCondition()==1)
{
//MoveEnd2Current
for (j=0;j<TabMax;j++)
if (strcmp(Tdelete.table,TabDic[j].tab_name)==0)
break;
fclose(fp);
get_last(TabDic[j],Buf);
//open data file
TabDic[j].row_num--;
DelFlag ++;
if (ConsRecNum >= RecordNum) break;
if ((fp=fopen("DATABASE","rb+"))==NULL)
{
printf("Can't open data file\n");
exit(1);
}
lfp -= GetTabRowLen(Tdelete.table);
fseek(fp,lfp,0);
fwrite(Buf,GetTabRowLen(Tdelete.table),1,fp);
fseek(fp,lfp,0);
i--;
//if (i==k) BlockNum = ddd;
}//end if condition
}
}while (BlockNum != -1);
printf("%d records deleted\n",DelFlag);//delete record
fclose(fp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -