📄 relationship.cpp
字号:
// Relationship.cpp: implementation of the Relationship class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Database.h"
#include "Relationship.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Relationship::Relationship()
{
wtag=0;
CurNode=NULL;
CurNo=0;
CurDbPtr=0;
enddb=1;
buffer=NULL;
rcd_len=0;
tree=NULL;
}
//id,fileNo,time,db_addr都未知
Relationship::Relationship(CString n, WORD an):attr_num(an)
{
ID=0;
DataFileNo=0;
time=0;
tree=NULL;
wtag=1;
idx_num=0;
rcd_len=0;//辅助
CurNode=NULL;
CurNo=0;
CurDbPtr=0;
enddb=1;
buffer=NULL;
if(n.GetLength()<=10)
{
name=n;
name_length=n.GetLength()+1;
}
else
{
name=n.Left(10);
name_length=10+1;
}
at=new CAttribute[attr_num+1];
length=GetHeadLength();////易出错
MultiNum=0;
MultiIdx=new CMultiIdx[2];//初始化复合索引0个,位置2个
}
Relationship::Relationship(CString n,UINT id,WORD an,UINT FN,int t)
:ID(id),attr_num(an),DataFileNo(FN)
{
wtag=1;
idx_num=0;
rcd_len=0;//辅助
tree=NULL;
CurNode=NULL;
CurNo=0;
CurDbPtr=0;
enddb=1;
buffer=NULL;
if(n.GetLength()<=10)
{
name=n;
name_length=n.GetLength()+1;
}
else
{
name=n.Left(10);
name_length=10+1;
}
time=t;
at=new CAttribute[attr_num+1];
length=GetHeadLength();//易出错
MultiNum=0;
MultiIdx=new CMultiIdx[2];//初始化复合索引0个,位置2个
}
void Relationship::AddAttribute(USHORT index,CAttribute &a)
{
ASSERT(index>=1&&index<=attr_num);
a.offset=rcd_len;
at[index]=a;
length+=(a.GetLength());
if(a.type==CHAR_TYPE)
rcd_len+= (a.length+1);
else if(a.type==VARCHAR_TYPE)
rcd_len+= (a.length+2);
else
rcd_len+= a.length;
}
Relationship::~Relationship()
{
delete []at;
delete tree;
delete []MultiIdx;
delete buffer;
}
WORD Relationship::GetHeadLength()//易出错处3*siaeof(UINT)
{
return (2*sizeof(BYTE)+4*sizeof(WORD)+sizeof(int)
+3*sizeof(UINT)+name_length+sizeof(PDB));
}
void Relationship::WriteBack()
{
WORD i;
CString filename("");
BYTE exist=1;
UINT offset=UINT(db_addr&0xFFFFFFFF);
UINT fileno=UINT(db_addr>>32);
filename.Format("D:\\DB\\%d.scmf",fileno);
CSchemaFile cscmf(LPCTSTR(filename),CFile::modeReadWrite);
cscmf.Seek(offset,CFile::begin);
cscmf.Write(&exist,sizeof(BYTE));
cscmf.Write(&length,sizeof(WORD));
cscmf.Write(&name_length,sizeof(BYTE));
cscmf.Write(LPCTSTR(name),name_length);
cscmf.Write(&ID,sizeof(UINT));
cscmf.Write(&attr_num,sizeof(WORD));
cscmf.Write(&idx_num,sizeof(WORD));
cscmf.Write(&MultiNum,sizeof(WORD));//+++++++++++++
cscmf.Write(&DataFileNo,sizeof(UINT));
cscmf.Write(&db_addr,sizeof(PDB));
cscmf.Write(&IndexMainFile,sizeof(UINT));//新
cscmf.Write(&time,sizeof(int));
tree->WriteBack(MultiIdx,MultiNum);//顺便写复合索引
//写CAttribute
for(i=1;i<=attr_num;i++)
{
cscmf.Write(&at[i].name_length,sizeof(BYTE));
cscmf.Write(LPCTSTR(at[i].name),at[i].name_length);
cscmf.Write(&at[i].type,sizeof(BYTE));
cscmf.Write(&at[i].idx,sizeof(BYTE));
cscmf.Write(&at[i].unq,sizeof(BYTE));
cscmf.Write(&at[i].ispk,sizeof(BYTE));
cscmf.Write(&at[i].can_null,sizeof(BYTE));
cscmf.Write(&at[i].rf_relationship,sizeof(UINT));
cscmf.Write(&at[i].rf_Attribute,sizeof(WORD));///!!!!!!!!!!!!!!!!
cscmf.Write(&at[i].length,sizeof(WORD));
if(at[i].idx)
{
at[i].tree->WriteBack(NULL,0);//写B+树主文件
}
cscmf.Write(&at[i].IndexMainFile,sizeof(UINT));
cscmf.Write(&at[i].offset,sizeof(UINT));
}
}
Record * Relationship::NextRecord(bool bAccordBuffer/*,CBuffer *buffer*/)
{
CBlock *pblk=NULL;
if(!bAccordBuffer)
{
if(!CurNode)
{
enddb=1;
return NULL;
}
if(CurNo >= CurNode->keynum)
{
//9.7发现的bug
CurNode->rtag=0x1;//旧的解锁
CurNode=CMemory::ReadIDXBlock(CurNode->pointer.address1.right
,tree->M,tree->KeyType,tree->KeyLength,CurNode);
CurNo=0;
if(!CurNode)
{
enddb=1;
return NULL;
}
else
CurNode->rtag=0x2;//新的加锁
}
PDB recptr=CurNode->pointer.address1.recptr[CurNo];
while(recptr==DB_NULL&&enddb!=1)
{
CurNo++;
if(CurNo >= CurNode->keynum)
{
//9.7发现的bug
CurNode->rtag=0x1;//旧的解锁
CurNode=CMemory::ReadIDXBlock(CurNode->pointer.address1.right
,tree->M,tree->KeyType,tree->KeyLength,CurNode);
CurNo=0;
if(!CurNode)
{
enddb=1;
return NULL;
}
}
if(CurNode)
{
CurNode->rtag=0x2;//新的加锁
recptr=CurNode->pointer.address1.recptr[CurNo];
}
}
if(recptr!=DB_NULL)
{
CurDbPtr=recptr;
pblk=CMemory::ReadDBBlock(recptr);
}
CurNo++;
return (pblk->ReadRecord( OFFSET(recptr) ,this) );
}
else
{
if(buffer==NULL)
{
CurNo=0;
enddb=1;
return NULL;
}
++CurNo;
enddb=0;
if(CurNo>buffer->count)
{
CurNo=0;
enddb=1;
return NULL;
}
PDB recptr=(*buffer)[CurNo];
pblk=CMemory::ReadDBBlock(recptr);
CurDbPtr=recptr;
return (pblk->ReadRecord( OFFSET(recptr),this) );
}
}
//根据索引查找符合条件的第一条记录
//若字段未建索引,返回NULL,此时k是错的
CResult * Relationship::SearchRecord(WORD AttrNo,CString AttrValue,KEY &k)
{
if(at[AttrNo].idx==0)
{
return NULL;
}
else
{
switch(at[AttrNo].type)
{
case INT_TYPE:
k=KEY(0,atoi(LPCTSTR(AttrValue)));
break;
case FLOAT_TYPE:
k=KEY(0,float(atof(LPCTSTR(AttrValue))));
break;
case CHAR_TYPE:
case VARCHAR_TYPE:
k=KEY(0,AttrValue);
break;
case TIME_TYPE:
{
Time time(AttrValue);
k=KEY(0,time);
break;
}
case DATE_TYPE:
{
Date date(AttrValue);
k=KEY(0,date);
break;
}
default:
ASSERT(0);
break;
}
ASSERT(at[AttrNo].tree);
CResult res=at[AttrNo].tree->SearchBTree(k);
CResult *Ret=new CResult(res.success,res.pdbNode,res.recptr,res.pos);
return Ret;
}
}
void Relationship::AddMultiIdx(CMultiIdx mul)
{
CMultiIdx *newbase=NULL;
if(MultiNum>=2)
{
newbase=new CMultiIdx[MultiNum+1];
::memcpy(newbase,MultiIdx,MultiNum*sizeof(CMultiIdx));
delete []MultiIdx;
MultiIdx=newbase;
}
MultiIdx[MultiNum]=mul;
MultiNum++;
}
BOOL Relationship::CheckRcdKey(CResult *res, KEY *k, Record *rcd,CUpdate *update)
{
WORD i;
ANY value;
BOOL should=TRUE;
BOOL Dup;
if(k==NULL)
{
ASSERT(res==NULL);
return TRUE;
}
//memset(res,0,(attr_num+1)*sizeof(CResult));
//memset(k,0,(attr_num+1)*sizeof(KEY));
for(i=1;i<=attr_num&&should;i++)
{
if(at[i].idx)
{
Dup=BOOL(1-at[i].unq);
value=rcd->AttrToValue(i);
switch(at[i].type)
{
case INT_TYPE:
k[i]=KEY(0,value.ival);
break;
case FLOAT_TYPE:
k[i]=KEY(0,value.fval);
break;
case CHAR_TYPE:
case VARCHAR_TYPE:
k[i]=KEY(0,*(value.pcval));
break;
case TIME_TYPE:
k[i]=KEY(0,*(value.ptval));
break;
case DATE_TYPE:
k[i]=KEY(0,*(value.pdval));
break;
}
res[i]=at[i].tree->SearchBTree(k[i]);
if(res[i].success==true&&!Dup )//不允许重复键
{
if(!update || update->IsUpdated(i))
should=FALSE;
}
}
}
CBuffer *buf1=NULL;
CBuffer *buf2=NULL;
CBuffer *buf3=NULL;
WORD attr1=0,attr2=0;
for(i=0;i<this->MultiNum&&should;i++)
{
if(MultiIdx[i].Dup==0)//不允许重复键的多重索引
{
attr1=MultiIdx[i].AttrNo[0];
attr2=MultiIdx[i].AttrNo[1];
if(!update || (update->IsUpdated(attr1)) || (update->IsUpdated(attr2)) )
{
if(at[attr1].unq)
{
if(res[attr1].success)
buf1=at[attr1].tree->SearchAll(k[attr1]
,&res[attr1],FALSE);//步韵许重复
}
else
buf1=at[attr1].tree->SearchAll(k[attr1]
,&res[attr1],TRUE);//允许重复
if(at[attr2].unq)
{
if(res[attr2].success)
buf2=at[attr2].tree->SearchAll(k[attr2]
,&res[attr2],FALSE);//步韵许重复
}
else
buf2=at[attr2].tree->SearchAll(k[attr2]
,&res[attr2],TRUE);//允许重复
if(buf1&&buf2)
{
buf1->HeapSort();
buf2->HeapSort();
buf3=(*buf1)*(*buf2);
}
if(buf3&&buf3->count!=0)
{
should=FALSE;
}
}
}
}
delete buf1;
delete buf2;
delete buf3;
return should;
}
WORD Relationship::AttrNameToAttrNo(CString AttrName)
{
WORD i,AttrNo=0;
bool found=false;
if(AttrName.GetLength()>10)
AttrName=AttrName.Left(10);
for(i=1;i<=attr_num&&!found;i++)
{
if(at[i].name==AttrName)
{
AttrNo=i;
found=true;
}
}
return AttrNo;
}
void Relationship::Reset()
{
CurNode=tree->m_sqt;
CurNo=0;
CurDbPtr=0;
enddb=1;
}
Record * Relationship::NextFitDelete(CBuffer *buffer)
{
//Reset();
UINT fileno=0;
CDatabaseFile *cdbf=NULL;
Record *Cur=NULL;
this->SetCurBuffer(buffer);
do
{
Cur=NextRecord(true);//按buffer读
if(!Cur)//记录读完
{
return NULL;
}
else
{
fileno=UINT(CurDbPtr>>32);
cdbf=CMemory::GetFile(fileno);
cdbf->DeleteRecord(CurDbPtr,this,false);//不返回
return Cur;
}
}
while(!enddb);///////////////////////////////////////////////////假的
}
//目前只能作到"buffer与"
BOOL Relationship::UpdateRecord(CBuffer *buffer, CUpdate &update)
{
BOOL success=TRUE;
bool bWatchAll=false;//慢扫描
for(WORD i=0;i<update.current;i++)
{
WORD No=update.up_itms[i].index;//被修改的字段,同CupAttrNo
if(at[No].idx==0 &&at[No].unq==1)
bWatchAll=true;
}
CBlock *block=NULL;
Record *oldRcd=NULL;
Record newRcd;
CResult *new_res=NULL;
KEY *new_k=NULL;
if(idx_num>0)
{
new_res=new CResult[attr_num+1];//0号废弃
new_k=new KEY[attr_num+1];//0号废弃
}
ANY any;
KEY oldk;
CResult old_res;
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
this->enddb=0;
this->SetCurBuffer(buffer);
UINT iii=0;//debug
do
{
oldRcd=NextRecord(true);
iii++;
TRACE("iii=%d\n",iii);
if(oldRcd)
{
newRcd=(*oldRcd);
newRcd.Update(update);
BOOL bShould=CheckRcdKey(new_res,new_k,&newRcd,&update);
if(bShould && bWatchAll)
bShould=CheckRcdKey(&newRcd,&update);//慢扫描
if(bShould)
{
block=CMemory::ReadDBBlock(CurDbPtr);
block->WriteRecord(&newRcd, OFFSET(CurDbPtr) );
for(WORD j=0;j<update.current;j++)
{
WORD CupAttrNo=update.up_itms[j].index;
if(at[CupAttrNo].idx)
{
any=oldRcd->AttrToValue(CupAttrNo);
oldk=KEY(any);
old_res=at[CupAttrNo].tree->SearchBTree(oldk);
ASSERT(at[CupAttrNo].unq&&old_res.success||!(at[CupAttrNo].unq));
if(at[CupAttrNo].unq==1)
at[CupAttrNo].tree->DeletePtr(oldk,old_res.pdbNode,old_res.pos);//删除旧键
else
at[CupAttrNo].tree->DeletePtr(oldk,old_res.pdbNode,old_res.recptr
,CurDbPtr);//删除Dup旧键
//插入新键
at[CupAttrNo].tree->InsertBTree(new_k[CupAttrNo],CurDbPtr
,new_res[CupAttrNo].pdbNode,new_res[CupAttrNo].pos);
}
}
}
else
{
success=FALSE;//修改后键值重复
}
delete oldRcd;
}
}
while(!enddb);
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
delete []new_k;
delete []new_res;
return success;
}
//没有索引,慢扫描
BOOL Relationship::CheckRcdKey( Record *rcd,CUpdate *update)
{
WORD i;
bool bContinue=false;
for(i=1;i<=attr_num;i++)
{
if(at[i].unq==1 &&at[i].idx==0)
{
bContinue=true;
break;
}
}
if(!bContinue)//没有需要检验的键
return TRUE;
Record *Cur;
ANY any1,any2;
BTNODE *CurNode1=CurNode;
UINT CurNo1=CurNo;
PDB CurDbPtr1=CurDbPtr;
BYTE enddb1=enddb;
Reset();
enddb=0;
while(!enddb&&bContinue)
{
Cur=NextRecord(false);
if(Cur&&Cur->ID!=rcd->ID)//与rcd不是同一条记录
{
for(i=1;i<=attr_num&&bContinue;i++)
{
if(at[i].unq==1 && at[i].idx==0)
{
any1=Cur->AttrToValue(i);
any2=rcd->AttrToValue(i);
if(any1==any2)
bContinue=false;
}
}
}
}
CurNode=CurNode1;
CurNo=CurNo1;
CurDbPtr=CurDbPtr1;
enddb=enddb1;
if(!bContinue)
return FALSE;
else
return TRUE;
}
//一次只选出一条记录,此处的form只能慢扫描
Record * Relationship::SelectNext(CNormalForm &form,CBuffer *buf)
{
Record *rcd=NULL;
bool bAccordBuffer=true;
if(!buf)
bAccordBuffer=false;
if(buf && buf->count==0)
return NULL;
SetCurBuffer(buf);
do
{
rcd=NextRecord(bAccordBuffer);
if(rcd && rcd->Fit(form)==TRUE)//马上改成根据form选择
return rcd;
}
while(rcd);
ASSERT(rcd==NULL);
return NULL;
}
CBuffer * Relationship::SelectByIndex(CNormalForm &ApForm)
{
CBuffer *buffer=NULL;
CBuffer *res_buf=NULL;
CBuffer *del=NULL;
CCondition condition;
WORD AttrNo=0;
for(UINT i=0;i<ApForm.Count;i++)
{
condition=ApForm[i];
AttrNo=condition.AttrNo1;
CResult res=at[AttrNo].tree->SearchBTree(condition.xkey);
if(condition.xflag!=2)//不是单纯的"="
{
if(at[AttrNo].unq==1)
buffer=at[AttrNo].tree->SearchScope(condition.xkey,condition.skey,
res.pdbNode,condition.xflag,condition.sflag,res.pos);
else
buffer=at[AttrNo].tree->SearchScope(condition.xkey,condition.skey,
res.pdbNode,condition.xflag,condition.sflag,res.recptr);
if(i==0)
{
res_buf=buffer;
res_buf->HeapSort();
}
if(res_buf->count==0)
return res_buf;//空集的脚永远为空,直接返回
}
else
{
if(at[AttrNo].unq==1)
buffer=at[AttrNo].tree->SearchAll(condition.xkey ,&res, FALSE);
else
buffer=at[AttrNo].tree->SearchAll(condition.xkey, &res, TRUE);
if(i==0)
{
res_buf=buffer;
res_buf->HeapSort();
}
if(res_buf->count==0)
return res_buf;
}
if(i>0)
{
del=res_buf;
buffer->HeapSort();
res_buf=(*res_buf) * (*buffer);
delete buffer;
delete del;
}
}
return res_buf;
}
Record * Relationship::Connect(Relationship *R2, WORD AttrNo1, WORD AttrNo2, BOOL cmp
,Record *&rcd1)
{
Record *combine=NULL;
//Record *rcd1=NULL;
Record *rcd2=NULL;
bool con_success=false;
do
{
if(R2->enddb==1)
{
delete rcd1;
rcd1=NextRecord(false);//暂且不考虑根据buffer读记录,故为false
//R2->Reset();
}
if(rcd1)
{
ANY any1=rcd1->AttrToValue(AttrNo1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -