📄 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 + -