📄 relationship.cpp
字号:
KEY k(any1);
if(R2->at[AttrNo2].idx)
{
CBlock *pblk=NULL;
CResult res=R2->at[AttrNo2].tree->SearchBTree(k);
if(R2->at[AttrNo2].unq)
{
if(res.success)
{
R2->enddb=1;
pblk=CMemory::ReadDBBlock(res.recptr);
rcd2=pblk->ReadRecord(OFFSET(res.recptr),R2);//!!!!!!!!
combine=(*rcd1)+(*rcd2);
delete rcd2;
con_success=true;
}
}
else
{
if(R2->enddb==1)
{ //超级冗余
CBuffer *buffer=R2->at[AttrNo2].tree->SearchAll(k,&res,TRUE);//允许重复//??
R2->SetCurBuffer(buffer);
R2->Reset();
}
rcd2=R2->NextRecord(true);//根据buffer读
if(rcd2)
{
combine=(*rcd1)+(*rcd2);
delete rcd2;
con_success=true;
}
}
}
else//R2响应字段未建索引
{
if(R2->enddb==1)
{
R2->Reset();
R2->enddb=0;
}
rcd2=R2->NextRecord(false);//不根据buffer读
if(rcd2)
{
ANY any2=rcd2->AttrToValue(AttrNo2);
switch(cmp)
{
case 0:
{
if(any1==any2)
{
combine=(*rcd1)+(*rcd2);
con_success=true;
}
break;
}
case 1:
{
if(any1<any2)
{
combine=(*rcd1)+(*rcd2);
con_success=true;
}
break;
}
case 2:
{
if(any1>any2)
{
combine=(*rcd1)+(*rcd2);
con_success=true;
}
break;
}
}
delete rcd2;
}
}
}
else
{
delete R2->buffer;
R2->buffer=NULL;
}
}
while(rcd1 && !con_success);
return combine;
}
void Relationship::SetCurBuffer(CBuffer *buffer)
{
if(this->buffer!=buffer)
delete (this->buffer);
this->buffer=buffer;
}
UINT Relationship::GetRecordLength()
{
WORD i;
UINT length=0;
for(i=1;i<=attr_num;i++)
{
if(at[i].type==CHAR_TYPE)
length+=(at[i].length+1);
else if(at[i].type==VARCHAR_TYPE)
length+=(at[i].length+2);
else
length+=at[i].length;
}
return length;
}
Record * Relationship::NextUnion(CHashTable &HashTable,Relationship *R2
,BYTE *mask1,BYTE *mask2,
BOOL distinct,CBuffer *buf1,CBuffer *buf2)
{
Record *Ret=NULL;
Record *Src=NULL;
do
{
delete Ret;
Ret=NULL;
if(buf1)
{
Src=NextRecord(true);
if(Src)
Ret=Src->Shadow(mask1);//按buffer读
delete Src;
}
else
{
Src=NextRecord(false);
if(Src)
Ret=Src->Shadow(mask1);//不按buffer读
delete Src;
}
if(Ret && HashTable.InsertRecord(Ret,!distinct)==TRUE)
return Ret;
}
while(Ret);
//并R2
do
{
delete Ret;
Ret=NULL;
if(buf2)
{
Src=R2->NextRecord(true);
if(Src)
Ret=Src->Shadow(mask2);//按buffer读
delete Src;
}
else
{
Src=R2->NextRecord(false);
if(Src)
Ret=Src->Shadow(mask2);//不按buffer读
delete Src;
}
if(Ret && HashTable.InsertRecord(Ret,!distinct)==TRUE)
return Ret;
}
while(Ret);
return NULL;
}
//将所有记录插入索引
void Relationship::AutoIndex(WORD AttrNo)
{
Record *rcd=NULL;
KEY k;
CResult res;
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
enddb=0;
while(enddb==0)
{
rcd=NextRecord(false);
if(rcd)
{
k=rcd->AttrToKey(AttrNo);
res=at[AttrNo].tree->SearchBTree(k);
at[AttrNo].tree->InsertBTree(k,CurDbPtr,res.pdbNode,res.pos);
}
}
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
}
BOOL Relationship::InsertRecord(Record *rcd)
{
BOOL should=TRUE;
PDB recptr=DB_NULL;
CResult *res=NULL;
KEY *k=NULL;
if(idx_num>0)
{
res=new CResult[attr_num+1];
k=new KEY[attr_num+1];
}
should=CheckRcdKey(res,k,rcd);
if(should)
should=CheckRcdKey(rcd);//慢扫描
if(should)
{
CDatabaseFile *cdbf=CMemory::GetFile(DataFileNo);
recptr=cdbf->Allocate(rcd,this);
//记录ID插入B+树
KEY kid(0,rcd->ID);
CResult res_id=tree->SearchBTree(kid);
ASSERT(!(res_id.success));
tree->InsertBTree(kid,recptr,res_id.pdbNode,res_id.pos);
//所有已建索引的B+树插入新键
for(WORD i=1;i<=attr_num;++i)
{
if(at[i].idx)
{
at[i].tree->InsertBTree(k[i],recptr,res[i].pdbNode,res[i].pos);
}
}
}
else
{
AfxMessageBox("Dup Key");
}
delete []k;
delete []res;
//delete rcd;
}
void Relationship::DeleteRecord(CBuffer *buffer)
{
//对于重复键,!(res.success)并不代表没有存在的记录
CString sss;//debug
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
enddb=0;
//用于删除键值
ANY any;
KEY dk;
CResult dres;
Record *deleted=NULL;
while(!enddb)
{
deleted=NextFitDelete(buffer);//不根据范式???
if(deleted)
{
//删除B+树中的记录ID
dk=KEY(0,deleted->ID);
dres=tree->SearchBTree(dk);
ASSERT(dres.success);
tree->DeletePtr(dk,dres.pdbNode,dres.pos);
//删除所有已建的键值
for(WORD j=1;j<=UINT(attr_num);j++)
{
if(at[j].idx)
{
any=deleted->AttrToValue(j);
dk=KEY(any);
dres=at[j].tree->SearchBTree(dk);//应该都能找到
ASSERT(at[j].unq&&dres.success||!(at[j].unq));
if(at[j].unq==1)
at[j].tree->DeletePtr(dk,dres.pdbNode,dres.pos);//删除旧键
else
at[j].tree->DeletePtr(dk,dres.pdbNode,dres.recptr
,CurDbPtr);//删除Dup旧键
}
}
}
delete deleted;
}
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
}
CBuffer * Relationship::SelectRecord(CNormalForm &form)
{
CBuffer *res_buf=new CBuffer(300,300);
Record *rcd=NULL;
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
enddb=0;/////////////////////////////////////////////////////////
CNormalForm ApForm;
Split(form,ApForm);//改变Form和ApForm
CBuffer *buffer=SelectByIndex(ApForm);
//CViewData view;
//WORD OrderAttrNo=0;
//CMergeTree mtree;
//ANY any;
//KEY k;
//Result res;
UINT ii=0;//////////////////////////调试
UINT Count=0;
do
{
rcd=SelectNext(form,buffer);//此时form全是不能用索引的条件
if(rcd)
res_buf->Append(CurDbPtr);
ii++;
delete rcd;
}
while(rcd);
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
return res_buf;
}
//返回的ApForm是建过索引的
void Relationship::Split(CNormalForm &Form,CNormalForm &ApForm)
{
UINT i;
CCondition *condition=NULL;
for(i=0;i<Form.Count;i++)
{
condition=new CCondition(Form[i]);
if(condition->AttrNo2==0 && at[condition->AttrNo1].idx==1)
//没有第二字段且第一字段建过索引
{
if(condition->xkey.type!=CHAR_TYPE || condition->xflag==2)
{
Form.DeleteCondition(i);
ApForm.InsertCondition(condition);
}
else
{
delete condition;
}
}
else
{
delete condition;
}
}
}
void Relationship::Display(CBuffer *buffer,CString *shd,WORD OrderAttrNo,bool bDistinct
,CListCtrl &List)
{
WORD i,j=0;
UINT Count=0;
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
enddb=0;/////////////////////////////////////////////////////////
SetCurBuffer(buffer);
while(List.DeleteColumn(0)==TRUE);
Record *rcd;
Record *src_rcd;
BYTE *mask=new BYTE[attr_num+1];
::memset(mask,0,attr_num+1);
for(i=1;i<=attr_num;i++)
{
if(shd[i]!="")//非空
{
List.InsertColumn(j,LPCTSTR(shd[i]),LVCFMT_CENTER,80);
mask[i]=1;
j++;
}
}
CMergeTree mtree;
if(OrderAttrNo!=0)
{
//创建的新临时文件覆盖原来文件
CIndexFile f("D:\\DB\\4.index",CFile::modeCreate
|CFile::modeReadWrite,4);
mtree=CMergeTree(1-at[OrderAttrNo].unq,at[OrderAttrNo].type,1,4);
}
BOOL NoDup=TRUE;
CHashTable HashTable;
if(bDistinct)//要消除重复
{
UINT HashID=CMemory::GetHashFileID();
UINT RcdLen=GetRecordLength();
HashTable=CHashTable(RcdLen,HashID);
}
do
{
src_rcd=NextRecord(true);//按Buffer读
if(src_rcd)
rcd=src_rcd->Shadow(mask,NULL,NULL);///////////////////////////////////////!!!
else
rcd=NULL;
if(rcd)
{
if(bDistinct)
NoDup=HashTable.InsertRecord(rcd,false);//不允许重复
if(NoDup)
{
if(OrderAttrNo==0)//不需排序
rcd->Draw(Count++,List,NULL,NULL,mask);
else
{
KEY key=rcd->AttrToKey(OrderAttrNo);
CResult res=mtree.SearchBTree(key);
mtree.InsertBTree(key,CurDbPtr,res.pdbNode,res.pos);
}
}
}
delete rcd;
}
while(rcd);
if(OrderAttrNo!=0)//需要排序
{
Reset();
enddb=0;
CurNode=mtree.m_sqt;
do
{
rcd=NextRecord(false);
if(rcd)
{
rcd->Draw(Count++,List,NULL,NULL,mask);
}
delete rcd;
}
while(rcd);
}
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
CMemory::DestroyHashTable();
}
//B树主文件
//UINT ID
//BYTE DUP
//BYTE KeyType
//BYTE KeyNum
//WORD KeyLength
//WORD M
//PDB ROOT
//PDB SQT
//unsigned int m_uiKeyCount;
//unsigned int m_uiEffectKey;
//UINT currentFile//当前文件号
//复合索引1,复合索引2,复合索引3........
BOOL Relationship::CreateIndex(CString AttrName)
{
WORD AttrNo=0;
if(AttrName!="")
{
AttrNo=AttrNameToAttrNo(AttrName);
if(AttrNo==0)
{
AfxMessageBox("wrong attribute");
return FALSE;
}
}
BYTE KeyType,KeyNum=1;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!KeyNum恒等于1
WORD KeyLength;
if(AttrName=="")
{
KeyType=UINT_TYPE;
KeyLength=4;
BOOL Dup=0;
UINT IndexMainID=CMemory::AllocateID(FILE_ID);
UINT IndexID=CMemory::AllocateID(FILE_ID);
IndexMainFile=IndexMainID;
tree=new CBplusTree(IndexMainID,Dup,KeyType,KeyNum,KeyLength,IndexID);
CString s;
s.Format("D:\\DB\\%d.mdx",IndexMainID);
CFile f(LPCTSTR(s),CFile::modeCreate);//主文件
f.Close();
s.Format("D:\\DB\\%d.index",IndexID);
CIndexFile cidxf(LPCTSTR(s),CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite
,IndexID);
}
else
{
switch(at[AttrNo].type)
{
case INT_TYPE:
case FLOAT_TYPE:
KeyType=at[AttrNo].type;
KeyLength=4;
break;
case CHAR_TYPE:
case VARCHAR_TYPE:
KeyType=CHAR_TYPE;
KeyLength=KEY_LENGTH;////////////////////////////////////////////////////////////!!!!!!!!!!!!!!!!!!
break;
case TIME_TYPE:
KeyType=TIME_TYPE;
KeyLength=4;///////////////////////////////////////////////////BYTE [4]
break;
case DATE_TYPE:
KeyType=DATE_TYPE;
KeyLength=8;//////////////////////////////////////////////////WORD [8]
break;
default:
ASSERT(0);
}
if(at[AttrNo].idx!=1)
{
idx_num++;
at[AttrNo].idx=1;
wtag=1;
BOOL Dup=BOOL(1-at[AttrNo].unq);
UINT IndexMainID=CMemory::AllocateID(FILE_ID);
UINT IndexID=CMemory::AllocateID(FILE_ID);
at[AttrNo].SetIndex(IndexMainID);
at[AttrNo].tree=new CBplusTree(IndexMainID,Dup,KeyType,KeyNum,KeyLength,IndexID);
CString s;
s.Format("D:\\DB\\%d.mdx",IndexMainID);
CFile f(LPCTSTR(s),CFile::modeCreate);//主文件
f.Close();
s.Format("D:\\DB\\%d.index",IndexID);
CIndexFile cidxf(LPCTSTR(s),CFile::modeCreate|CFile::modeReadWrite
,IndexID);
/////////////////the bug is killed at 9.14,
//cidxf析构时会将错误的数值0,覆盖正确的数值
cidxf.Close();
this->AutoIndex(AttrNo);
}
}
return TRUE;
}
BOOL Relationship::CreateMulIndex(CString AttrName1, CString AttrName2, BOOL Dup)
{
WORD AttrNo1=AttrNameToAttrNo(AttrName1);
WORD AttrNo2=AttrNameToAttrNo(AttrName2);
if(AttrNo1>0 && AttrNo2>0)
{
CMultiIdx multi(Dup,AttrNo1,AttrNo2);
CreateIndex(AttrNo1);
CreateIndex(AttrNo2);
AddMultiIdx(multi);//大错!!!!!!!!!!!!!!!!!!!!!!!
return TRUE;
}
return FALSE;
}
void Relationship::CreateIndex(WORD AttrNo)
{
BYTE KeyType,KeyNum=1;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!KeyNum恒等于1
WORD KeyLength;
if(AttrNo==0)
{
KeyType=UINT_TYPE;
KeyLength=4;
BOOL Dup=0;
UINT IndexMainID=CMemory::AllocateID(FILE_ID);
UINT IndexID=CMemory::AllocateID(FILE_ID);
IndexMainFile=IndexMainID;
tree=new CBplusTree(IndexMainID,Dup,KeyType,KeyNum,KeyLength,IndexID);
CString s;
s.Format("D:\\DB\\%d.mdx",IndexMainID);
CFile f(LPCTSTR(s),CFile::modeCreate);//主文件
f.Close();
s.Format("D:\\DB\\%d.index",IndexID);
CIndexFile cidxf(LPCTSTR(s),CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite
,IndexID);
}
else
{
switch(at[AttrNo].type)
{
case INT_TYPE:
case FLOAT_TYPE:
KeyType=at[AttrNo].type;
KeyLength=4;
break;
case CHAR_TYPE:
case VARCHAR_TYPE:
KeyType=CHAR_TYPE;
KeyLength=KEY_LENGTH;////////////////////////////////////////////////////////////!!!!!!!!!!!!!!!!!!
break;
case TIME_TYPE:
KeyType=TIME_TYPE;
KeyLength=4;///////////////////////////////////////////////////BYTE [4]
break;
case DATE_TYPE:
KeyType=DATE_TYPE;
KeyLength=8;//////////////////////////////////////////////////WORD [8]
break;
default:
ASSERT(0);
}
if(at[AttrNo].idx!=1)
{
idx_num++;
at[AttrNo].idx=1;
wtag=1;
BOOL Dup=BOOL(1-at[AttrNo].unq);
UINT IndexMainID=CMemory::AllocateID(FILE_ID);
UINT IndexID=CMemory::AllocateID(FILE_ID);
at[AttrNo].SetIndex(IndexMainID);
at[AttrNo].tree=new CBplusTree(IndexMainID,Dup,KeyType,KeyNum,KeyLength,IndexID);
CString s;
s.Format("D:\\DB\\%d.mdx",IndexMainID);
CFile f(LPCTSTR(s),CFile::modeCreate);//主文件
f.Close();
s.Format("D:\\DB\\%d.index",IndexID);
CIndexFile cidxf(LPCTSTR(s),CFile::modeCreate|CFile::modeReadWrite
,IndexID);
/////////////////the bug is killed at 9.14,
//cidxf析构时会将错误的数值0,覆盖正确的数值
cidxf.Close();
this->AutoIndex(AttrNo);
}
}
}
BOOL Relationship::CheckUpdateData(CUpdate &update)
{
BOOL correct=TRUE;
for(WORD i=0;i<update.current && correct;i++)
{
WORD No=update.up_itms[i].index;//被修改的字段,同CupAttrNo
CString value=update.up_itms[i].value;
switch(at[No].type)
{
case INT_TYPE:
{
int ival=0;
correct=CMemory::ATOI(value,ival);
}
break;
case FLOAT_TYPE:
{
float fval=0;
correct=CMemory::ATOF(value,fval);
}
break;
case TIME_TYPE:
{
Time t;
correct=CMemory::ATOTime(value,t);
}
break;
case DATE_TYPE:
{
Date d;
correct=CMemory::ATODate(value,d);
}
break;
default:
break;
}
}
return correct;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -