代码拉取完成,页面将自动刷新
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//初始化treeview
ini_tree();
// QString s = "wangwen = '123'";
// QStringList p = s.split("and");
// for (QString x : p) {
// qDebug() << x << "\n";
// }
// QChar c = '\'';
// qDebug() << c;
/* 树widge
//信号:
itemClicked(QTreeWidgetItem *item, int column)
//实现:
qDebug()<<item->text(column);*/
setWindowTitle("TempSQL");
setWindowIcon(QIcon(":/images/source/appicon.png"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ini_tree() {
//将所有的数据库列表读取到树状图中
QStandardItemModel *model = new QStandardItemModel(this);//构建模型
ui->treeView->header()->setSectionResizeMode(QHeaderView::Stretch);
model->setHorizontalHeaderLabels(QStringList(QStringLiteral("数据库")));//设置头部文件
ui->treeView->setModel(model);
ui->treeView->expandAll();//设置为展开
ui->treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置节点不可编辑
//此处读取所有数据库名字
vector<QString> databases;
QFile database_file(types::current_path + "ban.csv");
QTextStream database_stream(&database_file);
if (!database_file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the ban.csv!";
return;
}
database_file.seek(0);
while (!database_stream.atEnd()) {
QString cur = database_stream.readLine();
databases.push_back(cur);
}
//读取对应数据库名字中的表的名字
vector<vector<QString>> tables;
for (QString database : databases) {
vector<QString> temp;//暂存当前数据库的表名
QFile table_file(types::current_path + database + "/tables.csv");
QTextStream table_stream(&table_file);
if (!table_file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!";
return;
}
table_file.seek(0);
while (!table_stream.atEnd()) {
QString cur = table_stream.readLine();
temp.push_back(cur);
}
tables.push_back(temp);
}
for (int i = 0; i < databases.size(); ++i) {
QStandardItem *item_database = new QStandardItem(databases[i]);//创建根目录,即数据库
//D:\Qt\qDBMS-3\dmbs-8\dbms_2
item_database->setIcon(QIcon(":/images/source/database.jpg"));//注意相对路劲
// item_database->setIcon(QIcon("D:/Qt/qDBMS-3/dbms-4/dbms_2/source/database.jpg"));//注意相对路劲
model->appendRow(item_database);
for (int j = 0; j < tables[i].size(); ++j) {
QStandardItem *item_table = new QStandardItem(tables[i][j]);
item_table->setIcon(QIcon(":/images/source/table.jpg"));//"D:/Qt/qDBMS-3/dmbs-8/dbms_2/database.jpg"
// item_table->setIcon(QIcon("D:/Qt/qDBMS-3/dbms-4/dbms_2/source/table.jpg"));
item_database->appendRow(item_table);
}
}
}
void MainWindow::get_created_stm(QString s) {
s = s.toLower();
created_parser(s, true);//调用创建表
}
void MainWindow::on_toolButton_2_clicked()
{
create_db_widge = new CreateDB();//点击创建表之后实现弹出窗口
connect(create_db_widge, SIGNAL(send_created_stm(QString)), this, SLOT(get_created_stm(QString)));
create_db_widge->show();//展示创建表的新式
}
bool MainWindow::inserted_parser(QString s){
// insert into 表名(可选) values(值)
QRegExp *ex=new QRegExp("(insert)\\s+(into)\\s\\w+((\((\\w*,)*(\\w*)\\)))?\\s*"
"values\(('\\w*',|\\w*,)*('\\w*'|\\w*)\\)\\;$");
ex->setPattern("insert\\s+into\\s+(\\w+)(\\(((\\w*,)*(\\w*))\\))?\\s*(values)\\s*\\((( ('.*',)|(.*,) )*('.'|.*))\\)\\;$");
if (!ex->exactMatch(s)) {// (\\w+)表名
QMessageBox::warning(this, "警告", "插入语法错误!");
return false;
}//1是表名,2是列名们,7是值们
QFile file(types::current_path + current_database + "/tables.csv");
//换成自己的路径!! 运行程序时不要打开文件!!
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
//打开不成功
qDebug() << "fail to open the tables.csv!\n";
return false;
}
QString tname=ex->cap(1);//第一个是表名
QString attri=ex->cap(2);//第二个是属性们(可能是空)(sno,cno,grade,fll)
attri.remove(QRegExp("\\s"));
QString values=ex->cap(7);//第七个是值们 而且有逗号(11,111,566)
qDebug()<<"attri="<<attri<<" values="<<values;
//找数据库有没有这个表
file.seek(0);
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == tname) {
qDebug() << "succeed to find the table!\n"+tname;
}
}
//找到tablec存的表名,则表存在
file.close();//留着没啥用了,关了吧
//找表中的 元数据metadata并且存入 colinfo
QFile mfile(types::current_path + current_database + "/" +tname+"/type.csv");
if (!mfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the type.csv!\n";
return false;
}
map<int, pair<QString, QString>> colinfo;
QTextStream * read = new QTextStream(&mfile);
QStringList Data = read->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
Data[0].remove(QRegExp("\\s"));
Data[1].remove(QRegExp("\\s"));
QStringList strLine1 = Data.at(0).split(",");//获取每行信息 第一行是列名 第二行是属性 Data[0] "id,name"
QStringList strLine2 = Data.at(1).split(",");//第二行是对应的类型 一行中的单元格以,区分 Data[1] "int,varchar(8)"
//列号 起始为0!!!!!!!!
for(int i=0;i<strLine1.length();i++){//把列的信息存进map<列号,pair<列名,类型>>里面
//colinfo.insert(i,pair<QString,QString>(strLine.at(i),"ss"));
if(strLine1.at(i)!="")
colinfo.insert(pair<int, pair<QString, QString>>(i,pair<QString, QString>(strLine1.at(i),strLine2.at(i))));
}
qDebug()<<"strlength=="<<strLine1.length()<<"map colinfo="<<colinfo.size();//打印出每行的第一个单元格的数据
mfile.close();
int colnum=strLine1.length();
//qDebug()<<strLine1;
//std::cout<<"strline1.1=["<<strLine1.at(0).toStdString()<<"]["<<strLine1.at(1).toStdString()<<endl;
qDebug()<<"col=="<<colnum;
map<int, pair<QString, QString>>::iterator it;
for (it= colinfo.begin();it!=colinfo.end();it++){
qDebug()<<"map: "<<it->first<<" "<<it->second.first<<" "<<it->second.second;
}
QFile tfile(types::current_path + current_database + "/" +tname+"/user.csv");
if(!tfile.open(QIODevice::Append)){//追加写
qDebug()<<" Fail to open the data.csv!\n";
}
//tfile.seek(0);
QTextStream out(&tfile);//写出
bool hasFor=0;
vector<vector<QString>> foreignKeys;//可能有多个主键, 内层容量为3,约束名、参照列、被参照表、被参照列
QFile Foreignfile(types::current_path + current_database + "/" +tname+"/foreign_key.csv");
if (!Foreignfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the foreign_key.csv!\n";
return false;
}
QTextStream * forread = new QTextStream(&Foreignfile);
QStringList forData = forread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//forData.removeAll(QRegExp("\\s"));
QString firstData = forread->readLine();
qDebug()<<"外键文件 firstData"<<firstData;
if(forData.size()==0){
qDebug()<<"11外键为空";hasFor=0;/*else if(firstData==""){
qDebug()<<"22外键为空";hasFor=0;
}*/
}else{
qDebug()<<"外键非空";hasFor=1;
vector<QString> fk;
qDebug()<<"forData.size()="<<forData.size();
for(int i=0;i<forData.size();i++){
forData[i].remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList forConLine = forData[i].split(",");
fk.erase(fk.begin(),fk.end());
for(int j=1;j<=3;j++){
fk.push_back(forConLine.at(j));
//存每一个外键:参照列、被参照表、被参照列
}
foreignKeys.push_back(fk);
}
qDebug()<<"外键约束foreignkeys="<<foreignKeys;
}
//检查主键
bool hasPri=0;
QFile primaryfile(types::current_path + current_database + "/" +tname+"/primary_key.csv");
if (!primaryfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the primary_key.csv!\n";
return false;
}
vector<vector<QString>> pri;//存主键对应的userdata
QTextStream * priread = new QTextStream(&primaryfile);
//QStringList priData = priread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString priData = priread->readLine();
vector<QString> pricolName;//存复合主键的每个列名
if(priData.size()==0){
qDebug()<<"主键为空";hasPri=0;
}else{
hasPri=1;
qDebug()<<"主键非空";
QString colN = priData;// 存第一行,即复合主键[0]
qDebug()<<"主键属性 ["<<colN<<"]";
//colN.remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList priColName = colN.split(",");//获取每行信息 第一行是列名 第二行是属性
for(int i=1;i<priColName.length();i++){//下标0存的约束名,不管
pricolName.push_back(priColName.at(i));
}
qDebug()<<"主键"<<pricolName;
//将主键的userdata数据写入vector<vector<QString>> pri;
QFile userfile(types::current_path + current_database + "/" +tname+"/user.csv");
if (!userfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the user.csv!\n";
return false;
}
//vector<vector<QString>> pri;//存主键 striLine1里面存了列
QTextStream * userread = new QTextStream(&userfile);
QStringList userData = userread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
if(userData.size()!=0){
for(int i=0;i<userData.length();i++){//外层遍历userdata
userData[i].remove(QRegExp("\\s"));
vector<QString> useritem;
useritem.erase(useritem.begin(),useritem.end());// 清空
QStringList singleitem = userData[i].split(",");//userdata的一行
for(int j=0;j<pricolName.size();j++){//内层遍历主键
int pos= strLine1.indexOf(pricolName[j]);//找到第j个主键的下标
useritem.push_back(singleitem.at(pos));
}//qDebug()<<"内层循环"<<useritem;
pri.push_back(useritem);// 写入二维数组
}
qDebug()<<" 外层 "<<pri;
}
userfile.close();
primaryfile.close();
}
QStringList list;//存列名们 是个list
if(attri!=NULL){
attri.remove(QChar('('), Qt::CaseInsensitive);
attri.remove(QChar(')'), Qt::CaseInsensitive);
}
//写入过程
if (attri==NULL){
//没指定列,转换为指定列处理
//attri=strLine1;
for(int i=0;i<strLine1.size()-1;i++){
attri.append(strLine1[i]+",");
}
attri.append(strLine1[strLine1.size()-1]);
/*
QStringList userdata = values.split(",");
if(userdata.length()!= strLine1.length()){
// 有可能会+1,因为csv最后一个读的空,但是colinfo不会,因为我去空了hhh colinfo.size()
qDebug()<<"输入数据个数错误 userdata.length()="<<userdata.length()<<" strLine1.length()="<<strLine1.length();
return;
}
//没有指定列,直接全插入
//to do 检查一下类型匹配问题
int flag=1;//如果flag为真,则完全匹配
for(int i=0;i<colnum;i++){
if(!checkMatch(colinfo.at(i).second,userdata[i]))
flag=0;
}
if(flag==0){
qDebug()<<"输入数据类型错误";
return;
}else{
QStringList invalues = values.split(",");//待插入数据
//检查 主键
if(hasPri!=0){
qDebug()<<"进入比较主键";
//pri存的userdata比较
vector<QString> inserted_pridata;
qDebug()<<" user pri: "<<pri;
qDebug()<<" pri.size()= "<<pri.size()<<" pricolName.size()="<<pricolName.size();
for(int j=0;j<pricolName.size();j++){//内层遍历主键
int pos= strLine1.indexOf(pricolName[j]);//找到第j个主键的下标
//useritem.push_back(singleitem.at(pos));
inserted_pridata.push_back(invalues[pos]);
}
qDebug()<<"待插入数据中涉及主键:"<<inserted_pridata;
int same=0;
for(int i=0;i<pri.size();i++){//外层遍历userdata
same=0;
for(int j=0;j<pricolName.size();j++){
//qDebug()<<"比较:pri[i].at(j)="<<pri[i].at(j)<<"inserted_pridata[j]="<<inserted_pridata[j];
if(pri[i].at(j)==inserted_pridata[j]){
//主键中的某一个相同
same++;
}
}
if(same==pricolName.size()){
//全部重复,即主键有重合
qDebug()<<"完蛋,主键有重复";
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(主键)");
return;
}
}
}
// 匹配类型完成,写入数据
qDebug()<<invalues<<" 不指定列名,数量 ivalues.size="<<invalues.length();
for(int i=0;i<invalues.length();i++){
if(invalues[i][0]=="'" && invalues[i][invalues[i].length()-1]=="'"){
invalues[i].remove(0,1);
invalues[i].remove(invalues[i].length()-1,1);
//如果某个人值前后都是单引号,那把单引号删除
}
}
values=invalues.join(",");
qDebug()<<"写入的数据:"<<values;
out<<values<<endl;
}
qDebug()<<values<<endl;
qDebug()<<"*没指定列,全部插入\n";
*/
}
qDebug()<<"attri="<<attri;
if(attri!=NULL){
//指定了列attri=attri.left(attri.size()-1);
qDebug()<<"列名们"<<attri;
list = attri.split(",");//这里是列名
/*for(int i=0;i<list.length();i++){
qDebug()<<"列名:"<<list[i];
}*/
QStringList userdata = values.split(",");//这里是插入的数值
if(list.length()!=userdata.length()){
QMessageBox::warning(this, "警告", "数量不匹配");
qDebug()<<"数量不匹配";
return false;
}// list要插入的列,userdata要插入的数据,strLine1存所有列名,priColName存主键的列名
int vnum=list.length();//插入元素个数
qDebug()<<"插入元素个数="<<vnum;//找到之后,进入 该名字的文件夹,看看有没有data.csv
int flag=1;//如果flag为真,则完全匹配
for(int i=0;i<vnum;i++){
//获取第i列在基表中对应的位置
//qDebug()<<"list at(i)="<<list.at(i);
//qDebug()<<"strLine1="<<strLine1.at(0)<<strLine1.at(1);
int pos = strLine1.indexOf(list.at(i));
if(pos==-1){
QMessageBox::warning(this, "警告", "输入列名有误!");
qDebug()<<"输入列名有误!";
return false;
}
if(!checkMatch(strLine2.at(pos),userdata.at(i)))
flag=0;
}
if(flag==0){
QMessageBox::warning(this, "警告", "输入数据类型错误");
qDebug()<<"输入数据类型错误";
return false;
}else{
qDebug()<<"匹配完成,可以插入";
//检查notnull
QFile constraintfile(types::current_path + current_database + "/" +tname+"/constraint.csv");
if (!constraintfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the constraint.csv!\n";
return false;
}
constraintfile.seek(0);
QTextStream * conread = new QTextStream(&constraintfile);
QStringList ConData = conread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString condataline = conread->readLine();
/*if(condataline==""){
qDebug()<<"无约束";
}else{
}*/
ConData[0].remove(QRegExp("\\s"));
QStringList ConCollist = ConData.at(0).split(",");//约束限制,null/notnull
qDebug()<<"null约束="<<ConCollist;
//检查notnull的是否被插入数据
for(int i=0;i<ConCollist.length();i++){
if(ConCollist.at(i)=="notnull"){
//寻找这是哪个列
int findit = list.indexOf(strLine1[i]);
if(findit==-1){
//这个列为notnull,但是没插入数据
QMessageBox::warning(this, "警告", "违反约束!(NOT NULL)");
return false;
}else if(userdata[findit]=="null"){
QMessageBox::warning(this, "警告", "违反约束!(NOT NULL)");
}
}
}
constraintfile.close();
//检查notnull over
// 指定列的 检查主键
if(hasPri!=0){
//vector<vector<QString>> pri;//存主键对应的userdata
//vector<QString> inserted_pridata;
qDebug()<<"进入比较主键";
for(int i=0;i<pricolName.size();i++){
if(list.indexOf(pricolName[i])==-1){
//没插入主键
qDebug()<<"完蛋,没插入主键啊xd";
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(未写入主键数据)");
return false;
}else if(userdata[list.indexOf(pricolName[i])]=="null"){
//指定的列有,但是插入的是null,还tm是主键,直接拒绝
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(主键不能为null)");
return false;
}
}
vector<QString> inserted_pridata_appointed;
inserted_pridata_appointed.erase(inserted_pridata_appointed.begin(),inserted_pridata_appointed.end());
qDebug()<<" user pri: "<<pri;
qDebug()<<" pri.size()= "<<pri.size();
qDebug()<<" pricolName.size()="<<pricolName.size();
// 把带插入的数据的主键信息存入inserted_pridata_appointed
// list要插入的列,userdata要插入的数据,strLine1存所有列名,priColName存主键的列名
for(int j=0;j<pricolName.size();j++){//内层遍历主键
int pos= list.indexOf(pricolName[j]);//找到第j个主键的下标
inserted_pridata_appointed.push_back(userdata[pos]);
}
qDebug()<<"带插入数据中 涉及主键:"<<inserted_pridata_appointed;
qDebug()<<"pir="<<pri;
qDebug()<<"pricolName.size()="<<pricolName.size();
int same=0;
for(int i=0;i<pri.size();i++){//外层遍历userdata
same=0;
//qDebug()<<"进入外循环";
for(int j=0;j<pricolName.size();j++){
//qDebug()<<" 进入nei循环";
//qDebug()<<"比较:pri[i].at(j)="<<pri[i].at(j)<<"inserted_pridata[j]="<<inserted_pridata[j];
inserted_pridata_appointed[j].remove("'");
if(pri[i].at(j)==inserted_pridata_appointed[j]){
//主键中的某一个相同
same++;
}
}
if(same==pricolName.size()){
//全部重复,即主键有重合
qDebug()<<"完蛋,主键有重复";
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(主键)");
tfile.close();
return false;
}
}qDebug()<<"for结束";
}
//检查主键over
//检查外键
if(hasFor!=0){
//有外键
int allowinsert = 1;
//循环看外键是否符合
for(int i=0;i<foreignKeys.size();i++){
//检查每一个外键 ForeignKeys:参照列、被参照表、被参照列
int insertedForeiIndex=-1;//在 待插入数据里外键的index
insertedForeiIndex= list.indexOf(foreignKeys[i].at(0));
if(insertedForeiIndex==-1){
return false;
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束( 未写入外键数据)");
}
//foreignKeys[i].at(1);//QString insertedvalue,QString referedtable,QString referedCol
if(!CheckForeignKey(userdata[insertedForeiIndex],foreignKeys[i].at(1),foreignKeys[i].at(2))){
allowinsert=0;
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(外键找不到参照)");
tfile.close();
return false;
}
}
}
//检查外键over
QStringList insert_values[colinfo.size()];//strLine1.length()strLine1.length()
for(int i =0;i<colinfo.size();i++){//strLine1.length()-1;
insert_values->append("null");
}
for(int i=0;i<vnum;i++){
//获取第i列在基表中对应的位置
int pos = strLine1.indexOf(list.at(i));//列名对应的位置
if(userdata[i][0]=="'" && userdata[i][userdata[i].length()-1]=="'"){
userdata[i].remove(0,1);
userdata[i].remove(userdata[i].length()-1,1);
//如果某个人值前后都是单引号,那 把单引号删除
}
insert_values->replace(pos,userdata.at(i));
//if(insert_values[pos]=="'")
}
QString strTxt = insert_values->join(",");
qDebug()<<strTxt;
out<<strTxt<<endl;
}
}
tfile.close();
return true;
}//insert
bool MainWindow::CheckForeignKey(QString insertedvalue,QString referedtable,QString referedCol){
qDebug()<<"进入比较外键 insertedvalue="<<insertedvalue<<" referedtable="<<referedtable<<" referedCol="<<referedCol;
insertedvalue.remove("'");
//参照表名、参照列名、要插入的值 即找 该值是否存在
int referedIndex=-1;//被参照的列的位置(0,1……)
QFile redfile(types::current_path + current_database + "/"+referedtable+ "/type.csv");
QTextStream stream(&redfile);
if (!redfile.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the referenced tables.csv!\n";
return false;
}
redfile.seek(0);
QStringList ReferedDataName = stream.readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
ReferedDataName[0].remove(QRegExp("\\s"));
QStringList strLine1 = ReferedDataName.at(0).split(",");//获取每行信息 第一行是列名 第二行是属性 Data[0] "id,name"
referedIndex= strLine1.indexOf(referedCol);
if(referedIndex==-1){
qDebug()<<"找不到要参照的列!";
return false;
}//以上定位了被参照列的列号
redfile.close();
//打开user表找对应数据
QFile referedUserData(types::current_path + current_database +"/"+referedtable+ "/user.csv");
QTextStream userstream(&referedUserData);
if (!referedUserData.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the referenced user.csv!\n";
return false;
}
referedUserData.seek(0);
QStringList ReferedUser = userstream.readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//ReferedData[0].remove(QRegExp("\\s"));
//QStringList strLine1 = ReferedData.at(0).split(",");
int exist=0;
for(int i=0;i<ReferedUser.size();i++){
ReferedUser[i].remove(QRegExp("\\s"));
QStringList Linedata = ReferedUser[i].split(",");
qDebug()<<"compare: ReferedUser="<<Linedata.at(referedIndex)<<" insertedvalue:"<<insertedvalue;
if(Linedata.at(referedIndex)==insertedvalue){
exist=1;
qDebug()<<"Find the foreign key!!CHERRS!!!";
break;
}
}
if(exist==1){
return true;
}else
return false;
//Data[1].remove(QRegExp("\\s"));
}
bool MainWindow::checkMatch(QString type,QString value){
if(value=="null")
return true;
//检查输入的值与表中的类型是否 匹配 "int", "varchar","datetime","double","bool
qDebug()<<"IN MATCH: type="<<type<<" value="<<value;
bool flag=false;
if(type=="double"){
value.toDouble(&flag);
if(flag){
qDebug()<<"\t5match double!";
return true;
}else{
qDebug()<<"\t not match double!";
return false;
}
}else if(type=="datetime"){
//时间怎么匹配啊 不会
QRegExp rx("'(\\d{4})-(\\d{2})-(\\d{2})'");
//to_date("20221102","yyyymmnn");
//QDateTime MyTime;
if (!rx.exactMatch(value)) {
QMessageBox::warning(this, "警告", "此值不符合datetime类型!");
return false;
}
int month = rx.cap(2).toInt();
if (month <= 0 || month > 12) {
QMessageBox::warning(this, "警告", "月份不符合实际!");
return false;
}
int day = rx.cap(3).toInt();
if (day <= 0 || day > 31) {
QMessageBox::warning(this, "警告", "天份不符合实际!");
return false;
}
//MyTime = QDateTime::fromString(str,"yyyy-MM-dd HH:mm:ss");
//qDebug() << MyTime;
qDebug()<<"\tmatch time!";
return true;
}else if(type.contains("varchar")){
QRegExp *ex=new QRegExp("varchar\\((\\d+)\\)");
if(!ex->exactMatch(type)){
qDebug()<<"类型错误";
}
QString c1=ex->cap(1);//第一个是数字
qDebug()<<"cap1="<<c1;
int slength=c1.toInt()+2;//int(QString(type.at(8)).toInt());//varchar长度
if(value[0]!="'"||value[value.length()-1]!="'"){
qDebug()<<"错误的varchar数据";
return false;
}
if(value.length()>slength){
qDebug()<<"allow len="<<slength<<" act="<<value.length();
qDebug()<<"\tnot match varchar!";
return false;
}else{
qDebug()<<"\tmatch varchar!";
return true;
/*
int slength=int(QString(type.at(8)).toInt());//varchar长度
if(value.length()>slength){
qDebug()<<"\tnot match varchar!";
return false;
}else{
qDebug()<<"\tmatch varchar!";
return true;
}*/
}
}else if(type=="bool"){
if(value=="1"||value=="0"||value=="true"||value=="false"){
qDebug()<<"\tmatch bool!";
return true;
}else{
qDebug()<<"\tnot match bool!";
return false;
}
}else if(type=="int"){//int类型
value.toInt(&flag);
if(flag){
qDebug()<<"\5match int!";
return true;
}else{
qDebug()<<"\tnot match!";
return false;
}
}
qDebug()<<"\tnot match!";
return false;
}
void MainWindow::created_parser(QString s, int flag) {
//flag为true时,创建的是表
QRegExp *rx;
if (flag == 1) {
rx = new QRegExp("(create)\\s+(table)\\s+(\\w+)\\s*\\(([^,]+(,[^,]+)*)?\\)\\s*;$");
if (!rx->exactMatch(s)) {
QMessageBox::warning(this, "警告", "创建语法错误!");
return;
}
QString name = rx->cap(3);
//查看是否该数据库中已经存在此表
QFile file(types::current_path + current_database + "/tables.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!\n";
return;
}
file.seek(0);
//记录了所有的表名
vector<QString> tables;
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == name) {
QMessageBox::warning(this, "警告", "此表已经存在!");
return;
}
tables.push_back(cur);
}
//记录所有的约束的名字, 以及它们的约束类型
vector<pair<QString, QString>> ct_names;
QString properties = rx->cap(4);
//处理字符串,并且此处为考虑约束条件
properties.replace("//s+", " ");
// properties.replace("(", " ");
// properties.replace(")", " ");
properties.replace(";", " ");
properties.replace("\t", " ");
properties.replace("\n", " ");
properties.replace("//s,//s", ",");
qDebug() << properties << "\n";
QStringList list = properties.split(",");//此处为根据,分割字符串
vector<pair<QString, QString>> pro;//用于存储col和col——type的
//记录那些列需要被设为not null
vector<QString> not_nulls;
//记录加入的主键
pair<QString, vector<QString>> pks;
bool pk_flag = false;
//记录加入的外键,约束名、被参照表、被参照列
vector<pair<pair<QString, QString>, pair<QString, QString>>> fks;
//记录被参照的表中的信息,参照表的名字、约束名
vector<pair<QString, pair<QString, QString>>> fedks;
for (int i = 0; i < list.size(); i++) {
//如果所输入的类型不在我们所选的内容里面则视为语法错误
//QStringList list_s = list[i].split(" ");
qDebug() << "list " << list[i] << "\n";
int pos = 0;
while (pos < list[i].size() && list[i][pos] == " ") {
pos++;
}
list[i] = list[i].mid(pos, list[i].size() - pos);
//判断是否为primary key约束
//primary\\s+key\\s*\\((.+)\\)\\s*
QRegExp ct("\\s*constraint\\s+(\\w+)\\s+(.+)");
//判断是否为列的输入
QRegExp temp("(\\w+)\\s(\\w+)(\\s*\\(\\s*\\d+\\s*\\))?(\\s+not null)?(\\s+default\\s+)?(.+)?$");
if (ct.exactMatch(list[i])) {
//如果约束为主键
QRegExp pk("primary\\s+key\\s*\\((.+)\\)\\s*");
//如果约束为外键,此处我们默认外键只能由一个属性组成
QRegExp fk("foreign\\s+key\\s*\\((\\w+)\\)\\s+references\\s+(\\w+)\\s*\\((\\w+)\\)\\s*");
//记录约束的名字
QString name_ct = ct.cap(1);
for (auto it : ct_names) {
if (it.first == name_ct) {
QMessageBox::warning(this, "警告", "约束的名字已存在!");
return;
}
}
//符合主键时
if (pk.exactMatch(ct.cap(2))) {
if (pk_flag) {
QMessageBox::warning(this, "警告", "主键只能存在一个!");
return;
}
QStringList primary_key_col = pk.cap(1).split(":");
pks.first = name_ct;
for (QString x : primary_key_col) {
x.replace(" ", "");
pks.second.push_back(x);
}
ct_names.emplace_back(name_ct, "primary_key");//加入此约束名
} else if (fk.exactMatch(ct.cap(2))) {
QString foreign_key = fk.cap(1);
QString foreigned_table = fk.cap(2);
QString foreigned_key = fk.cap(3);
//判断表是否存在
if (std::find(tables.begin(), tables.end(), foreigned_table) == tables.end()) {
QMessageBox::warning(this, "警告", "创建的外键的被参照表不存在!");
return;
}
//判断参照的列是否存在
QFile file2(types::current_path + current_database + "/" + foreigned_table + "/type.csv");
QTextStream stream2(&file2);
if (!file2.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the foreigned_table.csv!\n";
return;
}
file2.seek(0);
QStringList foreigned_cols = stream2.readLine().split(",");
if (!foreigned_cols.contains(foreigned_key)) {
qDebug() << foreigned_table << "\n";
QMessageBox::warning(this, "警告", "创建的外键的被参照列不存在!");
return;
}
//判断你指定的列是否存在
bool b = false;
for (int i = 0; i < pro.size(); ++i) {
if (pro[i].first == foreign_key) {
b = true;
break;
}
}
if (!b) {
QMessageBox::warning(this, "警告", "创建的外键的参照列不存在!");
return;
}
//约束名、参照表、参照列名
fedks.emplace_back(foreigned_table, make_pair(name_ct, foreigned_key));
//约束名、被参照表、被参照列名
fks.emplace_back(make_pair(name_ct, foreign_key), make_pair(foreigned_table, foreigned_key));
ct_names.emplace_back(name_ct, "foreign_key");
} else {
QMessageBox::warning(this, "警告", "创建的约束不符合语法!");
return;
}
} else if (temp.exactMatch(list[i])) {
if (types::type.find(temp.cap(2).toStdString()) == types::type.end()) {
qDebug() << temp.cap(2) << "\n";
QMessageBox::warning(this, "警告", "创建表时使用了不能被识别的类型!");
return;
}
QString type_col = temp.cap(2);
if (type_col == "varchar") {
QStringList p = rx->capturedTexts();
if (temp.cap(3) == NULL) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中未给n的值");
return;
}
QString num = temp.cap(3);
//去除()以及空格
num.replace(" ", "");
num.replace("(", "");
num.replace(")", "");
string num_s = num.toStdString();
for (char c : num_s) {
if (!isdigit(c)) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中的n不为整型");
return;
}
}
pro.emplace_back(temp.cap(1), temp.cap(2) + temp.cap(3));
} else {
pro.emplace_back(temp.cap(1), temp.cap(2));
}
if (temp.cap(4) != NULL) {
//此列有个约束为not null
not_nulls.push_back(temp.cap(1));
}
} else {
QMessageBox::warning(this, "警告", "创建表时,列的语法出现问题!");
return;
}
}
for (QString x : pks.second) {
bool flag = false;
for (int i = 0; i < pro.size(); ++i) {
if (pro[i].first == x) {
flag = true;
break;
}
}
if (!flag) {
QMessageBox::warning(this, "警告", "设置的主键的列名不存在!");
return;
}
}
stream << name + "\n";
//创建该表文件夹
QDir dir;
dir.mkdir(types::current_path + current_database + "/" + name);
qDebug() << "succeed to create table!\n";
file.close();
stream.flush();
QFile file4(types::current_path + current_database + "/" + name + "/primary_key.csv");//date描述表中的数据
QTextStream stream4(&file4);
if (!file4.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the primary_key.csv!\n";
return;
}
if (pks.first != "") {
stream4 << pks.first << ",";
}
for (int i = 0; i < pks.second.size(); ++i) {
if (i == pks.second.size() - 1) {
stream4 << pks.second[i] << "\n";
} else {
stream4 << pks.second[i] << ",";
}
}
QFile file2(types::current_path + current_database + "/" + name + "/type.csv");//date描述表中的数据
QTextStream stream2(&file2);
if (!file2.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!\n";
return;
}
QFile file3(types::current_path + current_database + "/" + name + "/constraint.csv");
QTextStream stream3(&file3);
if (!file3.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the constraint.csv!\n";
return;
}
bool t = false;
for (int i = 0; i < pro.size(); ++i) {
if (i == pro.size() - 1) {
stream2 << pro[i].first + "\n";//将col的名字输入到date文件中
} else {
stream2 << pro[i].first + ",";//将col的名字输入到date文件中
}
//如果此类在notnull数组中则在约束表中加入notnull
if (std::find(not_nulls.begin(), not_nulls.end(), pro[i].first) != not_nulls.end()) {
if (!t) {
stream3 << "notnull";
t = true;
} else {
stream3 << "," << "notnull";
}
} else {
if (!t) {
stream3 << "null";
t = true;
} else {
stream3 << "," << "null";
}
}
}
for (int i = 0; i < pro.size(); ++i) {
if (i == pro.size() - 1) {
stream2 << pro[i].second + "\n";//将col的类型输入到date文件中
} else {
stream2 << pro[i].second + ",";//将col的类型输入到date文件中
}
}
//写入外键文件
QFile file5(types::current_path + current_database + "/" + name + "/foreign_key.csv");//date描述表中的数据
QTextStream stream5(&file5);
if (!file5.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the foreign_key.csv!\n";
return;
}
for (auto it : fks) {
stream5 << it.first.first << "," << it.first.second << "," << it.second.first << "," << it.second.second << "\n";
}
//写入被参照文件
for (auto it : fedks) {
QFile file6(types::current_path + current_database + "/" + it.first + "/foreigned_key.csv");//date描述表中的数据
QTextStream stream6(&file6);
if (!file6.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the foreigned_key.csv!\n";
return;
}
stream6 << it.second.first << "," << it.second.second << "\n";
}
QFile file_ct(types::current_path + current_database + "/" + name + "/constraint_name.csv");
QTextStream stream_ct(&file_ct);
if (!file_ct.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the constraint_name.csv!\n";
return;
}
file_ct.seek(0);
for (auto it : ct_names) {
stream_ct << it.first << "," << it.second << "\n";
}
file2.close();
stream2.flush();
qDebug() << "succeed to create complete table!\n";
} else if (flag == 2) {
rx = new QRegExp("(create)\\s+(database)\\s+(\\w+)\\s*;$");
if (!rx->exactMatch(s)) {
QMessageBox::warning(this, "警告", "创建语法错误!");
return;
}
QString name = rx->cap(3);
QFile file(types::current_path + "ban.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the file!\n";
return;
}
file.seek(0);
qDebug() << name;
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == name) {
QMessageBox::warning(this, "警告", "数据库名字出现重名,请重新输入!");
return;
}
}
//未找到相匹配的数据库则将此数据库插入到ban.csv中
stream << name + "\n";
//建立相应的数据库文件夹里面存放对应表的信息
QDir dir;
dir.mkdir(types::current_path + name);
qDebug() << "succeed to create database!\n";
stream.flush();
file.close();
} else if (flag == 3) {
//to do index creation
}
ini_tree();//加入数据之后我们需要重新加载tree
}
bool MainWindow::altered_parser(QString s) {
qDebug() << "start..." << "\n";
QRegExp rx("\\s*(alter)\\s+(table)\\s+(\\w+)\\s+(modify|add|drop)\\s+(column\\s+)?(.+);$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "此alter操作不符合语法规范");
return false;
}
QString name = rx.cap(3);
QFile file(types::current_path + current_database + "/tables.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!\n";
return false ;
}
file.seek(0);
bool flag = false;//记录是否当前数据库存在此表
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行表名字
if (cur == name) {
flag = true;
}
}
if (!flag) {
QMessageBox::warning(this, "警告", "此alter操作的表不存在!");
return false;
}
qDebug() << name << "\n";
vector<pair<QString, QString>> pro;//用于存储此表中的所有列的列名和类型
//读取所有的属性的名字和类型
QFile file2(types::current_path + current_database + "/" + name + "/type.csv");
QTextStream stream2(&file2);
if (!file2.open(QIODevice::ReadOnly)) {
qDebug() << "fail to open the type.csv!" << "\n";
return false;
}
file2.seek(0);
QString cur = stream2.readLine();
QStringList list = cur.split(",");
// if (list.last().isEmpty()) {
// list.removeLast();
// }
cur = stream2.readLine();
QStringList list2 = cur.split(",");
// if (list2.last().isEmpty()) {
// list2.removeLast();
// }
for (int i = 0; i < list.size(); ++i) {
pro.emplace_back(list[i], list2[i]);
qDebug() << list[i] << " *" << list2[i] << "\n";
}
//此处为记录所有的用户数据
vector<vector<QString>> user;
QFile file3(types::current_path + current_database + "/" + name + "/user.csv");
QTextStream stream3(&file3);
if (!file3.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the user.csv!";
return false;
}
file3.seek(0);
while (!stream3.atEnd()) {
QString cur = stream3.readLine();
QStringList ql = cur.split(",");
// if (ql.last().isEmpty()) {
// ql.removeLast();
// }
vector<QString> v;
for (auto x : ql) {
v.push_back(x);
}
user.push_back(v);
}
QString type_alter = rx.cap(4);
//记录列是否可以为null
vector<QString> nulls;
QFile file4(types::current_path + current_database + "/" + name + "/constraint.csv");
QTextStream stream4(&file4);
if (!file4.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the constraint.csv!";
return false;
}
file4.seek(0);
while (!stream4.atEnd()) {
QString cur = stream4.readLine();
QStringList ql = cur.split(",");
// if (ql.last().isEmpty()) {
// ql.removeLast();
// }
for (auto x : ql) {
nulls.push_back(x);
}
}
//存储主键属性
vector<QString> primary_keys;
QFile file5(types::current_path + current_database + "/" + name + "/primary_key.csv");
QTextStream stream5(&file5);
if (!file5.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the constraint.csv!";
return false;
}
file5.seek(0);
QStringList pks = stream5.readLine().split(",");
// if (pks.last().isEmpty()) {
// pks.removeLast();
// }
for (int i = 0; i < pks.size(); ++i) {
primary_keys.push_back(pks[i]);
}
if (type_alter == "add") {
QString col_stm = rx.cap(6);
qDebug() << col_stm << "\n";
QRegExp r("(\\w+)\\s(\\w+)(\\s*\\(\\s*\\d+\\s*\\))?(\\snot null\\s)?(default\\s)?(.+)?$");
if (!r.exactMatch(col_stm)) {
QMessageBox::warning(this, "警告", "ALTER 的 ADD 语句的语法出现问题!");
return false;
}
if (types::type.find(r.cap(2).toStdString()) == types::type.end()) {
qDebug() << r.cap(2) << "\n";
QMessageBox::warning(this, "警告", "ADD 列时使用了不能被识别的类型!");
return false;
}
QString col_name = r.cap(1);
QString col_type = r.cap(2);
if (col_type == "varchar") {
if (r.cap(3) == NULL) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中未给n的值");
return false;
}
QString num = r.cap(3);
//去除()以及空格
num.replace(" ", "");
num.replace("(", "");
num.replace(")", "");
string num_s = num.toStdString();
for (char c : num_s) {
if (!isdigit(c)) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中的n不为整型");
return false;
}
}
//如果加入的列设置只能设计成null
nulls.push_back("null");
for (int i = 0; i < user.size(); ++i) {
user[i].push_back("null");
}
pro.emplace_back(r.cap(1), r.cap(2) + "(" + num + ")");
} else {
pro.emplace_back(r.cap(1), r.cap(2));
//如果加入的列设置只能设计成null
nulls.push_back("null");
for (int i = 0; i < user.size(); ++i) {
user[i].push_back("null");
}
}
} else if (type_alter == "modify") {
QFile modify_file(types::current_path + current_database + "/" + name + "/user.csv");
if (modify_file.exists() && modify_file.size() != 0) {
QMessageBox::warning(this, "警告", "表中存在数据不允许modify修改类型!");
return false;
}
QString col_stm = rx.cap(6);
if (rx.captureCount() == 6) {
col_stm = rx.cap(6);
} else {
col_stm = rx.cap(5);
}
QRegExp r("(\\w+)\\s(\\w+)(\\s*\\(\\s*\\d+\\s*\\))?(\\snot null\\s)?(default\\s)?(.+)?$");
if (!r.exactMatch(col_stm)) {
QMessageBox::warning(this, "警告", "ALTER 中的 MODIFY 语句的语法出现问题!");
return false;
}
if (types::type.find(r.cap(2).toStdString()) == types::type.end()) {
qDebug() << r.cap(2) << "\n";
QMessageBox::warning(this, "警告", "MODIFY 列时使用了不能被识别的类型!");
return false;
}
QString col_name = r.cap(1);
QString col_type = r.cap(2);
if (col_type == "varchar") {
QStringList p = r.capturedTexts();
if (p.size() < 3) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中未给n的值");
return false;
}
QString num = r.cap(3);
//去除()以及空格
num.replace(" ", "");
num.replace("(", "");
num.replace(")", "");
string num_s = num.toStdString();
for (char c : num_s) {
if (!isdigit(c)) {
QMessageBox::warning(this, "警告", "VARCHAR 类型中的n不为整型");
return false;
}
}
col_type = r.cap(2) + "(" + num + ")";
}
bool b = false;
for (int i = 0; i < pro.size(); ++i) {
if (pro[i].first == col_name) {
pro[i].second = col_type;
b = true;
break;
}
}
if (!b) {
QMessageBox::warning(this, "警告", "MODIFY 列时修改的列名不存在!");
return false;
}
} else if (type_alter == "drop") {
qDebug() << "ok";
QFile fedk_ex_file(types::current_path + current_database + "/" + name + "/foreigned_key.csv");
if (fedk_ex_file.exists() && fedk_ex_file.size() != 0) {
QMessageBox::warning(this, "警告", "由于被其他表参考不允许删除!");
return false;
}
QString col_name = rx.cap(6);
bool b = false;
//记录删除的列的位置
int pos;
for (int i = 0; i < pro.size(); ++i) {
if (pro[i].first == col_name) {
b = true;
pro.erase(pro.begin() + i);
pos = i;
break;
}
}
if (!b) {
QMessageBox::warning(this, "警告", "DROP 列时的列名不存在!");
return false;
}
//删除对应的数据文件信息
for (int i = 0; i < user.size(); ++i) {
user[i].erase(user[i].begin() + pos);
}
//删除对应的constraint信息
nulls.erase(nulls.begin() + pos);
//如果删除的属性为主键时
if (std::find(primary_keys.begin() + 1, primary_keys.end(), col_name) != primary_keys.end()) {
primary_keys.erase(std::find(primary_keys.begin() + 1, primary_keys.end(), col_name));
}
}
int n = pro.size();
//重写type文件
QFile file6(types::current_path + current_database + "/" + name + "/type.csv");
QTextStream stream6(&file6);
if (!file6.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the type.csv!" << "\n";
return false;
}
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < n; ++j) {
if (i == 0) {
if (j == n - 1) {
stream6 << pro[j].first << "\n";
} else {
stream6 << pro[j].first << ",";
}
} else {
if (j == n - 1) {
stream6 << pro[j].second << "\n";
} else {
stream6 << pro[j].second << ",";
}
}
}
}
//重写user文件
QFile file7(types::current_path + current_database + "/" + name + "/user.csv");
QTextStream stream7(&file7);
if (!file7.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!" << "\n";
return false;
}
for (int i = 0; i < user.size(); ++i) {
for (int j = 0; j < user[i].size(); ++j) {
if (j == user[i].size() - 1) {
stream7 << user[i][j] << "\n";
} else {
stream7 << user[i][j] << ",";
}
}
}
//重写constraint文件
QFile file8(types::current_path + current_database + "/" + name + "/constraint.csv");
QTextStream stream8(&file8);
if (!file8.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the constraint.csv!" << "\n";
return false;
}
for (int j = 0; j < nulls.size(); ++j) {
if (j == nulls.size() - 1) {
stream8 << nulls[j] << "\n";
} else {
stream8 << nulls[j] << ",";
}
}
//重写主键文件
QFile file9(types::current_path + current_database + "/" + name + "/primary_key.csv");
QTextStream stream9(&file9);
if (!file9.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the primary_key.csv!" << "\n";
return false;
}
if (primary_keys.size() > 1) {
for (int j = 0; j < primary_keys.size(); ++j) {
if (j == primary_keys.size() - 1) {
stream9 << primary_keys[j] << "\n";
} else {
stream9 << primary_keys[j] << ",";
}
}
}
qDebug() << "succeed to alter table!\n";
ini_tree();
return true;
}
void MainWindow::use_parser(QRegExp rx) {
QFile file(types::current_path + "ban.csv");
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the file!\n";
return;
}
QString name = rx.cap(2);
file.seek(0);
qDebug() << "name " << name;
QTextStream stream(&file);
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
qDebug() << "in file cur is " << cur + "\n";
if (cur == name) {
qDebug() << "succeed to use the database!\n";
current_database = name;
return;
}
}
//未找到名字为name的数据库名字
qDebug() << "fail to find the database!\n";
return ;
}
void MainWindow::selected_parser(QString s) {
//qDebug()<<"coming"<<endl;
QString s1 = "";//select
QString s2 = "";//from
QString s3 = "";//where
QString s4 = "";//group by
QString s5 = "";// having
QString s6 = "";// order by
QStringList properties;
QStringList tables;
QStringList wheres;
QStringList groups;
QStringList havings;
QStringList orders;
s = s.simplified();//去掉字符串中多余的空格
int whichone = -1; //正确的select语句格式有12种,不同种类对应一个数字
QRegExp temp0("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\s*;\\s*");
if (temp0.exactMatch(s)) {
whichone = 0;
}
QRegExp temp1("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp1.exactMatch(s)) {
whichone = 1;
}
QRegExp temp2("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\group\\s+by\\b(.+)\\s*;\\s*");
if (temp2.exactMatch(s)) {
whichone = 2;
}
QRegExp temp3("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\group\\s+by\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp3.exactMatch(s)) {
whichone = 3;
}
QRegExp temp4("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\group\\s+by\\b(.+)\\having\\b(.+)\\s*;\\s*");
if (temp4.exactMatch(s)) {
whichone = 4;
}
QRegExp temp5("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\group\\s+by\\b(.+)\\having\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp5.exactMatch(s)) {
whichone = 5;
}
QRegExp temp6("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\s*;\\s*");
if (temp6.exactMatch(s)) {
whichone = 6;
}
QRegExp temp7("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp7.exactMatch(s)) {
whichone = 7;
}
QRegExp temp8("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\group\\s+by\\b(.+)\\s*;\\s*");
if (temp8.exactMatch(s)) {
whichone = 8;
}
QRegExp temp9("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\group\\s+by\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp9.exactMatch(s)) {
whichone = 9;
}
QRegExp temp10("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\group\\s+by\\b(.+)\\having\\b(.+)\\s*;\\s*");
if (temp10.exactMatch(s)) {
whichone = 10;
}
QRegExp temp11("\\s*\\bselect\\b(.+)\\bfrom\\b(.+)\\bwhere\\b(.+)\\group\\s+by\\b(.+)\\having\\b(.+)\\border\\s+by\\b(.+)\\s*;\\s*");
if (temp11.exactMatch(s)) {
whichone = 11;
}
if (whichone == -1) {
QMessageBox::warning(this, "警告", "不符合select语法");
return;
}
//从文件中读取数据库
QFile file(types::current_path + current_database + "\\tables.csv");
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << file.errorString();
QMessageBox::warning(this, "警告", "tables表不存在");
return;
}
QVector<QString> table_names;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
table_names.push_back(line);
// QStringList fields = line.split(",");
// qDebug()<< line << endl;
// process fields
}
// qDebug() << table_names.size() << " ";
// for(int i = 0; i< table_names.size(); i++){
// qDebug() << table_names[i] <<" ";
// }
// cout << endl;
switch(whichone){ //对不同情况的select语句分别进行处理,将字符串进行分割
case 0 :
s1 = temp0.cap(1);
s2 = temp0.cap(2);
properties = s1.split(",");
tables = s2.split(",");
for(int i = 0; i < properties.size(); i++){
properties[i].remove(QRegExp("\\s"));
}
for(int i = 0; i < tables.size(); i++){
tables[i].remove(QRegExp("\\s"));
}
//qDebug() << properties << endl << tables;
break;
case 1 :
s1 = temp1.cap(1);
s2 = temp1.cap(2);
s6 = temp1.cap(3);
properties = s1.split(",");
tables = s2.split(",");
orders = s6.split(",");
for(int i = 0; i < properties.size(); i++){
properties[i].remove(QRegExp("\\s"));
}
for(int i = 0; i < tables.size(); i++){
tables[i].remove(QRegExp("\\s"));
}
for(int i = 0; i < orders.size(); i++){
orders[i].remove(QRegExp("\\s"));
}
//qDebug() << properties << endl << tables << endl << orders;
break;
case 2 :
s1 = temp2.cap(1);
s2 = temp2.cap(2);
s4 = temp2.cap(3);
properties = s1.split(",");
tables = s2.split(",");
groups = s4.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << groups;
break;
case 3 :
s1 = temp3.cap(1);
s2 = temp3.cap(2);
s4 = temp3.cap(3);
s6 = temp3.cap(4);
properties = s1.split(",");
tables = s2.split(",");
groups = s4.split(",");
orders = s6.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
orders.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << groups << endl << orders;
break;
case 4 :
s1 = temp4.cap(1);
s2 = temp4.cap(2);
s4 = temp4.cap(3);
s5 = temp4.cap(4);
properties = s1.split(",");
tables = s2.split(",");
groups = s4.split(",");
havings = s5.split("and");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
havings.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << groups << endl << havings;
break;
case 5 :
s1 = temp5.cap(1);
s2 = temp5.cap(2);
s4 = temp5.cap(3);
s5 = temp5.cap(4);
s6 = temp5.cap(5);
properties = s1.split(",");
tables = s2.split(",");
groups = s4.split(",");
havings = s5.split("and");
orders = s6.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
havings.replaceInStrings(QRegExp("\\s+"), "");
orders.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << groups << endl << havings <<endl << orders;
break;
case 6 :
s1 = temp6.cap(1);
s2 = temp6.cap(2);
s3 = temp6.cap(3);
properties = s1.split(",");
tables = s2.split(",");
wheres = s3.split("and");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << wheres;
break;
case 7 :
s1 = temp7.cap(1);
s2 = temp7.cap(2);
s3 = temp7.cap(3);
s6 = temp7.cap(4);
properties = s1.split(",");
tables = s2.split(",");
wheres = s3.split("and");
orders = s6.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
orders.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl << wheres << endl << orders;
break;
case 8 :
s1 = temp8.cap(1);
s2 = temp8.cap(2);
s3 = temp8.cap(3);
s4 = temp8.cap(4);
properties = s1.split(",");
tables = s2.split(",");
wheres = s3.split("and");
groups = s4.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables << endl<<wheres<<endl << groups;
break;
case 9 :
s1 = temp9.cap(1);
s2 = temp9.cap(2);
s3 = temp9.cap(3);
s4 = temp9.cap(4);
s6 = temp9.cap(5);
properties = s1.split(",");
tables = s2.split(",");
wheres= s3.split("and");
groups = s4.split(",");
orders = s6.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
orders.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables<<endl << wheres << endl << groups << endl << orders;
break;
case 10 :
s1 = temp10.cap(1);
s2 = temp10.cap(2);
s3 = temp10.cap(3);
s4 = temp10.cap(4);
s5 = temp10.cap(5);
properties = s1.split(",");
tables = s2.split(",");
wheres = s3.split("and");
groups = s4.split(",");
havings = s5.split("and");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
havings.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables<<endl<< wheres << endl << groups << endl << havings;
break;
case 11 :
s1 = temp11.cap(1);
s2 = temp11.cap(2);
s3 = temp11.cap(3);
s4 = temp11.cap(4);
s5 = temp11.cap(5);
s6 = temp11.cap(6);
properties = s1.split(",");
tables = s2.split(",");
wheres = s3.split("and");
groups = s4.split(",");
havings = s5.split("and");
orders = s6.split(",");
properties.replaceInStrings(QRegExp("\\s+"), "");
tables.replaceInStrings(QRegExp("\\s+"), "");
wheres.replaceInStrings(QRegExp("\\s+"), "");
groups.replaceInStrings(QRegExp("\\s+"), "");
havings.replaceInStrings(QRegExp("\\s+"), "");
orders.replaceInStrings(QRegExp("\\s+"), "");
//qDebug() << properties << endl << tables <<endl<< wheres<< endl << groups << endl << havings <<endl << orders;
break;
}
//判断有没有*
bool isall = false;
for(int i = 0; i < properties.size(); i++){
if(properties[i] == "*"){
isall = true;
}
}
if(isall == true && properties.size() > 1){
QMessageBox::warning(this, "警告", "已选取所有列");
return;
}
//对from里的内容进行判断
for(int i = 0; i < tables.size(); i++) //判断from的表是否存在
{
if (!table_names.contains(tables[i])) {
QMessageBox::warning(this, "警告", tables[i]+" NotFound!");
return;
qDebug() <<tables[i] << " NotFound!" << endl;
} /*else {
qDebug() <<tables[i] <<"found!" << endl;
}*/
}
//QMap<QString, QMap<int, QString>> map; //用来储存多表连接后的数据
QStringList list_type;//列名
QStringList list_real_type;//属性
for(int i = 0; i < tables.size(); i++){//对每一张表的字段进行连接
QFile file_type(types::current_path + current_database + "\\"+tables[i]+"\\type.csv");
if (!file_type.open(QIODevice::ReadOnly)) {
qDebug() << file_type.errorString();
QMessageBox::warning(this, "警告", "type表不存在");
return;
}
QTextStream in_type(&file_type);
QString line0 = in_type.readLine();
QStringList list_type0 = line0.split(",");
//list_type0.removeLast();
for(int j = 0; j < list_type0.size(); j++){
list_type0[j] = tables[i] + "." + list_type0[j];
}
list_type += list_type0;
QString line00 = in_type.readLine();
QStringList list_type00 = line00.split(",");
//list_type0.removeLast();
list_real_type += list_type00;
}
//qDebug() << list_real_type <<endl;
QVector<QVector<QString>> data;
QVector<QString> result;
for(int i = 0; i < tables.size(); i++){ //先把每个表中的内容放入一个vector中
QFile file_user(types::current_path + current_database + "\\"+tables[i]+"\\user.csv");
if (!file_user.open(QIODevice::ReadOnly)) {
qDebug() << file_user.errorString();
QMessageBox::warning(this, "警告", "user表不存在");
return;
}
QTextStream in_user(&file_user);
QVector<QString> temp_vector;
while (!in_user.atEnd()) {
QString line1 = in_user.readLine();
temp_vector.push_back(line1);
}
data.push_back(temp_vector);
}
result = data[0];
for(int i = 1; i < data.size(); i++){
result = cross(result, data[i]);
}
QVector<QVector<QString>> real_result;
for(int i = 0; i < result.size(); i++){ //将笛卡尔积之后的所有内容剪切出来放在容器里面 数据中不支持有空格
result[i].replace(" ", "");
QStringList temp_list = result[i].split(",");
real_result.push_back(QVector<QString>::fromList(temp_list));
}
qDebug() << real_result <<endl;
qDebug() << list_type;
qDebug() << list_real_type;
if(isall == true){
properties.clear();
for(int i = 0; i < list_type.size(); i++){
properties.push_back(list_type[i]);
}
}
//对where条件进行判断
//这里先要判断一下表里面有没有东西, 没有东西的话直接不执行了
if(!wheres.empty() && !real_result.empty()){
QVector<QVector<QString>> where_split; // 将表达式分开
for(int i = 0; i < wheres.size(); i++){
if(wheres[i].contains("<=")){
QRegExp judge_where("(.+)(<=)(.+)");
if(!judge_where.exactMatch(wheres[i])){
QMessageBox::warning(this, "警告", "where条件无效");
return;
} else {
QVector<QString> where_temp;
where_temp.push_back(judge_where.cap(1));
where_temp.push_back(judge_where.cap(2));
where_temp.push_back(judge_where.cap(3));
where_split.push_back(where_temp);
}
} else if(wheres[i].contains(">=")){
QRegExp judge_where("(.+)(>=)(.+)");
if(!judge_where.exactMatch(wheres[i])){
QMessageBox::warning(this, "警告", "where条件无效");
return;
} else {
QVector<QString> where_temp;
where_temp.push_back(judge_where.cap(1));
where_temp.push_back(judge_where.cap(2));
where_temp.push_back(judge_where.cap(3));
where_split.push_back(where_temp);
}
} else if(wheres[i].contains("!=")){
QRegExp judge_where("(.+)(!=)(.+)");
if(!judge_where.exactMatch(wheres[i])){
QMessageBox::warning(this, "警告", "where条件无效");
return;
} else {
QVector<QString> where_temp;
where_temp.push_back(judge_where.cap(1));
where_temp.push_back(judge_where.cap(2));
where_temp.push_back(judge_where.cap(3));
where_split.push_back(where_temp);
}
} else {
QRegExp judge_where("(.+)(=|<|>)(.+)");
if(!judge_where.exactMatch(wheres[i])){
QMessageBox::warning(this, "警告", "where条件无效");
return;
} else {
QVector<QString> where_temp;
where_temp.push_back(judge_where.cap(1));
where_temp.push_back(judge_where.cap(2));
where_temp.push_back(judge_where.cap(3));
where_split.push_back(where_temp);
}
}
}
//qDebug() << where_split;
//开始进行筛选
//符合条件的数据有6种,分别为列名 表名.列 int和double算一种(-2) bool(false和true)(-3) varchar和datatime算一种(-1),-10代表无效数据类型
//首先判断有没有单引号 有单引号分两种 不过我不需要判断
//首先判断有没有. 如果有.
vector<QPair<int, int>> where_lr_type;
for (int i = 0; i < where_split.size(); i++){
int left_type = -10, right_type = -10;
QRegExp string_or_not_left("^'(.+)'$");
QRegExp string_or_not_right("^'(.+)'$");
bool isNumber1 = false;
bool isNumber2 = false;
double d1 = where_split[i][0].toDouble(&isNumber1);
double d2 = where_split[i][2].toDouble(&isNumber2);
if(string_or_not_left.exactMatch(where_split[i][0])){ //判断左端是什么类型
left_type = -1;
} else if(isNumber1){
left_type = -2;
} else if(where_split[i][0] == "false" || where_split[i][0] == "true"){
left_type = -3;
} else { //下面判断这个字符串是不是列名
if(where_split[i][0].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(where_split[i][0] == list_type[j]){
left_type = j;
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = where_split[i][0];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
where_split[i][0] = (*temp_left).cap(1) + "." + where_split[i][0];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
} //else 的括号
// qDebug() << "left" ;
// qDebug() << left_type ;
// qDebug() << where_split[i][0];
//判断右边
if(string_or_not_right.exactMatch(where_split[i][2])){ //判断左端是什么类型
right_type = -1;
} else if(isNumber2){
right_type = -2;
} else if(where_split[i][2] == "false" || where_split[i][2] == "true"){
right_type = -3;
} else { //下面判断这个字符串是不是列名
if(where_split[i][2].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(where_split[i][2] == list_type[j]){
right_type = j;
break;
}
}
if(right_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = where_split[i][2];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
right_type = j;
where_split[i][2] = (*temp_left).cap(1) + "." + where_split[i][2];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(right_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
} //else 的括号
// qDebug() << "right" ;
// qDebug() << right_type ;
// qDebug() << where_split[i][2];
where_lr_type.push_back(qMakePair(left_type, right_type));
} //for的括号
//qDebug() << where_lr_type;
//下面对where中的每个条件进行筛选
for(int i = 0; i < where_lr_type.size(); i++){
if(real_result.empty()){ //当没有数据的时候直接结束循环
break;
}
if(where_lr_type[i].first < 0 and where_lr_type[i].second < 0){ //当两个都不是列的时候
if(where_lr_type[i].first != where_lr_type[i].second && where_split[i][1] != "!="){
QMessageBox::warning(this, "警告", "等号两边数据类型不一致");
return;
} else if(where_lr_type[i].first != where_lr_type[i].second && where_split[i][1] == "!="){
//qDebug() << "nothing hapened";
continue;
} else if(where_lr_type[i].first == where_lr_type[i].second){ //两边数据类型一致时进行判断
if(my_compare(where_split[i][0], where_split[i][2], -where_lr_type[i].first, where_split[i][1])){
//qDebug() << "yes";
continue;
} else {
real_result.clear();
}
}
} else { //当两边可能出现列的时候
//三种情况 左列 右列 左右列
if(where_lr_type[i].first < 0 and where_lr_type[i].second >= 0){ //右边时列 左边不是列 将它反转一下
int lefthahaha = where_lr_type[i].first;
where_lr_type[i].first = where_lr_type[i].second;
where_lr_type[i].second = lefthahaha;
QString lefthehehe = where_split[i][0];
where_split[i][0] = where_split[i][2];
where_split[i][2] = lefthehehe;
}
if(where_lr_type[i].first >= 0 and where_lr_type[i].second < 0){ //左边时列 右边不是列
QString checktemp1, checktemp2;
QString checktemp3 = where_split[i][1];
checktemp1 = where_split[i][2];
qDebug() << checktemp1;
checktemp2 = list_real_type[(where_lr_type[i].first)];
qDebug() << checktemp2;
if(!checkMatch(checktemp2, checktemp1)){
QMessageBox::warning(this, "警告", "等号两边类型不匹配");
return;
} else{
int where_temp;
if(checktemp2 == "int") where_temp = 2;
else if(checktemp2 == "double") where_temp = 2;
else if(checktemp2.contains("varchar")) where_temp = 1;
else if(checktemp2 == "bool") where_temp = 3;
else if(checktemp2 == "datetime") where_temp = 1;
//qDebug() << where_lr_type[i].first << " fdasfsad";
QVector<int> wherehahaha;
for(int j = 0; j < real_result.size(); j++){
QString jtemp0 = real_result[j][where_lr_type[i].first];
//qDebug() << jtemp0 << " ====";
if(where_temp == 1){ //喵咪咪
jtemp0 = QString("'%1'").arg(jtemp0);
qDebug() << jtemp0 << " here";
}
if(my_compare(jtemp0, checktemp1, where_temp,checktemp3 )){
continue;
} else{
wherehahaha.push_back(j);
}
}
for(int j = wherehahaha.size() - 1; j >= 0; j--){ //注意这块删除需要从后往前删
//qDebug()<< j;
real_result.remove(wherehahaha[j]);
}
}
}
if(where_lr_type[i].first >= 0 and where_lr_type[i].second >= 0){ //左边是列 右边是列
//先判断两个列类型是否相同
QString judge_both_two_have_var1 = list_real_type[(where_lr_type[i].first)];
QString judge_both_two_have_var2 = list_real_type[(where_lr_type[i].second)];
if(list_real_type[(where_lr_type[i].first)].contains("varchar")) {
judge_both_two_have_var1 = "varchar";
}
if(list_real_type[(where_lr_type[i].second)].contains("varchar")){
judge_both_two_have_var2 = "varchar";
}
if(judge_both_two_have_var1 != judge_both_two_have_var2){
QMessageBox::warning(this, "警告", "等号两边类型不匹配");
return;
} else {
//qDebug() << "that is cool!";
QVector<int> wherehahaha;
QString checktemp2 = judge_both_two_have_var1;
int where_temp;
if(checktemp2 == "int") where_temp = 2;
else if(checktemp2 == "double") where_temp = 2;
else if(checktemp2.contains("varchar")) where_temp = 1;
else if(checktemp2 == "bool") where_temp = 3;
else if(checktemp2 == "datetime") where_temp = 1;
for(int j = 0; j < real_result.size(); j++){
QString judge_two_value1 = real_result[j][where_lr_type[i].first];
QString judge_two_value2 = real_result[j][where_lr_type[i].second];
QString judge_two_value3 = where_split[i][1];
if(my_compare(judge_two_value1, judge_two_value2, where_temp, judge_two_value3)){
continue;
} else {
wherehahaha.push_back(j);
}
}
for(int j = wherehahaha.size() - 1; j >= 0; j--){ //注意这块删除需要从后往前删
//qDebug()<< j;
real_result.remove(wherehahaha[j]);
}
}
}
}
}//where筛选的for括号
// qDebug() << real_result;
// 2023 5 2 19.24 终于把where写完了 芜湖~
}
//下面是有关于group by的东西啦~
QVector<QVector<QVector<QString>>> real_group;
if(!groups.empty() && !real_result.empty()){
// if(groups.size() > 2){ //group by 只会2以内的呜呜呜
// QMessageBox::warning(this, "警告", "group by只支持两个以内喵~");
// return;
// }
//还是老样子,给列名变成全名,判断有没有在连接后的大表里面
QVector<int> column_places; //储存列名对应的位置
for(int i = 0; i < groups.size(); i++){
int left_type = -10;
if(groups[i].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(groups[i] == list_type[j]){
left_type = j;
column_places.push_back(j);
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = groups[i];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
column_places.push_back(j);
groups[i] = (*temp_left).cap(1) + "." + groups[i];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
}
// qDebug() << groups;
// qDebug() << column_places;
//先对第一个参数进行group by 第二个先不管哈
QVector<QVector<QVector<QString>>> first_group;
QMap<QString, QString> map1;
QMap<QString, int> map_temp1;
int map_count_temp1 = 0; //记录它应该在哪一个组
for(int i = 0; i < real_result.size(); i++){ //正式开始分组 好耶!
if(!map1.count(real_result[i][column_places[0]])){ //当不存在值一样的组的时候
map1.insert(real_result[i][column_places[0]], real_result[i][column_places[0]]);
map_temp1.insert(real_result[i][column_places[0]], map_count_temp1);
QVector<QVector<QString>> store_group1_temp;
store_group1_temp.push_back(real_result[i]);
first_group.push_back(store_group1_temp);
map_count_temp1++;
} else { //当已经分好组的时候
QString group1_temp = real_result[i][column_places[0]];
first_group[map_temp1.value(group1_temp)].push_back(real_result[i]);
}
}
// qDebug() << "分界线";
// qDebug() << first_group;
// QVector<QVector<QVector<QString>>> second_group;
// if(groups.size() == 2){ //下面对第二个参数进行分组
// //啊啊啊啊好难啊思路卡住了呜呜呜呜呜呜
// second_group = make_groups(first_group, column_places[1]);
// qDebug() << "分界线";
// qDebug() << second_group;
// }
real_group = first_group;
for(int i = 1; i < groups.size(); i++){
real_group = make_groups(real_group, column_places[i]);
}
qDebug() << "分界线";
//qDebug() << real_group;
}
qDebug() << "here is output" ;
qDebug() << real_group ;
qDebug() << "output finish" ;
//聚组函数
//判断数据是否为空,非空再开始执行
//先判断 groups 是否为空,为空则没有 group by 语句,将real_result复制进real_group
if(groups.empty() == true){
real_group.push_back(real_result);
}
qDebug() << real_group;
//分离聚组函数
QVector<QString> slctagrfunc;
//先判断properties中的聚组函数
for(int i = 0; i < properties.size(); i++){
QRegExp rx("(avg|sum|count|max|min)\\((\\w+\\.?\\w*)\\)");
int pos = 0;
while ((pos = rx.indexIn(properties[i], pos)) != -1) {
slctagrfunc.append(rx.cap(0));
pos += rx.matchedLength();
}
}
//再判断havings中的
for(int i = 0; i < havings.size(); i++){
QRegExp rx("(avg|sum|count|max|min)\\((\\w+\\.?\\w*)\\)");
int pos = 0;
while ((pos = rx.indexIn(havings[i], pos)) != -1) {
slctagrfunc.append(rx.cap(0));
pos += rx.matchedLength();
}
}
slctagrfunc = removeDuplicates(slctagrfunc);
qDebug()<< "slctagrfun:" << slctagrfunc;
//提取聚合函数类型,如avg,min
QVector<QString> agrfuntype;
for(int i = 0; i < slctagrfunc.size(); i++){
QRegExp rx("^(\\w+)");
rx.indexIn(slctagrfunc[i]);
QStringList list = rx.capturedTexts();
agrfuntype.push_back(list[1]);
}
qDebug() << "agrfuntype:" << agrfuntype;
//提取聚合函数括号中的属性
QVector<QString> agrfunprpt;
for(int i = 0; i < slctagrfunc.size(); i++){
QRegExp rx("\\((.*)\\)");
rx.indexIn(slctagrfunc[i]);
QStringList list = rx.capturedTexts();
agrfunprpt.push_back(list[1]);
}
//判断聚合函数是否合法
for(int i = 0; i < agrfunprpt.size(); i++){
int left_type = -10;
if(agrfunprpt[i].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(agrfunprpt[i] == list_type[j]){
left_type = j;
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = agrfunprpt[i];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
agrfunprpt[i] = (*temp_left).cap(1) + "." + agrfunprpt[i];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
}
qDebug() << "agrfunprpt:" << agrfunprpt;
QVector<int> indexofSumAvg;
//avg和sum只支持数字类型,如果不是数字类型则报错
//qDebug() << list_real_type;
for(int i = 0; i < agrfuntype.size(); i++){
if(agrfuntype[i] == "avg" || agrfuntype[i] == "sum"){
indexofSumAvg.push_back(i);
}
}
if(indexofSumAvg.isEmpty() == false){
bool isnum = true;
for(int i = 0; i < indexofSumAvg.size(); i++){
for(int j = 0; j < list_type.size(); j++){
if(agrfunprpt[indexofSumAvg[i]] == list_type[j]){
if(list_real_type[j] != "int" && list_real_type[j] != "double"){
isnum = false;
}
}
}
if(isnum == false){
QMessageBox::warning(this, "警告", "AVG 和 SUM 函数仅支持数值型参数");
return;
}
}
}
//判断select后的属性是否在group by中或者是聚组函数
qDebug() << "groups: " << groups;
//qDebug() << "prpts-agr: " << difference(properties.toVector(), slctagrfunc);
//为除去聚合函数外的select后的属性添加表名
/*if(slctagrfunc.size() > 0 || groups.size() > 0){
for(int i = 0; i < diff.size(); i++){
bool islegal = false;
for(int j = 0; j < groups.size(); j++){
QStringList templist = groups[j].split(".");
if(diff[i] == groups[j] || diff[i] == templist[1]){
islegal = true;
}
}
if(islegal == false){
QMessageBox::warning(this, "警告", "非聚合函数属性必须包含在 GROUP BY 子句中");
return;
}
}
}*/
QRegExp agre("(avg|sum|count|max|min)\\((\\w+\\.?\\w*)\\)");
for(int m = 0; m < properties.size(); m++){
int left_type = -10, right_type = -10;
QRegExp string_or_not_left("^'(.+)'$");
QRegExp string_or_not_right("^'(.+)'$");
bool isNumber1 = false;
bool isNumber2 = false;
if(!agre.exactMatch(properties[m])){
if(properties[m].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(properties[m] == list_type[j]){
left_type = j;
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = properties[m];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
properties[m] = (*temp_left).cap(1) + "." + properties[m];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
}
}
if(groups.size() > 0){
QVector<QString> diff = difference(properties.toVector(), slctagrfunc);
for(int i = 0; i < diff.size(); i++){
bool islegal = false;
for(int j = 0; j < groups.size(); j++){
if(diff[i] == groups[j]){
islegal = true;
}
}
if(islegal == false){
QMessageBox::warning(this, "警告", "非聚合函数属性必须包含在 GROUP BY 子句中");
return;
}
}
}
//向list_type中加入聚合函数,list_real_type中加入聚合函数对应的数据类型
for(int i = 0; i < slctagrfunc.size(); i++){
list_type.push_back(slctagrfunc[i]);
//这三种全部按double处理
if(agrfuntype[i] == "avg" || agrfuntype[i] == "sum" || agrfuntype[i] == "count"){
list_real_type.push_back("double");
}
//min和max要去找参数对应的数据类型
else{
QString type;
for(int j = 0; j < list_type.size(); j++){
if(agrfunprpt[i] == list_type[j]){
type = list_real_type[j];
}
}
list_real_type.push_back(type);
}
}
qDebug() << "所有列名:" << list_type;
qDebug() << "列对应的数据类型" << list_real_type;
if(slctagrfunc.size() > 0 && groups.size() == 0 && slctagrfunc.size() < properties.size()){
QMessageBox::warning(this, "警告", "非聚合函数属性必须包含在 GROUP BY 子句中");
return;
}
//开始遍历real_group, 添加聚合函数
for(int m = 0; m < agrfuntype.size(); m++){
for(int i = 0; i < real_group.size(); i++){
int agrcount = 0;
double agrsum = 0;
double agravg = 0;
QString min;
QString max;
double nummin;
double nummax;
bool isnum = true;
bool initminmax = false;
int index = findIndex(agrfunprpt[m], list_type);
int tempi = 0;
while(initminmax == false){
if(real_group[i][tempi][index] != "NULL"){
initminmax = true;
if(list_real_type[index] == "double" || list_real_type[index] == "int"){
nummin = real_group[i][tempi][index].toDouble();
nummax = real_group[i][tempi][index].toDouble();
//qDebug() << "nummax:" << nummax << " nummin:" << nummin;
}
else{
isnum = false;
min = real_group[i][tempi][index];
max = real_group[i][tempi][index];
//qDebug() << "max:" << max << " min:" << min;
}
}
else{
tempi++;
}
}
for(int j = 0; j < real_group[i].size(); j++){
//如果count中的属性非空则agrcount++
//qDebug() << "index:" <<index;
if(real_group[i][j][index] != "NULL"){
agrcount++;
if(isnum == true){
agrsum = agrsum + real_group[i][j][index].toDouble();
if(real_group[i][j][index].toDouble() > nummax){
nummax = real_group[i][j][index].toDouble();
}
if(real_group[i][j][index].toDouble() < nummin){
nummin = real_group[i][j][index].toDouble();
}
//qDebug() << "nummax:" << nummax << " nummin:" << nummin;
}
else{
if(real_group[i][j][index] > max){
max = real_group[i][j][index];
}
if(real_group[i][j][index] < min){
min = real_group[i][j][index];
}
//qDebug() << "max:" << max << " min:" << min;
}
}
}
//qDebug() << "count:" << agrcount;
QString strcount = QString::number(agrcount);
QString strsum = QString::number(agrsum);
QString stravg = QString::number(agravg);
//如果count为0则全为NULL
if(agrcount == 0){
stravg = "NULL";
strsum = "NULL";
min = "NULL";
max = "NULL";
}
else{
stravg = QString::number(agrsum/agrcount);
}
//将值写入real_group中
for(int l = 0; l < real_group[i].size(); l++){
if(agrfuntype[m] == "count"){
real_group[i][l].push_back(strcount);
}
if(agrfuntype[m] == "sum"){
real_group[i][l].push_back(strsum);
}
if(agrfuntype[m] == "avg"){
real_group[i][l].push_back(stravg);
}
if(isnum == true){
if(agrfuntype[m] == "min"){
real_group[i][l].push_back(QString::number(nummin));
}
if(agrfuntype[m] == "max"){
real_group[i][l].push_back(QString::number(nummax));
}
}
else{
if(agrfuntype[m] == "min"){
real_group[i][l].push_back(min);
}
if(agrfuntype[m] == "max"){
real_group[i][l].push_back(max);
}
}
}
}
}
//qDebug() << real_group;
//having
if(!havings.empty() && !real_group.empty()){
for(int z = 0; z < real_group.size(); z++){
QVector<QVector<QString>> having_split; // 将表达式分开
for(int i = 0; i < havings.size(); i++){
if(havings[i].contains("<=")){
QRegExp judge_having("(.+)(<=)(.+)");
if(!judge_having.exactMatch(havings[i])){
QMessageBox::warning(this, "警告", "Having 条件无效");
return;
} else {
QVector<QString> having_temp;
having_temp.push_back(judge_having.cap(1));
having_temp.push_back(judge_having.cap(2));
having_temp.push_back(judge_having.cap(3));
having_split.push_back(having_temp);
}
} else if(havings[i].contains(">=")){
QRegExp judge_having("(.+)(>=)(.+)");
if(!judge_having.exactMatch(havings[i])){
QMessageBox::warning(this, "警告", "HAVING 条件无效");
return;
} else {
QVector<QString> having_temp;
having_temp.push_back(judge_having.cap(1));
having_temp.push_back(judge_having.cap(2));
having_temp.push_back(judge_having.cap(3));
having_split.push_back(having_temp);
}
} else if(havings[i].contains("!=")){
QRegExp judge_having("(.+)(!=)(.+)");
if(!judge_having.exactMatch(havings[i])){
QMessageBox::warning(this, "警告", "HAVING 条件无效");
return;
} else {
QVector<QString> having_temp;
having_temp.push_back(judge_having.cap(1));
having_temp.push_back(judge_having.cap(2));
having_temp.push_back(judge_having.cap(3));
having_split.push_back(having_temp);
}
} else {
QRegExp judge_having("(.+)(=|<|>)(.+)");
if(!judge_having.exactMatch(havings[i])){
QMessageBox::warning(this, "警告", "HAVING 条件无效");
return;
} else {
QVector<QString> having_temp;
having_temp.push_back(judge_having.cap(1));
having_temp.push_back(judge_having.cap(2));
having_temp.push_back(judge_having.cap(3));
having_split.push_back(having_temp);
}
}
}
//qDebug() << where_split;
//开始进行筛选
//符合条件的数据有6种,分别为列名 表名.列 int和double算一种(-2) bool(false和true)(-3) varchar和datatime算一种(-1),-10代表无效数据类型
//首先判断有没有单引号 有单引号分两种 不过我不需要判断
//首先判断有没有. 如果有.
vector<QPair<int, int>> having_lr_type;
QRegExp agrre("(avg|sum|count|max|min)\\((\\w+)\\)");
for (int i = 0; i < having_split.size(); i++){
int left_type = -10, right_type = -10;
QRegExp string_or_not_left("^'(.+)'$");
QRegExp string_or_not_right("^'(.+)'$");
bool isNumber1 = false;
bool isNumber2 = false;
double d1 = having_split[i][0].toDouble(&isNumber1);
double d2 = having_split[i][2].toDouble(&isNumber2);
if(string_or_not_left.exactMatch(having_split[i][0])){ //判断左端是什么类型
left_type = -1;
} else if(isNumber1){
left_type = -2;
} else if(having_split[i][0] == "false" || having_split[i][0] == "true"){
left_type = -3;
} else if(agrre.exactMatch(having_split[i][0])){
left_type = findIndex(having_split[i][0], list_type);
} else { //下面判断这个字符串是不是列名
if(having_split[i][0].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(having_split[i][0] == list_type[j]){
left_type = j;
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = having_split[i][0];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
having_split[i][0] = (*temp_left).cap(1) + "." + having_split[i][0];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
} //else 的括号
// qDebug() << "left" ;
// qDebug() << left_type ;
// qDebug() << where_split[i][0];
//判断右边
if(string_or_not_right.exactMatch(having_split[i][2])){ //判断左端是什么类型
right_type = -1;
} else if(isNumber2){
right_type = -2;
} else if(having_split[i][2] == "false" || having_split[i][2] == "true"){
right_type = -3;
} else if(agrre.exactMatch(having_split[i][0])){
right_type = findIndex(having_split[i][0], list_type);
} else { //下面判断这个字符串是不是列名
if(having_split[i][2].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(having_split[i][2] == list_type[j]){
right_type = j;
break;
}
}
if(right_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = having_split[i][2];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
right_type = j;
having_split[i][2] = (*temp_left).cap(1) + "." + having_split[i][2];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(right_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
} //else 的括号
// qDebug() << "right" ;
// qDebug() << right_type ;
// qDebug() << where_split[i][2];
having_lr_type.push_back(qMakePair(left_type, right_type));
} //for的括号
//qDebug() << where_lr_type;
//下面对where中的每个条件进行筛选
for(int i = 0; i < having_lr_type.size(); i++){
if(real_group[z].empty()){ //当没有数据的时候直接结束循环
break;
}
if(having_lr_type[i].first < 0 and having_lr_type[i].second < 0){ //当两个都不是列的时候
if(having_lr_type[i].first != having_lr_type[i].second && having_split[i][1] != "!="){
qDebug() << "hhhhhhhaaaaaaaaaaa" << having_lr_type;
QMessageBox::warning(this, "警告", "等号两边数据类型不一致");
return;
} else if(having_lr_type[i].first != having_lr_type[i].second && having_split[i][1] == "!="){
//qDebug() << "nothing hapened";
continue;
} else if(having_lr_type[i].first == having_lr_type[i].second){ //两边数据类型一致时进行判断
qDebug() << "1:" << having_split[i][0];
qDebug() << "2:" << having_split[i][2];
qDebug() << "3:" << -having_lr_type[i].first;
qDebug() << "4:" << having_split[i][1];
if(my_compare(having_split[i][0], having_split[i][2], -having_lr_type[i].first, having_split[i][1])){
//qDebug() << "yes";
continue;
} else {
//qDebug() << "buhuiba";
real_group[z].clear();
}
}
} else { //当两边可能出现列的时候
//三种情况 左列 右列 左右列
if(having_lr_type[i].first < 0 and having_lr_type[i].second >= 0){ //右边时列 左边不是列 将它反转一下
int lefthahaha = having_lr_type[i].first;
having_lr_type[i].first = having_lr_type[i].second;
having_lr_type[i].second = lefthahaha;
QString lefthehehe = having_split[i][0];
having_split[i][0] = having_split[i][2];
having_split[i][2] = lefthehehe;
}
if(having_lr_type[i].first >= 0 and having_lr_type[i].second < 0){ //左边时列 右边不是列
QString checktemp1, checktemp2;
QString checktemp3 = having_split[i][1];
checktemp1 = having_split[i][2];
qDebug() << checktemp1;
checktemp2 = list_real_type[(having_lr_type[i].first)];
qDebug() << checktemp2;
if(!checkMatch(checktemp2, checktemp1)){
QMessageBox::warning(this, "警告", "等号两边类型不匹配");
return;
} else{
int where_temp;
if(checktemp2 == "int") where_temp = 2;
else if(checktemp2 == "double") where_temp = 2;
else if(checktemp2.contains("varchar")) where_temp = 1;
else if(checktemp2 == "bool") where_temp = 3;
else if(checktemp2 == "datetime") where_temp = 1;
//qDebug() << where_lr_type[i].first << " fdasfsad";
QVector<int> wherehahaha;
for(int j = 0; j < real_group[z].size(); j++){
QString jtemp0 = real_group[z][j][having_lr_type[i].first];
if(where_temp == 1){ //喵咪咪
jtemp0 = QString("'%1'").arg(jtemp0);
qDebug() << jtemp0 << " here";
}
qDebug() << "why?" << jtemp0;
qDebug() << checktemp1;
qDebug() << where_temp;
qDebug() << checktemp3;
if(my_compare(jtemp0, checktemp1, where_temp, checktemp3)){
continue;
} else{
wherehahaha.push_back(j);
}
}
for(int j = wherehahaha.size() - 1; j >= 0; j--){ //注意这块删除需要从后往前删
//qDebug()<< j;
real_group[z].remove(wherehahaha[j]);
}
}
}
qDebug() << having_lr_type[i].second << "[]" << i;
if(having_lr_type[i].first >= 0 and having_lr_type[i].second >= 0){ //左边是列 右边是列
//先判断两个列类型是否相同
qDebug() << "prblm:" << having_lr_type;
QString judge_both_two_have_var1 = list_real_type[(having_lr_type[i].first)];
QString judge_both_two_have_var2 = list_real_type[(having_lr_type[i].second)];
if(list_real_type[(having_lr_type[i].first)].contains("varchar")) {
judge_both_two_have_var1 = "varchar";
}
if(list_real_type[(having_lr_type[i].second)].contains("varchar")){
judge_both_two_have_var2 = "varchar";
}
if(judge_both_two_have_var1 != judge_both_two_have_var2){
QMessageBox::warning(this, "警告", "等号两边类型不匹配");
return;
} else {
//qDebug() << "that is cool!";
QVector<int> wherehahaha;
QString checktemp2 = judge_both_two_have_var1;
int where_temp;
if(checktemp2 == "int") where_temp = 2;
else if(checktemp2 == "double") where_temp = 2;
else if(checktemp2.contains("varchar")) where_temp = 1;
else if(checktemp2 == "bool") where_temp = 3;
else if(checktemp2 == "datetime") where_temp = 1;
for(int j = 0; j < real_group[z].size(); j++){
QString judge_two_value1 = real_group[z][j][having_lr_type[i].first];
QString judge_two_value2 = real_group[z][j][having_lr_type[i].second];
QString judge_two_value3 = having_split[i][1];
if(my_compare(judge_two_value1, judge_two_value2, where_temp, judge_two_value3)){
continue;
} else {
wherehahaha.push_back(j);
}
}
for(int j = wherehahaha.size() - 1; j >= 0; j--){ //注意这块删除需要从后往前删
//qDebug()<< j;
real_group[z].remove(wherehahaha[j]);
}
}
}
}
}//where筛选的for括号
// qDebug() << real_result;
} // 2023 5 2 19.24 终于把where写完了 芜湖~
}
qDebug() << "last1" << groups;
qDebug() << "last2" << orders;
//order by
qDebug() << "finished" <<real_result;
real_result.clear();
for(int i = 0; i < real_group.size(); i++){
for(int j = 0; j < real_group[i].size(); j++){
real_result.push_back(real_group[i][j]);
}
}
if(orders.size() > 0){
for(int m = 0; m < orders.size(); m++){
int left_type = -10, right_type = -10;
QRegExp string_or_not_left("^'(.+)'$");
QRegExp string_or_not_right("^'(.+)'$");
bool isNumber1 = false;
bool isNumber2 = false;
if(orders[m].split(".").size() == 2){ //已经是表名.列的情况
for(int j = 0; j < list_type.size(); j++){ //判断有没有在表中,如果在表中。则返回在哪个位置
if(orders[m] == list_type[j]){
left_type = j;
break;
}
}
if(left_type == -10){//列不存在
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
} else { //当只是列的情况 这时候只能在一个表里面出现 要是出现多次就会报错
int count_table = 0; //判断在表里出现了几次
QString tempsda = orders[m];
for(int j = 0; j < list_type.size(); j++){
//qDebug() << "(.+)\\." + tempsda;
QRegExp* temp_left = new QRegExp("(.+)\\." + tempsda);
if((*temp_left).exactMatch(list_type[j])){
count_table++;
left_type = j;
orders[m] = (*temp_left).cap(1) + "." + orders[m];
}
}
//qDebug() << count_table;
if(count_table > 1){
QMessageBox::warning(this, "警告", "请指定列的表名");
return;
}
if(left_type == -10){
QMessageBox::warning(this, "警告", "列名不存在");
return;
}
}
}
QVector<int> indices;
QVector<QString> type;
for(int i = 0; i < orders.size(); i++){
indices.push_back(findIndex(orders[i], list_type));
type.push_back(list_real_type[findIndex(orders[i], list_type)]);
}
qDebug() << indices;
qDebug() << type;
qSort(real_result.begin(), real_result.end(), [&](const QVector<QString>& v1, const QVector<QString>& v2) {
return compare(v1, v2, indices, type);
});
//sort(real_result, indices);
real_group.clear();
real_group.push_back(real_result);
}
qDebug() << "\\\///";
qDebug() << real_result;
qDebug() << properties;
//select
QVector<int> slctprpts;
for(int i = 0; i < properties.size(); i++){
slctprpts.push_back(findIndex(properties[i], list_type));
}
displaytable(ui->tableView, real_result, list_type);
removeColumnsExcept(ui->tableView, slctprpts);
//removeColumns(ui->tableView);
}
//删除重复列(多表连接时)
void MainWindow::removeColumns(QTableView *tableView) {
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(tableView->model());
if (!model) {
return;
}
QSet<QString> columnNames;
for (int i = 0; i < model->columnCount(); ++i) {
QString columnName = model->headerData(i, Qt::Horizontal).toString();
if (columnName.contains('.')) {
columnName = columnName.split('.').last();
}
if (columnNames.contains(columnName)) {
model->removeColumn(i);
--i;
} else {
columnNames.insert(columnName);
}
}
}
//删除重复行,保留指定列(SELECT)
void MainWindow::removeColumnsExcept(QTableView* tableWidget, QVector<int> columnsToKeep) {
/*for (int i = tableWidget->columnCount() - 1; i >= 0; --i) {
if (!columnsToKeep.contains(i)) {
tableWidget->removeColumn(i);
}
}
QVector<QVector<QString>> tableData(tableWidget->rowCount(), QVector<QString>(tableWidget->columnCount()));
for (int i = 0; i < tableWidget->rowCount(); ++i)
{
for (int j = 0; j < tableWidget->columnCount(); ++j)
{
QTableWidgetItem* item = tableWidget->item(i, j);
if (item)
{
tableData[i][j] = item->text();
}
}
}
qDebug() << tableData;
QSet<QString> rowSet;
for (int i = 0; i < tableWidget->rowCount(); ++i)
{
QString rowString;
for (int j = 0; j < tableWidget->columnCount(); ++j)
{
QTableWidgetItem* item = tableWidget->item(i, j);
if (item)
{
rowString += item->text();
}
}
if (rowSet.contains(rowString))
{
tableWidget->removeRow(i);
--i;
}
else
{
rowSet.insert(rowString);
}
}*/
for (int i = tableWidget->model()->columnCount() - 1; i >= 0; --i) {
if (!columnsToKeep.contains(i)) {
tableWidget->model()->removeColumn(i);
}
}
QVector<QVector<QString>> tableData(tableWidget->model()->rowCount(), QVector<QString>(tableWidget->model()->columnCount()));
for (int i = 0; i < tableWidget->model()->rowCount(); ++i)
{
for (int j = 0; j < tableWidget->model()->columnCount(); ++j)
{
QModelIndex index = tableWidget->model()->index(i,j);
if (index.isValid())
{
tableData[i][j] = index.data().toString();
}
}
}
qDebug() << tableData;
QSet<QString> rowSet;
for (int i = 0; i < tableWidget->model()->rowCount(); ++i)
{
QString rowString;
for (int j = 0; j < tableWidget->model()->columnCount(); ++j)
{
QModelIndex index = tableWidget->model()->index(i,j);
if (index.isValid())
{
rowString += index.data().toString();
}
}
if (rowSet.contains(rowString))
{
tableWidget->model()->removeRow(i);
--i;
}
else
{
rowSet.insert(rowString);
}
}
}
//全局变量
QVector<int> sortColumns;
QVector<int> sortOrder;
//sort函数 orderby 用
bool MainWindow::compare(const QVector<QString>& v1, const QVector<QString>& v2)
{
for (int i = 0; i < sortColumns.size(); ++i) {
int col = sortColumns[i];
if (v1[col] != v2[col]) {
return v1[col] < v2[col];
}
}
return false;
}
void MainWindow::sort(QVector<QVector<QString>>& data, const QVector<int>& sortColumns)
{
::sortColumns = sortColumns;
::sortOrder.fill(1, sortColumns.size());
qSort(data.begin(), data.end(), [&](const QVector<QString>& v1, const QVector<QString>& v2) {
return compare(v1, v2);
});
}
//重载compare方法
bool MainWindow::compare(const QVector<QString>& v1, const QVector<QString>& v2, const QVector<int>& indices, const QVector<QString>& type) {
for (int i = 0; i < indices.size(); ++i) {
int index = indices[i];
if (v1[index] == "NULL") {
return true;
} else if (v2[index] == "NULL") {
return false;
} else if (v1[index] != v2[index]) {
if(type[i] != "int" && type[i] != "double"){
return v1[index] < v2[index];
}
else{
return v1[index].toDouble() < v2[index].toDouble();
}
}
}
return false;
}
//显示表格
void MainWindow::displaytable(QTableView *table, QVector<QVector<QString>> result_set, QStringList prpt){
/*table->clear();
table->setRowCount(result_set.size());
table->setColumnCount(prpt.size());
for (int j = 0; j < result_set.size(); j++) {
for(int k = 0; k < result_set[j].size(); k++){
QTableWidgetItem *item = new QTableWidgetItem(result_set[j][k]);
table->setItem(j, k, item);
}
}
table->setHorizontalHeaderLabels(prpt);*/
table->setModel(new QStandardItemModel(result_set.size(), prpt.size()));
for (int j = 0; j < result_set.size(); j++) {
for(int k = 0; k < result_set[j].size(); k++){
table->model()->setData(table->model()->index(j,k),result_set[j][k]);
}
}
for(int i = 0; i < prpt.size(); i++){
table->model()->setHeaderData(i, Qt::Horizontal, prpt[i]);
}
}
//返回指定列名在表中是第几列
int MainWindow::findIndex(QString prpt, QStringList list_type){
for(int i = 0; i < list_type.size(); i++){
if(prpt == list_type[i]){
int t = i;
return t;
}
}
return -1;
}
//返回两个QVector<QString>a,b中a除去所有b中部分的集合
QVector<QString> MainWindow::difference(QVector<QString> a, QVector<QString> b){
QVector<QString> diff;
for(int i = 0; i < a.size(); i++){
bool issame = false;
for(int j = 0; j < b.size(); j++){
if(a[i] == b[j]){
issame = true;
}
}
if(issame == false){
diff.push_back(a[i]);
}
}
return diff;
}
//去除QVector中重复元素
QVector<QString> MainWindow::removeDuplicates(QVector<QString> v) {
QSet<QString> s;
for (int i = 0; i < v.size(); ++i) {
s.insert(v[i]);
}
return s.toList().toVector();
}
//判断字符串是否在指定容器中
bool MainWindow::InVectorOrNot(QString str, QVector<QString> vec){
for(int i = 0; i < vec.size(); i++){
if(vec[i] == str)
return true;
}
return false;
}
QVector<QVector<QVector<QString>>> MainWindow::make_groups(QVector<QVector<QVector<QString>>> first_group, int where_should){
QVector<QVector<QVector<QString>>> second_group;
int map_count_temp2 = 0;//记录应该在哪一个组
for(int i = 0; i < first_group.size(); i++){
QMap<QString, QString> map2;
QMap<QString, int> map_temp2;
for(int j = 0; j < first_group[i].size(); j++){
if(!map2.count(first_group[i][j][where_should])){ //当不存在值一样的组的时候
map2.insert(first_group[i][j][where_should], first_group[i][j][where_should]);
map_temp2.insert(first_group[i][j][where_should], map_count_temp2);
QVector<QVector<QString>> store_group2_temp;
store_group2_temp.push_back(first_group[i][j]);
second_group.push_back(store_group2_temp);
map_count_temp2++;
} else { //当已经分好组的时候
QString group2_temp = first_group[i][j][where_should];
second_group[map_temp2.value(group2_temp)].push_back(first_group[i][j]);
}
}
}
return second_group;
}
bool MainWindow::my_compare(QString a, QString b, int type, QString op){
// 字符 1
// 数字 2
// 布尔 3
double a2, b2;
switch(type){
case 1:
if(op == "="){
if(a == b){
return true;
} else return false;
}
if(op == ">="){
if(a >= b){
return true;
} else return false;
}
if(op == "<="){
if(a <= b){
return true;
} else return false;
}
if(op == "!="){
if(a != b){
return true;
} else return false;
}
if(op == "<"){
if(a < b){
return true;
} else return false;
}
if(op == ">"){
if(a > b){
return true;
} else return false;
}
break;
case 2 :
a2 = a.toDouble();
b2 = b.toDouble();
if(op == "="){
if(a2 == b2){
return true;
} else return false;
}
if(op == ">="){
if(a2 >= b2){
return true;
} else return false;
}
if(op == "<="){
if(a2 <= b2){
return true;
} else return false;
}
if(op == "!="){
if(a2 != b2){
return true;
} else return false;
}
if(op == "<"){
if(a2 < b2){
return true;
} else return false;
}
if(op == ">"){
if(a2 > b2){
return true;
} else return false;
}
break;
case 3 :
if(a == "false"){
a2 = 0;
} else{
a2 = 1;
}
if(b == "false"){
b2 = 0;
} else {
b2 = 1;
}
if(op == "="){
if(a2 == b2){
return true;
} else return false;
}
if(op == ">="){
if(a2 >= b2){
return true;
} else return false;
}
if(op == "<="){
if(a2 <= b2){
return true;
} else return false;
}
if(op == "!="){
if(a2 != b2){
return true;
} else return false;
}
if(op == "<"){
if(a2 < b2){
return true;
} else return false;
}
if(op == ">"){
if(a2 > b2){
return true;
} else return false;
}
break;
}
}
QVector<QString> MainWindow::cross(QVector<QString> a, QVector<QString> b){ //两个集合进行笛卡尔积
QVector<QString> result;
for(int i = 0; i < a.size(); i++){
for(int j = 0; j < b.size(); j++){
result.push_back(a[i] + ", " + b[j]);
}
}
return result;
}
void MainWindow::deleted_parser(QString s) {
QRegExp rx("\\s*delete\\s+from\\s+(\\w+)(.+)?;$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "不符合 DELETE 语法");
return;
}
QString name = rx.cap(1);
qDebug() << "name " << name << "\n";
//寻找需要删除的表的表名是否存在
QFile file(types::current_path + current_database + "/tables.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!\n";
return;
}
bool b = false;//如果没有找到此表名则为false
file.seek(0);
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == name) {
b = true;
}
}
qDebug() << "ok";
if (!b) {
QMessageBox::warning(this, "警告", "需要进行delete的表不存在!");
return;
}
file.close();
stream.flush();
//读取所有的被外键使用的键,当想要删除这些列的时候不允许
vector<QString> fedk;
QFile file_fedk(types::current_path + current_database + "/" + name + "/foreigned_key.csv");
QTextStream stream_fedk(&file_fedk);
if (!file_fedk.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the user.csv!\n";
return;
}
file_fedk.seek(0);
while (!stream_fedk.atEnd()) {
QStringList list = stream_fedk.readLine().split(",");
fedk.push_back(list[1]);//读取的每行第一个为约束名字第二个为参考的列名
}
if (!fedk.empty()) {
QMessageBox::warning(this, "警告", "由于此表被其他表参照了不能进行删除操作!");
return;
}
//读取此表中的所有数据
QFile file2(types::current_path + current_database + "/" + name + "/user.csv");
QTextStream stream2(&file2);
vector<vector<QString>> data;//用于存储表中的所有信息
vector<QString> col_names;//用于存储表的所有列名
vector<QString> col_types;//用于存储表中的所有列对应的类型
if (!file2.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the user.csv!\n";
return;
}
file2.seek(0);
while (!stream2.atEnd()) {
QString cur = stream2.readLine();// 读取一行数据库名字
QStringList list_data = cur.split(",");
vector<QString> l;
for (QString ss : list_data) {
l.push_back(ss);
}
data.push_back(l);
}
file2.close();
stream2.flush();
for (auto it : data) {
for (auto it2 : it) {
qDebug() << it2 << " ";
}
qDebug() << "\n";
}
//读取此表中的属性名
QFile file3(types::current_path + current_database + "/" + name + "/type.csv");
QTextStream stream3(&file3);
if (!file3.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the type.csv!\n";
return;
}
qDebug() << "seek";
file3.seek(0);
QString cur = stream3.readLine();
QStringList cols = cur.split(",");
for (QString ss : cols) {
col_names.push_back(ss);
}
cur = stream3.readLine();
QStringList col_tys = cur.split(",");
for (QString ss : col_tys) {
col_types.push_back(ss);
}
qDebug() << "**ok";
//判断是否存在where语句如果不存在则是删除整张表的数据
if (rx.cap(2) == NULL) {
QFile file4(types::current_path + current_database + "/" + name + "/user.csv");
QTextStream stream4(&file4);
if (!file4.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!" << "\n";
return;
}
qDebug() << "delete all data!\n";
} else {
//对where方法进行解析
QString temp = rx.cap(2);
qDebug() << "temp " << temp << "\n";
QRegExp r("\\s*where\\s+(.+)");
if (!r.exactMatch(temp)) {
QMessageBox::warning(this, "警告", "不符合 DELETE 语法");
return;
}
QStringList conditions = r.cap(1).split("and");//根据and进行对where条件分割
vector<QString> condition(col_names.size(), "null");//用于存储where中被设为条件的列值,没有被设置的则为NULL
vector<bool> vis(col_names.size(), true);//表示每行符合condition的列,如果比较完,完全为true则表示此行是需要删除的
vector<QString> signal(col_names.size());
vector<int> deleted_row;//记录需要删除的行
for (QString x : conditions) {
x.replace(" ", "");
//int eq_pos = x.toStdString().find("<=");
if (x.toStdString().find("<=") != -1) {
int pos_t = x.toStdString().find("<=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "<=";
break;
}
}
} else if (x.toStdString().find(">=") != -1) {
int pos_t = x.toStdString().find(">=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = ">=";
break;
}
}
} else if (x.toStdString().find("=") != -1) {
int pos_t = x.toStdString().find("=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "=";
break;
}
}
} else if (x.toStdString().find("<") != -1) {
int pos_t = x.toStdString().find("<");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "<";
break;
}
}
} else if (x.toStdString().find(">") != -1) {
int pos_t = x.toStdString().find(">");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "DELETE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = ">";
break;
}
}
}
}
qDebug() << "finished";
for (int i = 0; i < data.size(); ++i) {
vector<bool> t = vis;
for (int j = 0; j < data[0].size(); ++j) {
if (condition[j] != "null"/* && data[i][j] == condition[j]*/) {
// t[j] = true;
if (signal[j] == "=" && data[i][j] == condition[j]) {
t[j] = true;
} else if (signal[j] == ">=" && data[i][j] >= condition[j]) {
t[j] = true;
} else if (signal[j] == "<=" && data[i][j] <= condition[j]) {
t[j] = true;
} else if (signal[j] == "<" && data[i][j] < condition[j]) {
t[j] = true;
} else if (signal[j] == ">" && data[i][j] > condition[j]) {
qDebug() << "finished to";
t[j] = true;
qDebug() << j << " " << t[j];
}
}
}
//判断如果t全为true则此行需要删除
if (std::find(t.begin(), t.end(), false) == t.end()) {
deleted_row.push_back(i);
qDebug() << i;
}
}
QFile file4(types::current_path + current_database + "/" + name + "/user.csv");
QTextStream stream4(&file4);
if (!file4.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!" << "\n";
return;
}
for (int i = 0; i < data.size(); ++i) {
//如果此行不在需要删除的集合中,则将其写如文件
if (std::find(deleted_row.begin(), deleted_row.end(), i) == deleted_row.end()) {
for (int j = 0; j < data[i].size(); ++j) {
stream4 << data[i][j] << (j == data[i].size() - 1 ? "\n" : ",");
}
}
}
}
}
void MainWindow::droped_parser(QString s) {
QRegExp rx("\\s*drop\\s+(table|database)\\s+(\\w+)\\s*;$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "不符合drop的语法规范!");
return;
}
QString type_drop = rx.cap(1);//捕获drop是删除的表还是数据库
//将当前数据库下的所有表或者时数据库的名称读入数组
vector<QString> names;
if (type_drop == "table") {
QString table_name = rx.cap(2);//获得表名
QFile file(types::current_path + current_database + "/tables.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the tables.csv!\n";
return;
}
//将指针指向第一行数据
file.seek(0);
while (!stream.atEnd()) {
QString cur = stream.readLine();
names.push_back(cur);
}
if (std::find(names.begin(), names.end(), table_name) != names.end()) {
//需要判断是否此表中存在被外键约束的情况
QFile file_ex(types::current_path + current_database + "/" + table_name + "/foreigned_key.csv");
if (file_ex.exists()) {
QTextStream stream_ex(&file_ex);
file_ex.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text);
file_ex.seek(0);
if (!stream_ex.atEnd()) {
QMessageBox::warning(this, "警告", "此表被其他表设为了被参照表因此不允许删除!");
return;
} else {
names.erase(names.begin() + (std::find(names.begin(), names.end(), table_name) - names.begin()));
}
} else {
names.erase(names.begin() + (std::find(names.begin(), names.end(), table_name) - names.begin()));
}
} else {
QMessageBox::warning(this, "警告", "表名不存在!");
return;
}
QFile file2(types::current_path + current_database + "/tables.csv");
QTextStream stream2(&file2);
if (!file2.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the tables.csv!\n";
return;
}
for (QString x : names) {
stream2 << x << "\n";
}
QDir dir(types::current_path + current_database + "/" + table_name);
dir.removeRecursively();
qDebug() << "succeed to remove the table!";
} else if (type_drop == "database") {
QString name_database = rx.cap(2);
QFile file(types::current_path + "ban.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
qDebug() << "fail to open the ban.csv!";
return;
}
file.seek(0);
vector<QString> f;
while (!stream.atEnd()) {
QString cur = stream.readLine();
f.push_back(cur);
}
// QDir dir(types::current_path + name_database);
if (std::find(f.begin(), f.end(), name_database) != f.end()) {
QDir dir(types::current_path + name_database);
QFile out_file(types::current_path + "ban.csv");
QTextStream out(&out_file);
if (!out_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the ban.csv!";
return;
}
for (int i = 0; i < f.size(); ++i) {
if (f[i] != name_database) {
out << f[i] << "\n";
qDebug() << f[i];
}
}
//如果此文件夹存在则删除(数据库)并且需要重新指定当前操作的数据库
dir.removeRecursively();
current_database = "";
} else {
QMessageBox::warning(this, "警告", "此数据库不存在!");
return;
}
}
ini_tree();
}
void MainWindow::table_esixt(QString tablename){
QFile file(types::current_path + current_database + "/tables.csv");
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
//打开不成功
qDebug() << "fail to open the tables.csv!\n";
return;
}
bool b = false;//如果没有找到此表名则为false
file.seek(0);
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == tablename) {
b = true;
}
}
qDebug() << "ok";
if (!b) {
QMessageBox::warning(this, "警告", "需要进行 UPDATE 的表不存在");
return;
}
file.close();
stream.flush();
}
void MainWindow::updated_parser(QString s) {
if(s.contains("where")){
QRegExp rx("\\s*update\\s+(\\w+)\\s+set\\s+(.+)\\s+where\\s+(.+);$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "不符合 UPDATE 语法");
return;
}
// 要修改的表的表名
QString tablename = rx.cap(1);
table_esixt(tablename);
//读取此表中的所有数据
vector<vector<QString>> data;//用于存储表中的所有信息
vector<QString> col_names;//用于存储表的所有列名
vector<QString> col_types;//用于存储表中的所有列对应的类型
QFile file1(types::current_path + current_database + "/" + tablename + "/type.csv");
QTextStream stream1(&file1);
if (!file1.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the type.csv!\n";
return;
}
qDebug() << "seek";
file1.seek(0);
//读取列名
QString cur = stream1.readLine();
QStringList cols = cur.split(",");
for (QString ss : cols) {
col_names.push_back(ss);
}
//读取属性类型
cur = stream1.readLine();
QStringList col_tys = cur.split(",");
for (QString ss : col_tys) {
col_types.push_back(ss);
}
qDebug() << "**ok";
//读取记录
QFile file2(types::current_path + current_database + "/" + tablename + "/user.csv");
QTextStream stream2(&file2);
if (!file2.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the user.csv!\n";
return;
}
file2.seek(0);
while (!stream2.atEnd()) {
QString cur = stream2.readLine();
QStringList list_data = cur.split(",");
vector<QString> l;
for (QString ss : list_data) {
l.push_back(ss);
}
data.push_back(l);
}
file2.close();
stream2.flush();
for (auto it : data) {
for (auto it2 : it) {
qDebug() << it2 << " ";
}
qDebug() << "\n";
}
//对where进行解析
QStringList conditions = rx.cap(3).split("and"); //根据and进行对where条件分割
vector<QString> condition(col_names.size(), "null"); //用于存储where中被设为条件的列值,没有被设置的则为NULL
vector<bool> vis(col_names.size(), true); //表示每行符合condition的列,如果比较完,完全为true则表示此行是需要修改的
vector<QString> signal(col_names.size()); //记录<=,>=,=,<,>
vector<int> update_row;//记录需要修改的行
for (QString x : conditions) {
x.replace(" ", "");
if (x.toStdString().find("<=") != -1) {
int pos_t = x.toStdString().find("<=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "<=";
break;
}
}
} else if (x.toStdString().find(">=") != -1) {
int pos_t = x.toStdString().find(">=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = ">=";
break;
}
}
} else if (x.toStdString().find("=") != -1) {
int pos_t = x.toStdString().find("=");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "=";
break;
}
}
} else if (x.toStdString().find("<") != -1) {
int pos_t = x.toStdString().find("<");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = "<";
break;
}
}
} else if (x.toStdString().find(">") != -1) {
int pos_t = x.toStdString().find(">");
QString colName = x.mid(0, pos_t);//where中的列名
qDebug() << "colName " << colName << "\n";
QString colData = x.mid(pos_t + 1, x.size() - pos_t - 1);//where中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 WHERE 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
condition[i] = colData;
vis[i] = false;
signal[i] = ">";
break;
}
}
}
}
qDebug() << "finished";
for (int i = 0; i < data.size(); ++i) {
vector<bool> t = vis;
for (int j = 0; j < data[0].size(); ++j) {
if (condition[j] != "null") {
if (signal[j] == "=" && data[i][j] == condition[j]) {
t[j] = true;
} else if (signal[j] == ">=" && data[i][j] >= condition[j]) {
t[j] = true;
} else if (signal[j] == "<=" && data[i][j] <= condition[j]) {
t[j] = true;
} else if (signal[j] == "<" && data[i][j] < condition[j]) {
t[j] = true;
} else if (signal[j] == ">" && data[i][j] > condition[j]) {
qDebug() << "finished to";
t[j] = true;
qDebug() << j << " " << t[j];
}
}
}
//判断如果t全为true则此行需要修改
if (std::find(t.begin(), t.end(), false) == t.end()) {
update_row.push_back(i);
qDebug() << i;
}
}
if(update_row.size() == 0){
QMessageBox::warning(this, "警告", "未找到需要修改的记录");
return;
}
//检查主键
bool hasPri=0;
QFile primaryfile(types::current_path + current_database + "/" +tablename+"/primary_key.csv");
if (!primaryfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the primary_key.csv!\n";
return;
}
QTextStream * priread = new QTextStream(&primaryfile);
QString priData = priread->readLine();
vector<QString> pricolName;//存复合主键的每个列名
if(priData.size()==0){
qDebug()<<"主键为空";
hasPri=0;
}else{
hasPri=1;
qDebug()<<"主键非空";
QString colN = priData;// 存第一行,即复合主键[0]
qDebug()<<"主键属性 ["<<colN<<"]";
//colN.remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList priColName = colN.split(",");//获取每行信息
for(int i=1;i<priColName.length();i++){//下标0存主键约束名
pricolName.push_back(priColName.at(i));
}
qDebug()<<"主键"<<pricolName;
primaryfile.close();
}
//检查外键
bool hasFor=0;
vector<vector<QString>> foreignKeys;//可能有多个外键, 内层容量为3,约束名、参照列、被参照表、被参照列
QFile Foreignfile(types::current_path + current_database + "/" +tablename+"/foreign_key.csv");
if (!Foreignfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the foreign_key.csv!\n";
return;
}
QTextStream * forread = new QTextStream(&Foreignfile);
QStringList forData = forread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//forData.removeAll(QRegExp("\\s"));
QString firstData = forread->readLine();
qDebug()<<"外键文件 firstData"<<firstData;
if(forData.size()==0){
qDebug()<<"11外键为空";hasFor=0;
} else{
qDebug()<<"外键非空";hasFor=1;
vector<QString> fk;
qDebug()<<"forData.size()="<<forData.size();
for(int i=0;i<forData.size();i++){
forData[i].remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList forConLine = forData[i].split(",");
fk.erase(fk.begin(),fk.end());
for(int j=1;j<=3;j++){
fk.push_back(forConLine.at(j));
//存每一个外键:参照列、被参照表、被参照列
}
foreignKeys.push_back(fk);
}
qDebug()<<"外键约束foreignkeys="<<foreignKeys;
Foreignfile.close();
}
//检查notnull
QFile constraintfile(types::current_path + current_database + "/" +tablename+"/constraint.csv");
if (!constraintfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the constraint.csv!\n";
return;
}
constraintfile.seek(0);
QTextStream * conread = new QTextStream(&constraintfile);
QStringList ConData = conread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString condataline = conread->readLine();
ConData[0].remove(QRegExp("\\s"));
QStringList ConCollist = ConData.at(0).split(",");//约束限制,null/notnull
qDebug()<<"null约束="<<ConCollist;
constraintfile.close();
//检查是否有列被参考
int hasFored = 0;
QFile foreignedfile(types::current_path + current_database + "/" +tablename+"/foreigned_key.csv");
if (!foreignedfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the foreigned_key.csv!\n";
hasFored = 0;
}
vector<QString> foreignedKeys; //存被参考的列
QTextStream * foredread = new QTextStream(&foreignedfile);
QString foredData = foredread->readLine();
if(foredData.size()!=0){
hasFored = 1;
QStringList foredColName = foredData.split(",");//获取每行信息
for(int i=1;i<foredColName.length();i++){//下标0存约束名
foreignedKeys.push_back(foredColName.at(i));
}
}
foreignedfile.close();
//对set进行解析
QStringList sets = rx.cap(2).split(","); //根据","对set分割
vector<bool> sis(col_names.size(), false); //如果为true,则表示可以修改
vector<QString> set(col_names.size(), "null"); //用于存储修改后的值,不能被修改的则为NULL
for (QString sx : sets) {
sx.replace(" ", "");
int pos_t = sx.toStdString().find("=");
QString colName = sx.mid(0, pos_t);//set中的列名
qDebug() << "colName " << colName << "\n";
QString colData = sx.mid(pos_t + 1, sx.size() - pos_t - 1);//set中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
//检查列是否被参考
if(hasFored!=0){
for(int i=0;i< foreignedKeys.size();i++){
if(colName == foreignedKeys[i]){
QMessageBox::warning(this, "警告", "修改失败!此列被参考,不能修改");
return;
}
}
}
//检查notnull的是否被修改为null
for(int i=0;i<ConCollist.length();i++){
if(ConCollist.at(i)=="notnull"){
//寻找这是哪个列
if(colName == col_names[i] && colData == "null"){
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 输入的值违反了约束条件!");
return;
}
}
}
//检查外键
if(hasFor!=0){
for(int i=0;i<foreignKeys.size();i++){
//检查每一个外键 ForeignKeys:参照列、被参照表、被参照列
if(colName == foreignKeys[i].at(0)){
if(!CheckForeignKey(colData,foreignKeys[i].at(1),foreignKeys[i].at(2))){
QMessageBox::warning(this, "警告", "修改失败!违反完整性约束(外键找不到参照)");
return;
}
}
}
}
// 需要修改的列
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
set[i] = colData;
sis[i] = true;
break;
}
}
}
//检查对主键的修改
if(hasPri != 0){ //表中有主键
vector<QString> pricol; //修改的主键名
vector<QString> priset; //修改的主键值
for(int i = 0; i < col_names.size();i++){
if(sis[i] == true){
for(int j = 0; j < pricolName.size(); j++){
if(col_names[i] == pricolName[j]){ //修改了主键
if(update_row.size() >= 2){ //修改多条记录,主键相同
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
if(set[i] == "null"){ //主键为空
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
pricol.push_back(col_names[i]);
priset.push_back(set[i]);
break;
}
}
}
}
vector<vector<QString>> pri;//存修改的主键对应的userdata
//将修改的主键的userdata数据写入vector<vector<QString>> pri;
QFile userfile(types::current_path + current_database + "/" +tablename+"/user.csv");
if (!userfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the user.csv!\n";
return;
}
QTextStream * userread = new QTextStream(&userfile);
QStringList userData = userread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
if(userData.size()!=0){
for(int i=0;i<userData.length();i++){//外层遍历userdata
userData[i].remove(QRegExp("\\s"));
vector<QString> useritem;
useritem.erase(useritem.begin(),useritem.end());// 清空
QStringList singleitem = userData[i].split(",");//userdata的一行
for(int j=0;j<pricol.size();j++){//内层遍历主键
for(int k = 0; k<col_names.size();k++){
if(pricol[j] == col_names[k]){
useritem.push_back(singleitem.at(k));
break;
}
}
}
pri.push_back(useritem);// 写入二维数组
}
qDebug()<<" 外层 "<<pri;
}
userfile.close();
int sum[userData.length()];
for(int i = 0; i < userData.length();i++){
sum[i] = 0;
}
for(int j = 0; j < pricol.size(); j++){
for(int i = 0; i < userData.length(); i++){
qDebug()<<pri[0][0];
qDebug()<<priset[j];
qDebug()<<sum[i];
if(priset[j] == pri[i][j]){
sum[i]++;
if(sum[i] == pricol.size()){ //主键值完全相同
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
}
}
}
}
for(int j = 0; j < update_row.size(); j++){
for(int i = 0; i < col_names.size();i++){
if(sis[i] == true){
data[update_row[j]][i] = set[i];
}
}
}
// 重写
QFile file4(types::current_path + current_database + "/" + tablename + "/user.csv");
QTextStream stream4(&file4);
if (!file4.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!" << "\n";
return;
}
for (int i = 0; i < data.size(); ++i) {
for (int j = 0; j < data[i].size(); ++j) {
stream4 << data[i][j] << (j == data[i].size() - 1 ? "\n" : ",");
}
}
} else {
QRegExp rx("\\s*update\\s+(\\w+)\\s+set\\s+(.+);$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "不符合 UPDATE 语法");
return;
}
// 要修改的表的表名
QString tablename = rx.cap(1);
table_esixt(tablename);
//读取此表中的所有数据
vector<vector<QString>> data;//用于存储表中的所有信息
vector<QString> col_names;//用于存储表的所有列名
vector<QString> col_types;//用于存储表中的所有列对应的类型
QFile file1(types::current_path + current_database + "/" + tablename + "/type.csv");
QTextStream stream1(&file1);
if (!file1.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the type.csv!\n";
return;
}
qDebug() << "seek";
file1.seek(0);
//读取列名
QString cur = stream1.readLine();
QStringList cols = cur.split(",");
for (QString ss : cols) {
col_names.push_back(ss);
}
//读取属性类型
cur = stream1.readLine();
QStringList col_tys = cur.split(",");
for (QString ss : col_tys) {
col_types.push_back(ss);
}
qDebug() << "**ok";
//读取记录
QFile file2(types::current_path + current_database + "/" + tablename + "/user.csv");
QTextStream stream2(&file2);
if (!file2.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the user.csv!\n";
return;
}
file2.seek(0);
int sumrow = 0;//总行数
while (!stream2.atEnd()) {
QString cur = stream2.readLine();
sumrow ++;
QStringList list_data = cur.split(",");
vector<QString> l;
for (QString ss : list_data) {
l.push_back(ss);
}
data.push_back(l);
}
file2.close();
stream2.flush();
for (auto it : data) {
for (auto it2 : it) {
qDebug() << it2 << " ";
}
qDebug() << "\n";
}
vector<int> update_row;//需要修改的行
vector<bool> vis(col_names.size(), true); //表示每行符合condition的列,如果比较完,完全为true则表示此行是需要修改的
for(int i = 0; i < sumrow;i++){
update_row.push_back(i);
}
//检查主键
bool hasPri=0;
QFile primaryfile(types::current_path + current_database + "/" +tablename+"/primary_key.csv");
if (!primaryfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the primary_key.csv!\n";
return;
}
QTextStream * priread = new QTextStream(&primaryfile);
QString priData = priread->readLine();
vector<QString> pricolName;//存复合主键的每个列名
if(priData.size()==0){
qDebug()<<"主键为空";
hasPri=0;
}else{
hasPri=1;
qDebug()<<"主键非空";
QString colN = priData;// 存第一行,即复合主键[0]
qDebug()<<"主键属性 ["<<colN<<"]";
//colN.remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList priColName = colN.split(",");//获取每行信息
for(int i=1;i<priColName.length();i++){//下标0存主键约束名
pricolName.push_back(priColName.at(i));
}
qDebug()<<"主键"<<pricolName;
primaryfile.close();
}
//检查外键
bool hasFor=0;
vector<vector<QString>> foreignKeys;//可能有多个外键, 内层容量为3,约束名、参照列、被参照表、被参照列
QFile Foreignfile(types::current_path + current_database + "/" +tablename+"/foreign_key.csv");
if (!Foreignfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the foreign_key.csv!\n";
return;
}
QTextStream * forread = new QTextStream(&Foreignfile);
QStringList forData = forread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//forData.removeAll(QRegExp("\\s"));
QString firstData = forread->readLine();
qDebug()<<"外键文件 firstData"<<firstData;
if(forData.size()==0){
qDebug()<<"11外键为空";hasFor=0;
} else{
qDebug()<<"外键非空";hasFor=1;
vector<QString> fk;
qDebug()<<"forData.size()="<<forData.size();
for(int i=0;i<forData.size();i++){
forData[i].remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList forConLine = forData[i].split(",");
fk.erase(fk.begin(),fk.end());
for(int j=1;j<=3;j++){
fk.push_back(forConLine.at(j));
//存每一个外键:参照列、被参照表、被参照列
}
foreignKeys.push_back(fk);
}
qDebug()<<"外键约束foreignkeys="<<foreignKeys;
Foreignfile.close();
}
//检查notnull
QFile constraintfile(types::current_path + current_database + "/" +tablename+"/constraint.csv");
if (!constraintfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the constraint.csv!\n";
return;
}
constraintfile.seek(0);
QTextStream * conread = new QTextStream(&constraintfile);
QStringList ConData = conread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString condataline = conread->readLine();
ConData[0].remove(QRegExp("\\s"));
QStringList ConCollist = ConData.at(0).split(",");//约束限制,null/notnull
qDebug()<<"null约束="<<ConCollist;
constraintfile.close();
//检查是否有列被参考
int hasFored = 0;
QFile foreignedfile(types::current_path + current_database + "/" +tablename+"/foreigned_key.csv");
if (!foreignedfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the foreigned_key.csv!\n";
hasFored = 0;
}
vector<QString> foreignedKeys; //存在被参考的列
QTextStream * foredread = new QTextStream(&foreignedfile);
QString foredData = foredread->readLine();
if(foredData.size()!=0){
hasFored = 1;
QStringList foredColName = foredData.split(",");//获取每行信息
for(int i=1;i<foredColName.length();i++){//下标0存约束名
foreignedKeys.push_back(foredColName.at(i));
}
}
foreignedfile.close();
//对set进行解析
QStringList sets = rx.cap(2).split(","); //根据","对set分割
vector<bool> sis(col_names.size(), false); //如果为true,则表示可以修改
vector<QString> set(col_names.size(), "null"); //用于存储修改后的值,不能被修改的则为NULL
for (QString sx : sets) {
sx.replace(" ", "");
int pos_t = sx.toStdString().find("=");
QString colName = sx.mid(0, pos_t);//set中的列名
qDebug() << "colName " << colName << "\n";
QString colData = sx.mid(pos_t + 1, sx.size() - pos_t - 1);//set中的对应列名的值
if (std::find(col_names.begin(), col_names.end(), colName) == col_names.end()) {
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 输入的列名不存在!");
return;
}
if (!checkMatch(col_types[std::find(col_names.begin(), col_names.end(), colName) - col_names.begin()], colData)) {
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 输入的值不符合类型!");
return;
}
//如果值是一个varchar类型则需要去掉引号进行比较
if (colData[0] == '\'' && colData[colData.size() - 1] == '\'') {
colData = colData.mid(1, colData.size() - 2);
}
//检查列是否被参考
if(hasFored!=0){
for(int i=0;i< foreignedKeys.size();i++){
if(colName == foreignedKeys[i]){
QMessageBox::warning(this, "警告", "修改失败!此列被参考,不能修改");
return;
}
}
}
//检查notnull的是否被修改为null
for(int i=0;i<ConCollist.length();i++){
if(ConCollist.at(i)=="notnull"){
//寻找这是哪个列
if(colName == col_names[i] && colData == "null"){
QMessageBox::warning(this, "警告", "UPDATE 中的 SET 输入的值违反了约束条件!");
return;
}
}
}
//检查外键
if(hasFor!=0){
for(int i=0;i<foreignKeys.size();i++){
//检查每一个外键 ForeignKeys:参照列、被参照表、被参照列
if(colName == foreignKeys[i].at(0)){
if(!CheckForeignKey(colData,foreignKeys[i].at(1),foreignKeys[i].at(2))){
QMessageBox::warning(this, "警告", "修改失败!违反完整性约束(外键找不到参照)");
return;
}
}
}
}
// 需要修改的列
for (int i = 0; i < col_names.size(); ++i) {
if (colName == col_names[i]) {
set[i] = colData;
sis[i] = true;
break;
}
}
}
//检查对主键的修改
if(hasPri != 0){ //表中有主键
vector<QString> pricol; //修改的主键名
vector<QString> priset; //修改的主键值
for(int i = 0; i < col_names.size();i++){
if(sis[i] == true){
for(int j = 0; j < pricolName.size(); j++){
if(col_names[i] == pricolName[j]){ //修改了主键
if(update_row.size() >= 2){ //修改多条记录,主键相同
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
if(set[i] == "null"){ //主键为空
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
pricol.push_back(col_names[i]);
priset.push_back(set[i]);
break;
}
}
}
}
vector<vector<QString>> pri;//存修改的主键对应的userdata
//将修改的主键的userdata数据写入vector<vector<QString>> pri;
QFile userfile(types::current_path + current_database + "/" +tablename+"/user.csv");
if (!userfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the user.csv!\n";
return;
}
QTextStream * userread = new QTextStream(&userfile);
QStringList userData = userread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
if(userData.size()!=0){
for(int i=0;i<userData.length();i++){//外层遍历userdata
userData[i].remove(QRegExp("\\s"));
vector<QString> useritem;
useritem.erase(useritem.begin(),useritem.end());// 清空
QStringList singleitem = userData[i].split(",");//userdata的一行
for(int j=0;j<pricol.size();j++){//内层遍历主键
for(int k = 0; k<col_names.size();k++){
if(pricol[j] == col_names[k]){
useritem.push_back(singleitem.at(k));
break;
}
}
}
pri.push_back(useritem);// 写入二维数组
}
qDebug()<<" 外层 "<<pri;
}
userfile.close();
int sum[userData.length()];
for(int i = 0; i < userData.length();i++){
sum[i] = 0;
}
for(int j = 0; j < pricol.size(); j++){
for(int i = 0; i < userData.length(); i++){
qDebug()<<pri[0][0];
qDebug()<<priset[j];
qDebug()<<sum[i];
if(priset[j] == pri[i][j]){
sum[i]++;
if(sum[i] == pricol.size()){ //主键值完全相同
QMessageBox::warning(this, "警告", "修改失败!违反实体完整性");
return;
}
}
}
}
}
for(int j = 0; j < update_row.size(); j++){
for(int i = 0; i < col_names.size();i++){
if(sis[i] == true){
data[update_row[j]][i] = set[i];
}
}
}
// 重写
QFile file4(types::current_path + current_database + "/" + tablename + "/user.csv");
QTextStream stream4(&file4);
if (!file4.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!" << "\n";
return;
}
for (int i = 0; i < data.size(); ++i) {
for (int j = 0; j < data[i].size(); ++j) {
stream4 << data[i][j] << (j == data[i].size() - 1 ? "\n" : ",");
}
}
}
}
void MainWindow::on_run_btn_clicked()
{
QString s = ui->console->toPlainText();
s = s.toLower();
s.replace("\n", " ");
s.replace("\t", " ");
QRegExp rx("\\s*(create|select|update|delete|use|insert|alter|drop)\\s+.*;\\s*$");
if (!rx.exactMatch(s)) {
QMessageBox::warning(this, "警告", "请使用正确的 SQL 语法!");
return;
}
if (rx.cap(1) == "create") {
QRegExp r("(create)\\s+(table|database).*;\\s*$");
if (r.exactMatch(s)) {
QString type_created = r.cap(2);
if (type_created == "table" && current_database != "") {
created_parser(s, 1);
} else if (type_created == "database") {
created_parser(s, 2);
} else {
QMessageBox::warning(this, "警告", "请先选择数据库,或者创建数据库!");
return;
}
} else {
QMessageBox::warning(this, "警告", " CREATE 语法有问题!");
return;
}
} else if (rx.cap(1) == "select" && current_database != "") {
selected_parser(s);
} else if (rx.cap(1) == "update" && current_database != "") {
updated_parser(s);
} else if (rx.cap(1) == "delete" && current_database != "") {
deleted_parser(s);
} else if(rx.cap(1) == "insert" && current_database != ""){
if (current_database != "") {
inserted_parser(s);
//qDebug()<<insert_parser_2(s);
} else {
QMessageBox::warning(this, "警告", "请先选择数据库,或者创建数据库!");
return;
}
}else if (rx.cap(1) == "use") {
QRegExp r("\\s*(use)\\s+(\\w+)\\s*;\\s*$");
if (!r.exactMatch(s)) {
QMessageBox::warning(this, "警告", "请先选择数据库,或者创建数据库!");
return;
}
use_parser(r);
} else if (rx.cap(1) == "alter") {
QRegExp r("\\s*(alter)\\s+(table)\\s+(\\w+)\\s+.+;\\s*$");
if (r.exactMatch(s)) {
if (current_database != "") {
altered_parser(s);
} else {
QMessageBox::warning(this, "警告", "请先选择数据库,或者创建数据库!");
return;
}
} else {
QMessageBox::warning(this, "警告", "不符合 ALTER 语法!");
return;
}
} else if (rx.cap(1) == "drop") {
QRegExp r("\\s*drop\\s+(table|database)\\s+(\\w+)\\s*;\\s*$");
if (r.exactMatch(s)) {
if (current_database != "") {
droped_parser(s);
} else {
QMessageBox::warning(this, "警告", "请先选择数据库,或者创建数据库!");
return;
}
} else {
QMessageBox::warning(this, "警告", "不符合 DROP 语法!");
return;
}
}
}
void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
{
if (index.parent().isValid()) {
qDebug() << index.parent().data().toString();
qDebug() << index.data().toString();
clicked_database = index.parent().data().toString();//获得数据库的名字
clicked_table = index.data().toString();//获得表的名字
QFile file_table(types::current_path + clicked_database + "/" + clicked_table + "/user.csv");
QTextStream stream_table(&file_table);
if (!file_table.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the table .csv!";
return;
}
file_table.seek(0);
//存放我点击事件表的名字
clicked_datas.clear();
while (!stream_table.atEnd()) {
QStringList list = stream_table.readLine().split(",");
vector<QString> temp;
for (QString s : list) {
temp.push_back(s);
}
clicked_datas.push_back(temp);
}
//读取属性名
clicked_col.clear();
clicked_type.clear();
QFile file_col(types::current_path + clicked_database + "/" + clicked_table + "/type.csv");
QTextStream stream_col(&file_col);
if (!file_col.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "fail to open the type.csv!";
return;
}
file_col.seek(0);
QStringList list_col = stream_col.readLine().split(",");
for (QString s : list_col) {
clicked_col.push_back(s);
}
list_col = stream_col.readLine().split(",");
for (QString s : list_col) {
clicked_type.push_back(s);
}
qDebug() << "size : " << clicked_col.size();
//创建修改tableview
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(clicked_col.size());//设置列的长度
for (int i = 0; i < clicked_col.size(); ++i) {
model->setHeaderData(i, Qt::Horizontal, clicked_col[i]);
qDebug() << "clicked_col" << clicked_col[i];
}
ui->tableView->setModel(model);
for (int i = 0; i < clicked_datas.size(); ++i) {
QList<QStandardItem*> item;//添加一行
for (int j = 0; j < clicked_datas[i].size(); ++j) {
item.append(new QStandardItem(clicked_datas[i][j]));
}
model->appendRow(item);
}
ui->tableView->show();
} else {
qDebug() << "parent!";
}
clicked = true;
//等价使用use语句
current_database = clicked_database;
}
void MainWindow::on_tableView_doubleClicked(const QModelIndex &index)
{
}
bool MainWindow::insert_parser_2(QString s) {
QRegExp *ex=new QRegExp("insert\\s+into\\s+(\\w+)(\\(((\\w*,)*(\\w*))\\))?\\s*(values)\\s*\\((( ('.*',)|(.*,) )*('.'|.*))\\)\\;$");
if (!ex->exactMatch(s)) {
return false;
}//1是表名,2是列名们,7是值们
QFile file(types::current_path + current_database + "/tables.csv");
//换成自己的路径!! 运行程序时不要打开文件!!
QTextStream stream(&file);
if (!file.open(QIODevice::ReadOnly | QIODevice::Append | QIODevice::Text)) {
//打开不成功
qDebug() << "fail to open the tables.csv!\n";
return false;
}
QString tname=ex->cap(1);//第一个是表名
QString attri=ex->cap(2);//第二个是属性们(可能是空)(sno,cno,grade,fll)
attri.remove(QRegExp("\\s"));
QString values=ex->cap(7);//第七个是值们 而且有逗号(11,111,566)
qDebug()<<"attri="<<attri<<" values="<<values;
//找数据库有没有这个表
file.seek(0);
while (!stream.atEnd()) {
QString cur = stream.readLine();// 读取一行数据库名字
if (cur == tname) {
qDebug() << "succeed to find the table!\n"+tname;
}
}
file.close();//留着没啥用了,关了吧
QFile mfile(types::current_path + current_database + "/" +tname+"/type.csv");
if (!mfile.open(QIODevice::ReadOnly)) { //找表中的 元数据metadata并且存入 colinfo
//打开不成功
qDebug() << "fail to open the type.csv!\n";
return false;
}
map<int, pair<QString, QString>> colinfo;
QTextStream * read = new QTextStream(&mfile);
QStringList Data = read->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
Data[0].remove(QRegExp("\\s"));
Data[1].remove(QRegExp("\\s"));
QStringList strLine1 = Data.at(0).split(",");//获取每行信息 第一行是列名 第二行是属性 Data[0] "id,name"
QStringList strLine2 = Data.at(1).split(",");//第二行是对应的类型 一行中的单元格以,区分 Data[1] "int,varchar(8)"
//列号 起始为0!!!
for(int i=0;i<strLine1.length();i++){//把列的信息存进map<列号,pair<列名,类型>>里面
if(strLine1.at(i)!="")
colinfo.insert(pair<int, pair<QString, QString>>(i,pair<QString, QString>(strLine1.at(i),strLine2.at(i))));
}
mfile.close();
bool hasFor=0;
vector<vector<QString>> foreignKeys;//可能有多个主键, 内层容量为3,约束名、参照列、被参照表、被参照列
QFile Foreignfile(types::current_path + current_database + "/" +tname+"/foreign_key.csv");
if (!Foreignfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the foreign_key.csv!\n";
return false;
}
QTextStream * forread = new QTextStream(&Foreignfile);
QStringList forData = forread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//forData.removeAll(QRegExp("\\s"));
QString firstData = forread->readLine();
qDebug()<<"外键文件 firstData"<<firstData;
if(forData.size()==0){
qDebug()<<"11外键为空";hasFor=0;
}else{/*else if(firstData==""){
qDebug()<<"22外键为空";hasFor=0;
}*/
qDebug()<<"外键非空";hasFor=1;
vector<QString> fk;
qDebug()<<"forData.size()="<<forData.size();
for(int i=0;i<forData.size();i++){
forData[i].remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList forConLine = forData[i].split(",");
fk.erase(fk.begin(),fk.end());
for(int j=1;j<=3;j++){
fk.push_back(forConLine.at(j));
//存每一个外键:参照列、被参照表、被参照列
}
foreignKeys.push_back(fk);
}
qDebug()<<"外键约束foreignkeys="<<foreignKeys;
}
//检查主键
bool hasPri=0;
QFile primaryfile(types::current_path + current_database + "/" +tname+"/primary_key.csv");
if (!primaryfile.open(QIODevice::ReadOnly)) {//打开不成功
qDebug() << "fail to open the primary_key.csv!\n";
return false;
}
vector<vector<QString>> pri;//存主键对应的userdata
QTextStream * priread = new QTextStream(&primaryfile);
//QStringList priData = priread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString priData = priread->readLine();
vector<QString> pricolName;//存复合主键的每个列名
if(priData.size()==0){
qDebug()<<"主键为空";hasPri=0;
}else{
hasPri=1;
qDebug()<<"主键非空";
QString colN = priData;// 存第一行,即复合主键[0]
qDebug()<<"主键属性 ["<<colN<<"]";
//colN.remove(QRegExp("\\s"));//去掉最后一个的//r
QStringList priColName = colN.split(",");//获取每行信息 第一行是列名 第二行是属性
for(int i=1;i<priColName.length();i++){//下标0存的约束名,不管
pricolName.push_back(priColName.at(i));
}
qDebug()<<"主键"<<pricolName;
//将主键的userdata数据写入vector<vector<QString>> pri;
QFile userfile(types::current_path + current_database + "/" +tname+ "/user2.csv");
if (!userfile.open(QIODevice::ReadWrite)) {//打开不成功
//if (!userfile.open(QIODevice::ReadOnly|QIODevice::Append)) {//打开不成功 不存在则创建
qDebug() << "fail to open the user2.csv!\n";
return false;
}
//vector<vector<QString>> pri;//存主键 striLine1里面存了列
QTextStream * userread = new QTextStream(&userfile);
QStringList userData = userread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
//pri.erase(pri.begin(),pri.end());
qDebug()<<"userData.size()="<<userData.size();
if(userData.size()!=0){
for(int i=0;i<userData.length();i++){//外层遍历userdata
userData[i].remove(QRegExp("\\s"));
vector<QString> useritem;
useritem.erase(useritem.begin(),useritem.end());// 清空
QStringList singleitem = userData[i].split(",");//userdata的一行
for(int j=0;j<pricolName.size();j++){//内层遍历主键
int pos= strLine1.indexOf(pricolName[j]);//找到第j个主键的下标
useritem.push_back(singleitem.at(pos));
}//qDebug()<<"内层循环"<<useritem;
pri.push_back(useritem);// 写入二维数组
}
qDebug()<<" !!!!!!user2.csv==userdata的数据=="<<pri;
}
userfile.close();
primaryfile.close();
}
QStringList list;//存列名们 是个list
if(attri!=NULL){
attri.remove(QChar('('), Qt::CaseInsensitive);
attri.remove(QChar(')'), Qt::CaseInsensitive);
}
//写入过程
QFile tfile(types::current_path + current_database + "/" +tname+"/user2.csv");
if(!tfile.open(QIODevice::Append|QIODevice::ReadOnly)){//追加写
qDebug()<<" Fail to open the user2.csv!\n";
}
//tfile.seek(0);
QTextStream out(&tfile);//写出
if (attri==NULL){
//没指定列,转换为指定列处理
//attri=strLine1;
for(int i=0;i<strLine1.size()-1;i++){
attri.append(strLine1[i]+",");
}
attri.append(strLine1[strLine1.size()-1]);
}
qDebug()<<"attri="<<attri;
if(attri!=NULL){
//指定了列attri=attri.left(attri.size()-1);
qDebug()<<"列名们"<<attri;
list = attri.split(",");//这里是列名
QStringList userdata = values.split(",");//这里是插入的数值
if(list.length()!=userdata.length()){
QMessageBox::warning(this, "警告", "数量不匹配!");
qDebug()<<"数量不匹配";
return false;
}// list要插入的列,userdata要插入的数据,strLine1存所有列名,priColName存主键的列名
int vnum=list.length();//插入元素个数
qDebug()<<"插入元素个数="<<vnum;//找到之后,进入 该名字的文件夹,看看有没有data.csv
int flag=1;//如果flag为真,则完全匹配
for(int i=0;i<vnum;i++){
//获取第i列在基表中对应的位置
//qDebug()<<"list at(i)="<<list.at(i);
//qDebug()<<"strLine1="<<strLine1.at(0)<<strLine1.at(1);
int pos = strLine1.indexOf(list.at(i));
if(pos==-1){
QMessageBox::warning(this, "警告", "输入列名有误");
qDebug()<<"输入列名有误!";
return false;
}
if(!checkMatch(strLine2.at(pos),userdata.at(i)))
flag=0;
}
if(flag==0){
QMessageBox::warning(this, "警告", "数据类型错误");
qDebug()<<"输入数据类型错误";
return false;
}else{
qDebug()<<"匹配完成,可以插入";
//检查notnull
QFile constraintfile(types::current_path + current_database + "/" +tname+"/constraint.csv");
if (!constraintfile.open(QIODevice::ReadOnly)) {
//打开不成功
qDebug() << "fail to open the constraint.csv!\n";
return false;
}
constraintfile.seek(0);
QTextStream * conread = new QTextStream(&constraintfile);
QStringList ConData = conread->readAll().split("\n",QString::SkipEmptyParts); //每行以\n区分
QString condataline = conread->readLine();
ConData[0].remove(QRegExp("\\s"));
QStringList ConCollist = ConData.at(0).split(",");//约束限制,null/notnull
qDebug()<<"null约束="<<ConCollist;
//检查notnull的是否被插入数据
for(int i=0;i<ConCollist.length();i++){
if(ConCollist.at(i)=="notnull"){
//寻找这是哪个列
int findit = list.indexOf(strLine1[i]);
if(findit==-1){
qDebug()<<"这个列为notnull,但是没插入数据";
return false;
}else if(userdata[findit]=="null"){
qDebug()<<"这个列为notnull,但是插入null";
return false;
}
}
}
constraintfile.close();
//检查notnull over
// 指定列的 检查主键
if(hasPri!=0){
//vector<vector<QString>> pri;//存主键对应的userdata
//vector<QString> inserted_pridata;
qDebug()<<"进入比较主键";
for(int i=0;i<pricolName.size();i++){
if(list.indexOf(pricolName[i])==-1){
//没插入主键
qDebug()<<"完蛋,没插入主键啊xd";
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(未写入主键数据)");
return false;
}else if(userdata[list.indexOf(pricolName[i])]=="null"){
//指定的列有,但是插入的是null,还tm是主键,直接拒绝
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(主键不能为null)");
return false;
}
}
vector<QString> inserted_pridata_appointed;
inserted_pridata_appointed.erase(inserted_pridata_appointed.begin(),inserted_pridata_appointed.end());
qDebug()<<" user pri: "<<pri;
qDebug()<<" pri.size()= "<<pri.size();
qDebug()<<" pricolName.size()="<<pricolName.size();
// 把带插入的数据的主键信息存入inserted_pridata_appointed
// list要插入的列,userdata要插入的数据,strLine1存所有列名,priColName存主键的列名
for(int j=0;j<pricolName.size();j++){//内层遍历主键
int pos= list.indexOf(pricolName[j]);//找到第j个主键的下标
inserted_pridata_appointed.push_back(userdata[pos]);
}
qDebug()<<"带插入数据中 涉及主键:"<<inserted_pridata_appointed;
int same=0;
for(int i=0;i<pri.size();i++){//外层遍历userdata
same=0;
// qDebug()<<"进入外循环";
for(int j=0;j<pricolName.size();j++){
inserted_pridata_appointed[j].remove("'");
if(pri[i].at(j)==inserted_pridata_appointed[j]){
//主键中的某一个相同
same++;
}
}
if(same==pricolName.size()){
//全部重复,即主键有重合
qDebug()<<"完蛋,主键有重复";
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(主键)");
tfile.close();
return false;
}
}qDebug()<<"for结束";
}
//检查主键over
//检查外键
if(hasFor!=0){
//有外键
int allowinsert = 1;
//循环看外键是否符合
for(int i=0;i<foreignKeys.size();i++){
//检查每一个外键 ForeignKeys:参照列、被参照表、被参照列
int insertedForeiIndex=-1;//在 待插入数据里外键的index
insertedForeiIndex= list.indexOf(foreignKeys[i].at(0));
if(insertedForeiIndex==-1){
return false;
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束( 未写入外键数据)");
}
//foreignKeys[i].at(1);//QString insertedvalue,QString referedtable,QString referedCol
if(!CheckForeignKey(userdata[insertedForeiIndex],foreignKeys[i].at(1),foreignKeys[i].at(2))){
allowinsert=0;
QMessageBox::warning(this, "警告", "插入失败!违反完整性约束(外键找不到参照)");
tfile.close();
return false;
}
}
}
//检查外键over
QStringList insert_values[colinfo.size()];//strLine1.length()strLine1.length()
for(int i =0;i<colinfo.size();i++){//strLine1.length()-1;
insert_values->append("null");
}
for(int i=0;i<vnum;i++){
//获取第i列在基表中对应的位置
int pos = strLine1.indexOf(list.at(i));//列名对应的位置
if(userdata[i][0]=="'" && userdata[i][userdata[i].length()-1]=="'"){
userdata[i].remove(0,1);
userdata[i].remove(userdata[i].length()-1,1);
//如果某个人值前后都是单引号,那把单引号删除
}
insert_values->replace(pos,userdata.at(i));
//if(insert_values[pos]=="'")
}
QString strTxt = insert_values->join(",");
qDebug()<<strTxt;
out<<strTxt<<endl;
}
}
tfile.close();
return true;
}
void MainWindow::on_reserve_btn_clicked()
{
if (!clicked) {
QMessageBox::warning(this, "警告", "请先进行点击事件之后再点击保存按钮!");
return;
}
QFile::remove(types::current_path + current_database + "/" + clicked_table + "/user2.csv");//先删一遍
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(ui->tableView->model());
int rows = model->rowCount();
int cols = model->columnCount();
//如果添加了行
if (rows > clicked_datas.size()) {
for (int i = clicked_datas.size(); i < rows; ++i) {
QString stm = "insert into " + clicked_table + " values(";
for (int j = 0; j < cols; ++j) {
//判断是否类型是否为varchar和datetime如果是则需要加上'
if (model->data(model->index(i, j)).toString() != "null" && (clicked_type[j].contains("varchar") || clicked_type[j] == "datetime")) {
stm += "'";
stm += model->data(model->index(i, j)).toString() + "'" + (j == cols - 1 ? ");" : ",");
} else {
stm += model->data(model->index(i, j)).toString() + (j == cols - 1 ? ");" : ",");
}
}
if (!inserted_parser(stm)) {
qDebug() << "插入失败!";
return;
}
}
} else {
/*for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (clicked_datas[i][j] != model->data(model->index(i, j)).toString()) {
//这个地方需要转接到cf的update
//选将此行从数组中删除,然后调用insert语句来判断是否能够插入
clicked_datas[i][j] = model->data(model->index(i, j)).toString();
}
QString stm = "insert into " + clicked_table + " values(";
for (int j = 0; j < cols; ++j) {
//判断是否类型是否为varchar和datetime如果是则需要加上'
if (model->data(model->index(i, j)).toString() != "null" && (clicked_type[j].contains("varchar") || clicked_type[j] == "datetime")) {
stm += "'";
stm += model->data(model->index(i, j)).toString() + "'" + (j == cols - 1 ? ");" : ",");
} else {
stm += model->data(model->index(i, j)).toString() + (j == cols - 1 ? ");" : ",");
}
}
if (!insert_parser_2(stm)) {
QMessageBox::warning(this, "警告", "修改数据有误!");
//删除相当于缓存的文件
QFile::remove(types::current_path + current_database + "/" + clicked_table + "/user2.csv");
return;
}
}
}*/
for (int i = 0; i < rows; ++i) {
QString stm = "insert into " + clicked_table + " values(";
for (int j = 0; j < cols; ++j) {
if (clicked_datas[i][j] != model->data(model->index(i, j)).toString()) {
//这个地方需要转接到cf的update
//选将此行从数组中删除,然后调用insert语句来判断是否能够插入
clicked_datas[i][j] = model->data(model->index(i, j)).toString();
}
}
for (int j = 0; j < cols; ++j) {
//判断是否类型是否为varchar和datetime如果是则需要加上'
if (model->data(model->index(i, j)).toString() != "null" && (clicked_type[j].contains("varchar") || clicked_type[j] == "datetime")) {
stm += "'";
stm += model->data(model->index(i, j)).toString() + "'" + (j == cols - 1 ? ");" : ",");
} else {
stm += model->data(model->index(i, j)).toString() + (j == cols - 1 ? ");" : ",");
}
}
qDebug()<<"*******调用insert2 执行的语句"<<stm;
if (!insert_parser_2(stm)) {
QMessageBox::warning(this, "警告", "修改数据有误!");
//删除相当于缓存的文件
QFile::remove(types::current_path + current_database + "/" + clicked_table + "/user2.csv");
return;
}
}
//删除相当于缓存的文件
QFile::remove(types::current_path + current_database + "/" + clicked_table + "/user2.csv");
//重新展示tableview
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(clicked_col.size());//设置列的长度
for (int i = 0; i < clicked_col.size(); ++i) {
model->setHeaderData(i, Qt::Horizontal, clicked_col[i]);
qDebug() << "clicked_col" << clicked_col[i];
}
ui->tableView->setModel(model);
for (int i = 0; i < clicked_datas.size(); ++i) {
QList<QStandardItem*> item;//添加一行
for (int j = 0; j < clicked_datas[i].size(); ++j) {
item.append(new QStandardItem(clicked_datas[i][j]));
}
model->appendRow(item);
}
ui->tableView->show();
//重写文件中的数据
QFile file_user(types::current_path + clicked_database + "/" + clicked_table + "/user.csv");
QTextStream stream_user(&file_user);
if (!file_user.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!";
}
for (int i = 0; i < clicked_datas.size(); ++i) {
for (int j = 0; j < clicked_datas[i].size(); ++j) {
stream_user << clicked_datas[i][j] << (j == clicked_datas[i].size() - 1 ? "\n" : ",");
}
}
qDebug() << "succeed to update the row!";
}
}
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
clicked_row = index.row();
clicked_column = index.column();
}
void MainWindow::on_deleted_col_clicked()
{
if (clicked_column == -1) {
QMessageBox::warning(this, "警告", "请选择你需要删除的行");
return;
}
QString name = clicked_col[clicked_column];
QString alter_stm = "alter table " + clicked_table + " drop " + name + ";";
if (!altered_parser(alter_stm)) {
return;
}
//删除每一行对应的列
for (int i = 0; i < clicked_datas.size(); ++i) {
clicked_datas[i].erase(clicked_datas[i].begin() + clicked_column);
}
//删除属性中的对应列
clicked_col.erase(clicked_col.begin() + clicked_column);
clicked_type.erase(clicked_type.begin() + clicked_column);
//创建修改tableview
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(clicked_col.size());//设置列的长度
for (int i = 0; i < clicked_col.size(); ++i) {
model->setHeaderData(i, Qt::Horizontal, clicked_col[i]);
qDebug() << "clicked_col" << clicked_col[i];
}
ui->tableView->setModel(model);
for (int i = 0; i < clicked_datas.size(); ++i) {
QList<QStandardItem*> item;//添加一行
for (int j = 0; j < clicked_datas[i].size(); ++j) {
item.append(new QStandardItem(clicked_datas[i][j]));
}
model->appendRow(item);
}
ui->tableView->show();
}
void MainWindow::on_deleted_row_clicked()
{
if (clicked_row == -1) {
QMessageBox::warning(this, "警告", "请点击选定你需要删除的行!");
return;
}
//删除用户数据中的行
QFile file(types::current_path + current_database + "/" + clicked_table + "foreigned_key.csv");
if (file.exists() && file.size() == 0) {
QMessageBox::warning(this, "警告", "此表被其他表参照不允许删除!");
return;
}
clicked_datas.erase(clicked_datas.begin() + clicked_row);
//重新展示tableview
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(clicked_col.size());//设置列的长度
for (int i = 0; i < clicked_col.size(); ++i) {
model->setHeaderData(i, Qt::Horizontal, clicked_col[i]);
qDebug() << "clicked_col" << clicked_col[i];
}
ui->tableView->setModel(model);
for (int i = 0; i < clicked_datas.size(); ++i) {
QList<QStandardItem*> item;//添加一行
for (int j = 0; j < clicked_datas[i].size(); ++j) {
item.append(new QStandardItem(clicked_datas[i][j]));
}
model->appendRow(item);
}
ui->tableView->show();
//重写文件中的数据
QFile file_user(types::current_path + clicked_database + "/" + clicked_table + "/user.csv");
QTextStream stream_user(&file_user);
if (!file_user.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "fail to open the user.csv!";
}
for (int i = 0; i < clicked_datas.size(); ++i) {
for (int j = 0; j < clicked_datas[i].size(); ++j) {
stream_user << clicked_datas[i][j] << (j == clicked_datas[i].size() - 1 ? "\n" : ",");
}
}
qDebug() << "succeed to delete the row!";
}
void MainWindow::get_alter_stm(QString s) {
s = s.toLower();
altered_parser(s);
}
void MainWindow::on_add_col_clicked()
{
if (!clicked) {
QMessageBox::warning(this, "警告", "请进行点击事件选择表!");
}
add_col_widge = new AddCol();
connect(this, SIGNAL(send_table_name(QString)), add_col_widge, SLOT(get_table_name(QString)));
emit(send_table_name(clicked_table));
connect(add_col_widge, SIGNAL(send_stm_alter(QString)), this, SLOT(get_alter_stm(QString)));
add_col_widge->show();
}
void MainWindow::get_created_database_stm(QString s) {
s = s.toLower();
created_parser(s, 2);
}
void MainWindow::on_toolButton_3_clicked()
{
create_database_widge = new CreateDataBase();
connect(create_database_widge, SIGNAL(send_created_database_stm(QString)), this, SLOT(get_created_database_stm(QString)));
create_database_widge->show();
}
void MainWindow::on_add_row_clicked()
{
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(ui->tableView->model());
QList<QStandardItem*> item;//添加一行
for (int j = 0; j < clicked_col.size(); ++j) {
item.append(new QStandardItem("null"));
}
model->appendRow(item);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。