PS:如果读过题了可以跳过题目描述直接到题解部分
链接:UFUG2601_project_Fall2024 MiniDB Project
文章目录
- 题目
- 题解
- 声明
- 可完成操作
- 运行逻辑
- 大致思路
- 数据存储
- 数据类型
- 数据名称
- 命令输入
- 文件读入
- 命令读入
- 操作
- 2.1 Create Database and Use Database
- 2.2 Create Tables
- 2.3 Drop Tables
- 2.4 Data Insertion
- 2.5 Data Query: Basic
- 2.6 Data Query: "Where" Clause
- 2.7 Data Query: "Inner Join" Clause
- 2.8 Data Update
- 2.9 Data Deletion
- 代码实现
题目
题解
声明
解题过程中有部分代码功能上是使用AI(包括ChatGPT以及Kimi.ai生成,但是代码思路及操作实现都是自主完成,没有让AI直接生成大段的完整代码并直接抄写。
可完成操作
运行逻辑
大致思路
整个程序我都选择在线处理操作,既每个命令输入->操作(->输出)->下一个命令。
read部分在进行各种操作的读入及读入内容的处理,read之前的部分负责实现操作。
数据存储
这个程序一开始难住我的地方就在于数据如何存储,如果带入我们平时常写的代码,题目大概就是让你在既不知道数据类型也不知道数据名称的情况下写代码,那么接下来我们就依次解决一下这两个问题。
数据类型
我们可以定义一个枚举来表示支持的数据类型。
enum class DataType{INTEGER,FLOAT,TEXT
};
后来发现这个完全没用就删了……
数据名称
其实这个问题很好解决,用map
函数就好了。
class miniDB{private:map<string,map<string,DataType>> databases;public:void createDatabase(const string& dbName);//......
};
事实上,由于数据库特殊的性质,我们不能将数据存在内存中,因此我们需要创建一个外部文件来储存数据,我选择创建csv文件,所以直接把后续操作直接对文件进行即可。
命令输入
文件读入
首先,我们从题目中明确读入类型是文件读入。这个是个很简单的操作,你可以选择任何顺手的方法,包括文件流之类的,我选择了我比较顺手的freopen
。
freopen("input.sql","r",stdin);
命令读入
在这个地方我们需要考虑很多问题,最主要问题都是空格和换行造成的,包括如何判断一部分内容的结束等。比如逗号、分号、大括号和前面或者后面一部分是连在一起的还是分开的。还有,我们既可以选择一边输入一边输出,也可以选择全部输入将命令处理成我们便于操作的方式后再统一操作输出。
在这里我选择了我们自己对代码掌控很强的string
和char
混合读入处理的方式。(不想大量码代码的人慎用)(具体代码我放在操作部分了)
//处理一些字符串末尾的空格等
string trimTrailingSpaces(const string& str){size_t end=str.find_last_not_of(" \t\n\r\f\v\0");if(end!=string::npos){return str.substr(0,end+1);}return "";
}void readCommand(){string command;while(cin>>command){if(command=="CREATE"){readCreate();}else if(command=="USE"){readUse();}else if(command=="DROP"){readDrop();}else if(command=="INSERT"){cin>>command;//去除INTOreadInsert();}else if(command=="SELECT"){readSelect();cnt++;//输出时有用}else if(command=="UPDATE"){readUpdate();}else if(command=="DELETE"){cin>>command;//去除FROMreadDelete();}}
}
操作
2.1 Create Database and Use Database
即新建文件夹并命名和确定所需要打开文件的位置。
void createDatabase(const string& databaseName){string path=databaseName;mkdir(path.c_str());
}void readCreate(){string type;cin>>type;if(type=="DATABASE"){databaseName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);databaseName+=s;c=getchar();}databaseName=trimTrailingSpaces(databaseName);createDatabase(databaseName);}else if(type=="TABLE"){tableName="";int i=0;char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!='('){s.assign(1,c);tableName+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);readTable();}
}void readUse(){string type;cin>>type;databaseName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);databaseName+=s;c=getchar();}databaseName=trimTrailingSpaces(databaseName);
}
2.2 Create Tables
即新建csv文件。为了方便后续condition的处理,我在csv文件第一行存储了数据类型,第二行存储的列名称。
void createTable(const string& databaseName,const string& tableName,const vector<pair<string,string>>& columns){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath);for(size_t i=0;i<columns.size();++i){file<<columns[i].second;if(i<columns.size()-1){file<<",";}}file<<endl;for(size_t i=0;i<columns.size();++i){file<<columns[i].first;if(i<columns.size()-1){file<<",";}}file<<endl;file.close();
}void readTable(){vector<pair<string,string>> parsedColumns;char c;string s;while(c!=')'){string columnName="";string typeName="";string name="";int i=0;c=getchar();while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=','&&c!=')'){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'){s.assign(1,c);columnName+=s;++i;}c=getchar();}i--;int j=0;while(columnName[i--]==' ');while(columnName[i-j]!=' '){j++;}typeName.assign(columnName.substr(i-j+1,j+1));name.assign(columnName.substr(0,i-j));parsedColumns.emplace_back(name,typeName);if(c!=')'){c=getchar();}}while(c!=';'){c=getchar();}createTable(databaseName,tableName,parsedColumns);
}
2.3 Drop Tables
即删除csv文件。
void dropTable(const string& databaseName,const string& tableName){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;remove(filePath.c_str());
}void readDrop(){string type;cin>>type;tableName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!=';'){s.assign(1,c);tableName+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);dropTable(databaseName,tableName);
}
2.4 Data Insertion
即向csv文件中添加数据。
void dataInsert(const string& databaseName,const string& tableName,const vector<string>& values){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath,ios::out|ios::app);for(size_t i=0;i<values.size();++i){file<<values[i];if(i<values.size()-1){file<<",";}}file<<endl;file.close();
}void readValue(){vector<string> values;char c;string s;while(c!=')'){string value="";int i=0;c=getchar();while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!=','&&c!=')'){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'&&c!=0){s.assign(1,c);value+=s;++i;}c=getchar();}value=trimTrailingSpaces(value);values.emplace_back(value);}while(c!=';'){c=getchar();}dataInsert(databaseName,tableName,values);
}void readInsert(){char c;string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}tableName="";string name="";int i=0;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!='('){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'){s.assign(1,c);tableName+=s;i++;}c=getchar();}i--;while(tableName[i--]==' ');while(tableName[i--]!=' ');name.assign(tableName.substr(0,i+1));tableName.assign(name);readValue();
}
2.5 Data Query: Basic
即输出数据。其实要先从csv文件中读入数据筛选后输出。这里要注意输出格式(有无,
及---
)和输出位置(output.txt
)。
vector<vector<string>> readCSV(const string& databaseName,const string& tableName){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;vector<vector<string>> data;ifstream file(filePath);string line;while(getline(file,line)){vector<string> row;stringstream lineStream(line);string cell;while(getline(lineStream,cell,',')){row.push_back(cell);}data.push_back(row);}file.close();return data;
}void dataPrint(const vector<vector<string>>& data){string filePath="output.txt";ofstream file(filePath,ios::out|ios::app);if(cnt){file<<"---"<<endl;}for(const auto& row:data){file<<row[0];for(int i=1;i<row.size();++i){file<<","<<row[i];}file<<endl;}file.close();
}void readSelect(){string columns;string s;vector<string> column;cin>>s;while(s!="FROM"){columns+=s;cin>>s;}int len=columns.length();for(int i=0,j=0;i<len;){s="";while(columns[i]!=','&&i<len){++i;}s.assign(columns.substr(j,i-j));j=++i;column.emplace_back(s);}char c;c=getchar();columns="";//临时储存字符串 tableName="";while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);if(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){if(columns==" WHERE"){readSelectWhere(column);return;}else if(columns==" INNER"){readInner(column);return;}s=" ";tableName+=columns;columns="";}columns+=s;c=getchar();}tableName+=columns;auto data=readCSV(databaseName,tableName);vector<vector<string>> result;if(column[0]=="*"){for(int i=1;i<data.size();++i){result.emplace_back(data[i]);}dataPrint(result);return;}vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& columnName:column){if(columnName==data[1][i]){w.emplace_back(i);break;}}}for(size_t i=1;i<data.size();++i){vector<string> row;for(const auto& j:w){row.emplace_back(data[i][j]);}result.emplace_back(row);}dataPrint(result);
}
2.6 Data Query: “Where” Clause
同上。
void dataOperateAnd(const vector<string>& columns,const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> wc;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(columns);for(int i=0;i<data[1].size();++i){for(const auto& column:columns){if(column==data[1][i]){wc.emplace_back(i);break;}}}for(int i=2;i<data.size();++i){bool suit=1;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else{if(op[j]==1){if(data[i][w[j]]!=values[j]){suit=0;break;}}else if(op[j]==2){if(data[i][w[j]]==values[j]){suit=0;break;}}}}if(suit){vector<string> row;for(int j=0;j<wc.size();++j){row.emplace_back(data[i][wc[j]]);}result.emplace_back(row);}}dataPrint(result);
}void dataOperateOr(const vector<string>& columns,const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> wc;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(columns);for(int i=0;i<data[1].size();++i){for(const auto& column:columns){if(column==data[1][i]){wc.emplace_back(i);break;}}}for(int i=2;i<data.size();++i){bool suit=0;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else{if(op[j]==1){if(data[i][w[j]]==values[j]){suit=1;break;}}else if(op[j]==2){if(data[i][w[j]]!=values[j]){suit=1;break;}}}}if(suit){vector<string> row;for(int j=0;j<wc.size();++j){row.emplace_back(data[i][wc[j]]);}result.emplace_back(row);}}dataPrint(result);
}void readSelectWhere(vector<string> column){char c=getchar();vector<string> columnName;vector<int> op;//1= 2!= 3> 4<vector<string> value;string s,str="",strin="";//临时存放 bool a;//1and 0orwhile(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){str="";while(c!='='&&c!='!'&&c!='<'&&c!='>'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;c=getchar();}//读入columnName str=trimTrailingSpaces(str);columnName.emplace_back(str);if(c=='='){op.emplace_back(1);}else if(c=='!'){op.emplace_back(2);c=getchar();}else if(c=='<'){op.emplace_back(3);}else{op.emplace_back(4);}//读入op c=getchar();while(c==' '){c=getchar();}str="";while(c!=';'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;if(c==' '){if(str=="AND "){a=1;break;}else if(str=="OR "){a=0;break;}strin+=str;str="";}if(c==';'){break;}c=getchar();} strin+=str;value.emplace_back(trimTrailingSpaces(strin));if(c==';'){break;}c=getchar();}if(a){dataOperateAnd(column,columnName,op,value);}else{dataOperateOr(column,columnName,op,value);}
}
2.7 Data Query: “Inner Join” Clause
未完成。
void readInner(vector<string> column){}
2.8 Data Update
未完成。
void readUpdateWhere(){}void readUpdate(){}
2.9 Data Deletion
即清空数据。我用的是重新输出数据类型和列名称覆盖原文件的方式。
void filePrint(const string& databaseName,const string& tableName,const vector<vector<string>>& data){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath);for(size_t i=0;i<data.size();++i){for(size_t j=0;j<data[i].size();++j){file<<data[i][j];if(j<data[i].size()-1){file<<",";}}file<<endl;}file.close();
}void fileOperateAnd(const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(data[0]);result.emplace_back(data[1]);for(int i=2;i<data.size();++i){bool suit=1;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else{if(op[j]==1){if(data[i][w[j]]!=values[j]){suit=0;break;}}else if(op[j]==2){if(data[i][w[j]]==values[j]){suit=0;break;}}}}if(suit){result.emplace_back(data[i]);}}filePrint(databaseName,tableName,result);
}void fileOperateOr(const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(data[0]);result.emplace_back(data[1]);for(int i=2;i<data.size();++i){bool suit=0;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else{if(op[j]==1){if(data[i][w[j]]==values[j]){suit=1;break;}}else if(op[j]==2){if(data[i][w[j]]!=values[j]){suit=1;break;}}}}if(suit){result.emplace_back(data[i]);}}filePrint(databaseName,tableName,result);
}void readDeleteWhere(){char c=getchar();vector<string> columnName;vector<int> op;//1= 2!= 3> 4<vector<string> value;string s,str="",strin="";//临时存放 bool a;//1and 0orwhile(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){str="";while(c!='='&&c!='!'&&c!='<'&&c!='>'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;c=getchar();
// cout<<1<<endl;}//读入columnName str=trimTrailingSpaces(str);columnName.emplace_back(str);if(c=='='){op.emplace_back(1);}else if(c=='!'){op.emplace_back(2);c=getchar();}else if(c=='<'){op.emplace_back(3);}else{op.emplace_back(4);}//读入op c=getchar();while(c==' '){c=getchar();}str="";while(c!=';'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;if(c==' '){if(str=="AND "){a=1;break;}else if(str=="OR "){a=0;break;}strin+=str;str="";}if(c==';'){break;}c=getchar();} strin+=str;value.emplace_back(trimTrailingSpaces(strin));if(c==';'){break;}c=getchar();}if(a){fileOperateAnd(columnName,op,value);}else{fileOperateOr(columnName,op,value);}
}void readDelete(){char c=getchar();string s,str;tableName="";while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);if(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){if(str==" WHERE"){break;}s=" ";tableName+=str;str="";}str+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);if(c==';'){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;result.emplace_back(data[0]);result.emplace_back(data[1]);filePrint(databaseName,tableName,result);return;}readDeleteWhere();
}
代码实现
以下是最终未完成的完整版代码。
//minidb
#include<bits/stdc++.h>
#include<sys/stat.h>
using namespace std;
string databaseName;
string tableName;
int cnt;string trimTrailingSpaces(const string& str){size_t end=str.find_last_not_of(" \t\n\r\f\v\0");if(end!=string::npos){return str.substr(0,end+1);}return "";
}vector<vector<string>> readCSV(const string& databaseName,const string& tableName){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;vector<vector<string>> data;ifstream file(filePath);string line;while(getline(file,line)){vector<string> row;stringstream lineStream(line);string cell;while(getline(lineStream,cell,',')){row.push_back(cell);}data.push_back(row);}file.close();return data;
}void createDatabase(const string& databaseName){string path=databaseName;mkdir(path.c_str());
}void createTable(const string& databaseName,const string& tableName,const vector<pair<string,string>>& columns){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath);for(size_t i=0;i<columns.size();++i){file<<columns[i].second;if(i<columns.size()-1){file<<",";}}file<<endl;for(size_t i=0;i<columns.size();++i){file<<columns[i].first;if(i<columns.size()-1){file<<",";}}file<<endl;file.close();
}void dropTable(const string& databaseName,const string& tableName){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;remove(filePath.c_str());
}void dataInsert(const string& databaseName,const string& tableName,const vector<string>& values){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath,ios::out|ios::app);for(size_t i=0;i<values.size();++i){file<<values[i];if(i<values.size()-1){file<<",";}}file<<endl;file.close();
}void dataPrint(const vector<vector<string>>& data){string filePath="output.txt";ofstream file(filePath,ios::out|ios::app);if(cnt){file<<"---"<<endl;}for(const auto& row:data){file<<row[0];for(int i=1;i<row.size();++i){file<<","<<row[i];}file<<endl;}file.close();
}void dataOperateAnd(const vector<string>& columns,const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> wc;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(columns);for(int i=0;i<data[1].size();++i){for(const auto& column:columns){if(column==data[1][i]){wc.emplace_back(i);break;}}}for(int i=2;i<data.size();++i){bool suit=1;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else{if(op[j]==1){if(data[i][w[j]]!=values[j]){suit=0;break;}}else if(op[j]==2){if(data[i][w[j]]==values[j]){suit=0;break;}}}}if(suit){vector<string> row;for(int j=0;j<wc.size();++j){row.emplace_back(data[i][wc[j]]);}result.emplace_back(row);}}dataPrint(result);
}void dataOperateOr(const vector<string>& columns,const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> wc;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(columns);for(int i=0;i<data[1].size();++i){for(const auto& column:columns){if(column==data[1][i]){wc.emplace_back(i);break;}}}for(int i=2;i<data.size();++i){bool suit=0;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else{if(op[j]==1){if(data[i][w[j]]==values[j]){suit=1;break;}}else if(op[j]==2){if(data[i][w[j]]!=values[j]){suit=1;break;}}}}if(suit){vector<string> row;for(int j=0;j<wc.size();++j){row.emplace_back(data[i][wc[j]]);}result.emplace_back(row);}}dataPrint(result);
}void filePrint(const string& databaseName,const string& tableName,const vector<vector<string>>& data){string a="/";string b=".csv";string filePath=databaseName+a+tableName+b;ofstream file(filePath);for(size_t i=0;i<data.size();++i){for(size_t j=0;j<data[i].size();++j){file<<data[i][j];if(j<data[i].size()-1){file<<",";}}file<<endl;}file.close();
}void fileOperateAnd(const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(data[0]);result.emplace_back(data[1]);for(int i=2;i<data.size();++i){bool suit=1;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1!=value2){suit=0;break;}}else if(op[j]==2){if(value1==value2){suit=0;break;}}else if(op[j]==3){if(value1>=value2){suit=0;break;}}else{if(value1<=value2){suit=0;break;}}}else{if(op[j]==1){if(data[i][w[j]]!=values[j]){suit=0;break;}}else if(op[j]==2){if(data[i][w[j]]==values[j]){suit=0;break;}}}}if(suit){result.emplace_back(data[i]);}}filePrint(databaseName,tableName,result);
}void fileOperateOr(const vector<string>& columnName,const vector<int>& op,const vector<string>& values){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& column:columnName){if(column==data[1][i]){w.emplace_back(i);break;}}}result.emplace_back(data[0]);result.emplace_back(data[1]);for(int i=2;i<data.size();++i){bool suit=0;for(int j=0;j<op.size();++j){if(data[0][w[j]]=="INTEGER"){int value1=stoi(data[i][w[j]]);int value2=stoi(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else if(data[0][w[j]]=="FLOAT"){float value1=stof(data[i][w[j]]);float value2=stof(values[j]);if(op[j]==1){if(value1==value2){suit=1;break;}}else if(op[j]==2){if(value1!=value2){suit=1;break;}}else if(op[j]==3){if(value1<value2){suit=1;break;}}else{if(value1>value2){suit=1;break;}}}else{if(op[j]==1){if(data[i][w[j]]==values[j]){suit=1;break;}}else if(op[j]==2){if(data[i][w[j]]!=values[j]){suit=1;break;}}}}if(suit){result.emplace_back(data[i]);}}filePrint(databaseName,tableName,result);
}//read
void readTable(){vector<pair<string,string>> parsedColumns;char c;string s;while(c!=')'){string columnName="";string typeName="";string name="";int i=0;c=getchar();while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=','&&c!=')'){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'){s.assign(1,c);columnName+=s;++i;}c=getchar();}i--;int j=0;while(columnName[i--]==' ');while(columnName[i-j]!=' '){j++;}typeName.assign(columnName.substr(i-j+1,j+1));name.assign(columnName.substr(0,i-j));parsedColumns.emplace_back(name,typeName);if(c!=')'){c=getchar();}}while(c!=';'){c=getchar();}createTable(databaseName,tableName,parsedColumns);
}void readCreate(){string type;cin>>type;if(type=="DATABASE"){databaseName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);databaseName+=s;c=getchar();}databaseName=trimTrailingSpaces(databaseName);createDatabase(databaseName);}else if(type=="TABLE"){tableName="";int i=0;char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!='('){s.assign(1,c);tableName+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);readTable();}
}void readUse(){string type;cin>>type;databaseName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);databaseName+=s;c=getchar();}databaseName=trimTrailingSpaces(databaseName);
}void readDrop(){string type;cin>>type;tableName="";char c=getchar();string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!=';'){s.assign(1,c);tableName+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);dropTable(databaseName,tableName);
}void readValue(){vector<string> values;char c;string s;while(c!=')'){string value="";int i=0;c=getchar();while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!=','&&c!=')'){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'&&c!=0){s.assign(1,c);value+=s;++i;}c=getchar();}value=trimTrailingSpaces(value);values.emplace_back(value);}while(c!=';'){c=getchar();}dataInsert(databaseName,tableName,values);
}void readInsert(){char c;string s;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}tableName="";string name="";int i=0;while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||c=='\0'){c=getchar();}while(c!='('){if(c!='\t'&&c!='\n'&&c!='\r'&&c!='\f'&&c!='\v'){s.assign(1,c);tableName+=s;i++;}c=getchar();}i--;while(tableName[i--]==' ');while(tableName[i--]!=' ');name.assign(tableName.substr(0,i+1));tableName.assign(name);readValue();
}void readSelectWhere(vector<string> column){char c=getchar();vector<string> columnName;vector<int> op;//1= 2!= 3> 4<vector<string> value;string s,str="",strin="";//临时存放 bool a;//1and 0orwhile(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){str="";while(c!='='&&c!='!'&&c!='<'&&c!='>'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;c=getchar();}//读入columnName str=trimTrailingSpaces(str);columnName.emplace_back(str);if(c=='='){op.emplace_back(1);}else if(c=='!'){op.emplace_back(2);c=getchar();}else if(c=='<'){op.emplace_back(3);}else{op.emplace_back(4);}//读入op c=getchar();while(c==' '){c=getchar();}str="";while(c!=';'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;if(c==' '){if(str=="AND "){a=1;break;}else if(str=="OR "){a=0;break;}strin+=str;str="";}if(c==';'){break;}c=getchar();} strin+=str;value.emplace_back(trimTrailingSpaces(strin));if(c==';'){break;}c=getchar();}if(a){dataOperateAnd(column,columnName,op,value);}else{dataOperateOr(column,columnName,op,value);}
}void readInner(vector<string> column){}void readSelect(){string columns;string s;vector<string> column;cin>>s;while(s!="FROM"){columns+=s;cin>>s;}int len=columns.length();for(int i=0,j=0;i<len;){s="";while(columns[i]!=','&&i<len){++i;}s.assign(columns.substr(j,i-j));j=++i;column.emplace_back(s);}char c;c=getchar();columns="";//临时储存字符串 tableName="";while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);if(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){if(columns==" WHERE"){readSelectWhere(column);return;}else if(columns==" INNER"){readInner(column);return;}s=" ";tableName+=columns;columns="";}columns+=s;c=getchar();}tableName+=columns;auto data=readCSV(databaseName,tableName);vector<vector<string>> result;if(column[0]=="*"){for(int i=1;i<data.size();++i){result.emplace_back(data[i]);}dataPrint(result);return;}vector<int> w;for(int i=0;i<data[1].size();++i){for(const auto& columnName:column){if(columnName==data[1][i]){w.emplace_back(i);break;}}}for(size_t i=1;i<data.size();++i){vector<string> row;for(const auto& j:w){row.emplace_back(data[i][j]);}result.emplace_back(row);}dataPrint(result);
}void readUpdateWhere(){}void readUpdate(){}void readDeleteWhere(){char c=getchar();vector<string> columnName;vector<int> op;//1= 2!= 3> 4<vector<string> value;string s,str="",strin="";//临时存放 bool a;//1and 0orwhile(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){str="";while(c!='='&&c!='!'&&c!='<'&&c!='>'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;c=getchar();
// cout<<1<<endl;}//读入columnName str=trimTrailingSpaces(str);columnName.emplace_back(str);if(c=='='){op.emplace_back(1);}else if(c=='!'){op.emplace_back(2);c=getchar();}else if(c=='<'){op.emplace_back(3);}else{op.emplace_back(4);}//读入op c=getchar();while(c==' '){c=getchar();}str="";while(c!=';'){if(c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=' ';}s.assign(1,c);str+=s;if(c==' '){if(str=="AND "){a=1;break;}else if(str=="OR "){a=0;break;}strin+=str;str="";}if(c==';'){break;}c=getchar();} strin+=str;value.emplace_back(trimTrailingSpaces(strin));if(c==';'){break;}c=getchar();}if(a){fileOperateAnd(columnName,op,value);}else{fileOperateOr(columnName,op,value);}
}void readDelete(){char c=getchar();string s,str;tableName="";while(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){c=getchar();}while(c!=';'){s.assign(1,c);if(c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'){if(str==" WHERE"){break;}s=" ";tableName+=str;str="";}str+=s;c=getchar();}tableName=trimTrailingSpaces(tableName);if(c==';'){auto data=readCSV(databaseName,tableName);vector<vector<string>> result;result.emplace_back(data[0]);result.emplace_back(data[1]);filePrint(databaseName,tableName,result);return;}readDeleteWhere();
}void readCommand(){string command;while(cin>>command){if(command=="CREATE"){readCreate();}else if(command=="USE"){readUse();}else if(command=="DROP"){readDrop();}else if(command=="INSERT"){cin>>command;readInsert();}else if(command=="SELECT"){readSelect();++cnt;}else if(command=="UPDATE"){readUpdate();}else if(command=="DELETE"){cin>>command;readDelete();}}
}int main(){freopen("input.sql","r",stdin);readCommand();return 0;
}