⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 relationship.cpp

📁 有计算机图形学、图像处理、dbms、sniffer、中游俄罗斯外挂、othello、遗传算法、舌苔分析等程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -