?? intepretor.cpp
字號:
/******************************************************************
** 文件名: Intepretor.cpp
** Copyright (c) 2001-2002 計算機99F MiniSQL開發小組其一
** 創建人: 王淮
** 日 期: 2001-12_10
** 修改人: 王淮
** 日 期: 2002-01-07
** 描 述: 定義了MiniSQL Intepretor模塊除對磁盤文件操作之外的所有類和結構
** 版 本: 1.00
******************************************************************/
#include "Intepretor.h"
#include "Glob_Var.h"
extern char CurLocation[256];
//<---存有當前正在使用的表的相對路徑,如"../data/db1/"下存有book這張表
extern char CurRelationName[33];
//<---存當前表的表名
char CurDB[33] = "";
//---enum ErrType {RESOLVE,COMMON,COLUMNTYPE,KEYWORD,
//---COLNAMEERR_IN_CHECK,GET_OP_ERR,NOCOL};
//---用于拋出字串輸入錯誤時輸出錯誤提示使用
char* ppErr[] = {"Can't Resolve this command,It may not a correct command!",
"Common typing error!",
"The type of the data is wrong,we only support the \'char\',\'float\',\'int\' types!",
"Please type the correct keyword!--like \'NotNull\',\'imary\'",
"Your Column name typed in the Check straint doesn\'t exist!",
"May we does't support your operator typed,if you can make sure you have no typing error!",
"You must specify at least one Column for us to select it!"};
//<--- enum GnlErrType{NOSUCHDB,NODBUSED,SUCHDBEXIST};
//<---用于拋出一般性錯誤時輸出錯誤提示使用
char* ppGnlErr[] = {"The DB doesn\'t exist!",
"The Table doesn\'t exist!",
"You haven\'t choose a database!",
"This DB has already existed!",
"This Table has already existed!",
"You must have 2 \' to match each other!",
"No primary key exists!"};
ECMD_TYPE GetCommand(TB_Create_Info** ptrCreateInfo,TB_Select_Info** ptrSelectInfo,TB_Insert_Info** ptrInsertInfo,TB_Update_Info** ptrUpdateInfo,TB_Delete_Info** ptrDeleteInfo)
{
ECMD_TYPE CmdType = UNORMAL;//<---假設給出的命令是非正常的
try{
//--->打出提示信息
std::cout<<'\n';
std::cout<<"MiniSQL->";
Ch_csVstrBlk CommandInput;
//<---開始作解析命令的嘗試
CmdType = CommandInput.ResolveCmd();
//<---開始對輸入的是何命令作解析,由ResolveCmd()對第一個有意字串作判斷
if(CmdType != USE && CmdType != HELP && CmdType != QUIT
&& CmdType != SHOWDB && CmdType != DROP&&CmdType != NEW)
//<---以下命令必須在選擇數據庫后才能執行
{if(CompStrEver(CurDB,""))
{ CmdType = UNORMAL;
GnlTrwErr(NODBUSED);}
}
switch(CmdType) //<---選擇命令
{
case CREATE:
*ptrCreateInfo = CommandInput.CH_Create();
//<---對非該命令的指針賦0
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
return CREATE;
break;
case SELECT:
*ptrSelectInfo = CommandInput.CH_Select();
*ptrCreateInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
return SELECT;
break;
case INSERT:
*ptrInsertInfo = CommandInput.CH_Insert();
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
return INSERT;
break;
case UPDATE:
*ptrUpdateInfo = CommandInput.CH_Update();
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrDeleteInfo = 0;
return UPDATE;
break;
case DELETE:
*ptrDeleteInfo = CommandInput.CH_Delete();
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
return DELETE;
break;
case USE: //<---選擇數據庫
*ptrDeleteInfo = 0;
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
CommandInput.ChoseDatabase();
return USE;
break;
case DROP:
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
CommandInput.DropTB();
return DROP;
break;
case DROPDB:
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
CommandInput.DropDB();
return DROPDB;
break;
case NEW:
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
CommandInput.NewDB();
return NEW;
break;
case QUIT: //<---像該種單詞命令直接檢查合法性,其余命令皆在其函數內部檢查
CommandInput.PassCommon(";");
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
QuitSQL();
return QUIT;
break;
case SHOWDB:
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0; //<---指針置0
ShowDB();
break;
case SHOWTABLE:
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
//<---指針置0
if(CompStrEver(CurDB,""))
GnlTrwErr(NODBUSED);
ShowTable();
break;
case HELP: //<---像該種單詞命令直接檢查合法性,其余命令皆在其函數內部檢查
CommandInput.PassCommon(";");
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0; //<---指針置0
ShowHelp();
break;
default :
*ptrCreateInfo=0;
*ptrSelectInfo=0;
*ptrInsertInfo=0;
*ptrUpdateInfo=0;
*ptrDeleteInfo = 0;
break;
}
}
catch(ErrInfo a)
//字串輸入錯誤,給出提示--->
{
std::cout<<"The Error near \'"<<a.pErrStr<<"\'"<<"in Line "<<a.iLineNo<<" may be: \n";
std::cout<< ppErr[a.iErrType]<<'\n';
CmdType = UNORMAL;
}
catch(GnlErrInfo a)
//一般性錯誤--->
{
std::cout<< ppGnlErr[a.iErrType]<<'\n';
std::cout<< "Please type \'help\' to get help!\n";
CmdType = UNORMAL;
}
return CmdType;
}
//構造函數,對輸入進行處理,產生一個有以字串的集合--->
Ch_csVstrBlk::Ch_csVstrBlk()
{
InitialVar(); //<---初始化輸入字串
MakeVstrBlkList(); //<---生成有意字串塊的鏈表
}
void Ch_csVstrBlk::InitialVar()
{
//初始化某些參數--->
StrHead = 0;
StrNow = 0;
StrTail = 0;
iNumNowInVstr = 0;
iLineNum[0][0] = 0;
sta_i = 0;
strInputCharList = InitialInput();
}
//對輸入進行處理,產生一個有意字串的集合--->
void Ch_csVstrBlk::MakeVstrBlkList()
{
int flag;
int iForLineNum = 0;
char* tempStr;
VSTR_BLK_PTR vbNewBlk;
do
{
flag = InString(&tempStr);
//<---可能在字符串拷貝時會出錯,小心
if(flag == 0)
{
//<---返回有意字串
iNumNowInVstr++;
//<---有意字串個數加1
{vbNewBlk = new VSTR_BLK;
vbNewBlk->str = tempStr;
vbNewBlk->next = 0;
if(StrHead == 0)
StrHead = vbNewBlk;
else
StrTail->next = vbNewBlk;
StrTail = vbNewBlk;
}
//<---生成一個有意字串的結構體,并將它鏈成鏈表
}
else
{ //<--- 回車,說明行數加一
iLineNum[iForLineNum++][1] = iNumNowInVstr;
//<--- 原來末行的末地址
iLineNum[iForLineNum][0] = iNumNowInVstr + 1;
//<--- 新行的首地址
}
}
while(CompStrEver(tempStr,"\xff") != 1);
//<--- 得到的是"\xff"時,表示用戶輸入已經結束
iNumNowInVstr = 0;
//<--- 再次初始化iNumNowInVstr,用于正式輸入處理時的位置計算
StrNow = StrHead;
//<--- 將StrNow指到StrHead上
}
bool Ch_csVstrBlk::InString(char** ObjectStr)
/*********************************************************
return = 0,有意字串
return = 1,回車
*********************************************************/
/*
*/
{
int i = 0;
char chTemp;
*ObjectStr = new char[NAMEMAXLEN];
if((chTemp = strInputCharList[sta_i++]) != '\0')
(*ObjectStr)[i++] = chTemp;
//<--- 第一個字符如果為空,則必須略過
do{
chTemp = strInputCharList[sta_i++];
(*ObjectStr)[i++] = chTemp;
}
while(chTemp != '\0');
if(CompStrEver(*ObjectStr, "\n"))
return 1;//<--- 回車
else
return 0;//<--- 有意字串
}
char* Ch_csVstrBlk::InitialInput()
{
/*********************************************************
過濾空格信息,只留下回車和其他字符,對于有意字串用'\0'來區分,
對于字串的結束,用'\xff'來表示
共有5種辨別有意字串的字符
--- 空格, 逗號,分號,左括號,右括號,,左單引號,右單引號,回車
***checked 2001-12-5***
*********************************************************/
char* strResult;
strResult = new char[INPUTMAX];
char tempIn;
int i = 0;
int DoGetcharFlag = 1;
int MaybeEnd = 0;
int EndFlag = 0;
do{
if(DoGetcharFlag)
{
tempIn = getchar();
}
else
DoGetcharFlag = 1;
switch(tempIn)
{
case ' ' : //<--- 略空格
{
if(strResult[i - 1] != 0)
strResult[i++] = 0;
do{
tempIn = getchar();
}while(tempIn == ' '); //<--- 過濾空格
DoGetcharFlag = 0; //<--- 則新的循環中無需再讀入一個字符
}
break;
case ';' : //<--- 輸入結束標志
SaveKeyChar(strResult,&i,tempIn);
MaybeEnd = 1; //<--- 表示可能是輸入結束,MaybeEnd在下一次輸入回車時會用到
break;
case ',' :
case '(' :
case ')' :
case '>' :
case '<' :
case '=' :
SaveKeyChar(strResult,&i,tempIn);
break;
case '\'' : //<--- 在回車之前必須得到另外一個 ' 以作匹配
strResult[i++] = tempIn;
while( (tempIn = getchar())!='\n' &&tempIn != ','&&tempIn!= '\''&&tempIn!= ';')
strResult[i++] = tempIn;
if(tempIn == '\'')
{strResult[i++] = tempIn;
strResult[i++] = '\0';}
else{
do{tempIn=getchar();}while(tempIn !='\n');
GnlTrwErr(WITHOUTMATCH);//<--- 單引號不匹配
}
break;
case '\n' :
if(MaybeEnd == 0)
{
// 回車后將呈現的提示符 --->
std::cout<<" ->";
SaveKeyChar(strResult,&i,tempIn);
}
else //<--- 這一次是整個命令的正式結束
{SaveKeyChar(strResult,&i,tempIn);
EndFlag = 1;}
break;
default : //<--- 一般的字符輸入
strResult[i++] = tempIn;
break;
}
}
while(EndFlag == 0 && i < INPUTMAX);//<--- 檢查何種原因退出循環
SaveKeyChar(strResult,&i,'\xff');
strResult[i] = '\0';
return strResult;
}
TB_Create_Info* Ch_csVstrBlk::CH_Create()
/*****************************************************************
** 輸 出: --- 表示一個完整的有關Create操作的參數類
** 功能描述:負責Create命令的所有操作
** 調用模塊: PassCommon()
****************************************************************/
{
// 命令輸入應該如:create table tablename(columnname,type);
char* strTableName = 0;
TB_Create_Info* tbReturn;
pCreate_Column pTemp = 0,pHead = 0,pTail = 0;
int iColNum = 0;
bool NotEnd = 1;
bool bPriKeyExist = 0; //<--- 用于判斷Primary key是否存在的標志
PassCommon("table");
strTableName = GetTBName(); //<--- 取得表名
if(CheckTB(strTableName))
GnlTrwErr(SUCHTBEXIST); //<--- 檢驗輸入的該table是否存在,存在則給出錯誤
SetCurRelation(strTableName);
PassCommon("(");
do //<--- 取得各個列定義的名稱和類型
{
if(CompStrEver(StrNow->str,"check"))
GetCheckInfo(&NotEnd,pHead); //<--- 該行是有關列的約束信息
else
{pTemp = GetColumnInfo(&NotEnd,bPriKeyExist);
iColNum++; //<--- 列的數量+1
if(pHead == 0)
{pHead = pTemp;
pTail = pTemp;
}
else{
pTail->next = pTemp;
pTail = pTemp;}
}
}while(NotEnd);
PassCommon(")");
PassCommon(";");
if(bPriKeyExist == 0) //<--- primary key不存在
GnlTrwErr(NOPRIMARYKEY);
tbReturn = new TB_Create_Info(iColNum,pHead,strTableName);
//<--- 生成該表
return tbReturn;
}
void Ch_csVstrBlk::GetCheckInfo(bool *NotEnd,pCreate_Column pHead)
{
/*****************************************************************
** 功能描述:得到有關一個列的約束信息
****************************************************************/
char* strColName = new char[NAMEMAXLEN];
EOPE_TYPE optype;
ECOL_TYPE coltype;
COLVAL tmin;
COLVAL tmax;
pCreate_Column pColtemp = 0;
PassCommon("check");
PassCommon("(");
pColtemp = GetColForCheck(StrNow->str,pHead); //<--- 得到check中列的各個信息
optype = GetOptype(); //<--- 得到所要check的列的操作類型
coltype = pColtemp->ColType; //<--- 賦所要check的列的數據類型(char,int,float)中的一種
if(optype == BETWEEN) //<--- BETWEEN AND 比較特殊,單獨處理
{PassCommon("between");
switch(coltype) //<--- 根據數據類型給約束條件賦值
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -