#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <sstream>
#include <limits>
using namespace std;
// 关系类
class Relation {
public:
string name; // 关系名称
vector<string> attributes; // 属性列表
vector<vector<string>> tuples; // 元组列表
// 构造函数
Relation(string name, vector<string> attributes, vector<vector<string>> tuples) {
this->name = name;
this->attributes = attributes;
this->tuples = tuples;
}
};
vector<Relation> objects;
// 手动创建一个关系的函数
Relation createRelationManually() {
int numAttributes, numTuples;
string relationName;
vector<string> attributes;
vector<vector<string>> tuples;
// 输入关系名称
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "请输入关系名称: ";
getline(cin, relationName);
// 输入属性
cout << "请输入属性数量: ";
cin >> numAttributes;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略输入后的换行符
cout << "请输入属性列表(用空格分隔): ";
for (int i = 0; i < numAttributes; ++i) {
string attribute;
cin >> attribute;
attributes.push_back(attribute);
}
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略输入后的换行符
// 输入元组
cout << "请输入元组数量: ";
cin >> numTuples;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略输入后的换行符
cout << "请输入元组(每个值之间用空格分隔,每个元组占一行):" << endl;
for (int i = 0; i < numTuples; ++i) {
vector<string> tuple;
string tupleLine;
getline(cin, tupleLine);
istringstream ss(tupleLine);
string value;
while (ss >> value) {
tuple.push_back(value);
}
tuples.push_back(tuple);
}
// 创建并返回关系
return Relation(relationName, attributes, tuples);
}
// 获取关系的所有属性
vector<string> getAllAttributes(const Relation& relation) {
return relation.attributes;
}
// 单关系的投影操作
Relation project(const Relation& relation, const vector<string>& attributeList) {
vector<vector<string>> newTuples;
// 获取需要的属性在原关系中的索引
unordered_map<string, int> attributeIndexMap;
for (int i = 0; i < relation.attributes.size(); i++) {
attributeIndexMap[relation.attributes[i]] = i;//将键和值联系起来
}
// 对每个元组进行投影操作
for (const vector<string>& tuple : relation.tuples) {
vector<string> newTuple;
for (const string& attribute : attributeList) {
if (attributeIndexMap.count(attribute)) {//判断属性是否在关系中
newTuple.push_back(tuple[attributeIndexMap[attribute]]);
}
}
newTuples.push_back(newTuple);
}
return Relation(relation.name, attributeList, newTuples);
}
// 单关系的选择操作
Relation select(const Relation& relation, const string& condition) {
vector<vector<string>> newTuples;
// 解析条件表达式
string attributeName = condition.substr(0, condition.find(' '));//属性
string operatorType = condition.substr(condition.find(' ') + 1, 1);//运算符
string constantValue = condition.substr(condition.find(operatorType) + 2);//常量值
// 对每个元组进行选择操作——找where条件中属性下标
for (const vector<string>& tuple : relation.tuples) {
int attributeIndex = -1;
for (int i = 0; i < relation.attributes.size(); i++) {
if (relation.attributes[i] == attributeName) {
attributeIndex = i;
break;
}
}
// 根据操作符类型进行判断
if (operatorType == "=" && tuple[attributeIndex] == constantValue) {
newTuples.push_back(tuple);
}
else if (operatorType == "<" && tuple[attributeIndex] < constantValue) {
newTuples.push_back(tuple);
}
else if (operatorType == ">" && tuple[attributeIndex] > constantValue) {
newTuples.push_back(tuple);
}
}
return Relation(relation.name, relation.attributes, newTuples);
}
// 关系连接操作
Relation join(const Relation& relation1, const Relation& relation2, const string& condition) {
vector<vector<string>> newTuples;
// 解析连接条件
string attributeName1 = condition.substr(0, condition.find('=') - 1);
string attributeName2 = condition.substr(condition.find('=') + 2);
// 获取连接属性在两个关系中的索引
int attributeIndex1 = -1;
int attributeIndex2 = -1;
for (int i = 0; i < relation1.attributes.size(); i++) {
if (relation1.attributes[i] == attributeName1) {
attributeIndex1 = i;
break;
}
}
for (int i = 0; i < relation2.attributes.size(); i++) {
if (relation2.attributes[i] == attributeName2) {
attributeIndex2 = i;
break;
}
}
// 对每个元组进行连接操作
for (const vector<string>& tuple1 : relation1.tuples) {
for (const vector<string>& tuple2 : relation2.tuples) {
if (tuple1[attributeIndex1] == tuple2[attributeIndex2]) {
vector<string> newTuple = tuple1;
newTuple.insert(newTuple.end(), tuple2.begin(), tuple2.end());
newTuples.push_back(newTuple);
}
}
}
// 合并属性列表
vector<string> newAttributes = relation1.attributes;
newAttributes.insert(newAttributes.end(), relation2.attributes.begin(), relation2.attributes.end());
return Relation("Join", newAttributes, newTuples);
}
// 根据关系名获取关系对象
Relation getRelation(const string& relationName) {
// 根据关系名称返回对应的关系对象
// 这里假设已经定义了一些关系对象,并根据名称进行查找和返回
// 如果关系对象不存在,可以返回一个空的关系对象
for (const Relation newRelation : objects) {
if (newRelation.name == relationName) {
return newRelation;
}
}
return Relation("", {}, {});
}
// 解析属性列表
vector<string> getAttributeList(const string& attributeList) {
vector<string> attributes;
string attribute;
istringstream attributeStream(attributeList);
// 将属性列表分解为单个属性
while (getline(attributeStream, attribute, ',')) {
attributes.push_back(attribute);
}
return attributes;
}
//无连接,单条件
string getTokens5(vector<string>tokens) {
if (tokens.size() > 6) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 5; i < tokens.size(); i++) {
newToken += tokens[i];
if (i != tokens.size() - 1) {
newToken += ' ';
}
}
tokens[5] = newToken;
}
return tokens[5];
}
//有连接,单条件
string getTokens7(vector<string>tokens) {
if (tokens.size() > 8) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 7; i < tokens.size(); i++) {
newToken += tokens[i];
if (i != tokens.size() - 1) {
newToken += ' ';
}
}
tokens[7] = newToken;
}
return tokens[7];
}
// 解析查询语句,执行查询操作
string getTokens5_7(vector<string>tokens) {
if (tokens.size() > 6) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 5; i < 8; i++) {
newToken += tokens[i];
if (i != 7) {
newToken += ' ';
}
}
tokens[5] = newToken;
}
return tokens[5];
}
string getTokens7_9(vector<string>tokens) {
if (tokens.size() >= 7) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 7; i < 10; i++) {
newToken += tokens[i];
if (i != 9) {
newToken += ' ';
}
}
tokens[7] = newToken;
}
return tokens[7];
}
string getTokens9_11(vector<string>tokens) {
if (tokens.size() > 10) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 9; i < 12; i++) {
newToken += tokens[i];
if (i != 11) {
newToken += ' ';
}
}
tokens[9] = newToken;
}
return tokens[9];
}
string getTokens11_13(vector<string>tokens) {
if (tokens.size() > 12) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 11; i < 14; i++) {
newToken += tokens[i];
if (i != 13) {
newToken += ' ';
}
}
tokens[11] = newToken;
}
return tokens[11];
}
string getTokens12_14(vector<string>tokens) {
if (tokens.size() > 13) {
// 将第6个及以后的所有的字符串组成一个新的字符串
string newToken;
for (int i = 12; i < 15; i++) {
newToken += tokens[i];
if (i != 14) {
newToken += ' ';
}
}
tokens[12] = newToken;
}
return tokens[12];
}
Relation executeQuery(const string& query) {
vector<string> tokens;//将空格分割出来的单词保存
string token;
istringstream tokenStream(query);
// 将查询语句分解为单词
while (getline(tokenStream, token, ' ')) {
tokens.push_back(token);
}
// 执行查询操作
if (tokens[0] == "SELECT" && tokens[1] == "*") {
if (tokens[2] == "FROM") {
// 单关系的投影操作
if (tokens.size() == 4) {
return project(getRelation(tokens[3]), getAllAttributes(getRelation(tokens[3])));
}
// 单关系的选择操作
else if (tokens.size() == 8 && tokens[4] == "WHERE") {
return select(getRelation(tokens[3]), getTokens5(tokens));
}
else if (tokens[4] == "JOIN" && tokens[6] == "WHERE") {
if (tokens.size() == 10) {
return join(getRelation(tokens[3]), getRelation(tokens[5]), getTokens7(tokens));
}
else if (tokens[10] == "AND" && tokens.size() == 14) {
return select(join(getRelation(tokens[3]), getRelation(tokens[5]), getTokens7_9(tokens)), getTokens11_13(tokens));
}
}
else if (tokens[8] == "AND" && tokens.size() == 12) {
return select(select(getRelation(tokens[3]), getTokens5_7(tokens)), getTokens9_11(tokens));
}
else {
return Relation("", {}, {});
}
}
// "SELECT A,B FROM Relation1 WHERE A = 1",
// "SELECT A,B FROM Relation1",
}// "SELECT A,B FROM Relation1 JOIN Relation2 WHERE C = C",
// 0 1 2 3 4 5 6 7 8 9
else if (tokens[0] == "SELECT") {
if (tokens[2] == "FROM" && tokens.size() == 4) {
return project(getRelation(tokens[3]), getAttributeList(tokens[1]));
}
// 单关系多属性单条件的选择和投影操作
else if (tokens[2] == "FROM" && tokens[4] == "WHERE") {
return project(select(getRelation(tokens[3]), getTokens5(tokens)), getAttributeList(tokens[1]));
}
else if (tokens[2] == "FROM" && tokens[4] == "JOIN" && tokens[6] == "WHERE") {
return join(getRelation(tokens[3]), getRelation(tokens[5]), getTokens7(tokens));
}
else
return Relation("", {}, {});
}
else
return Relation("", {}, {});
}
vector<string> testQueries() {
// 查询语句
vector<string> queries = {
"SELECT * FROM Relation1",//
"SELECT * FROM Relation1 WHERE sno = 0118",//
"SELECT * FROM Relation1 JOIN Relation2 WHERE sno = sno",//
"SELECT * FROM Relation1 WHERE sno = 0118 AND age > 22",//
"SELECT * FROM Relation1 JOIN Relation2 WHERE sno = sno AND grade > 95",//
"SELECT sno,name,sex FROM Relation1 JOIN Relation2 WHERE sno = sno",//
"SELECT sno,sex FROM Relation2",//
"SELECT age,name FROM Relation1 WHERE age = 22",//
};
return queries;
}
int main() {
// 示例:手动创建一个关系
int n;
cout << "你要创建几个表格:"<<endl;
cin >> n;
for (int i = 0; i < n; i++) {
Relation it = createRelationManually();
objects.push_back(it);
}
// 打印新创建的关系以验证输入
/* for (const Relation newRelation : objects) {
cout << "新创建的关系: " << newRelation.name << endl;
cout << "属性: ";
for (const auto& attr : newRelation.attributes) {
cout << attr << " ";
}
cout << "\n元组:" << endl;
for (const auto& tuple : newRelation.tuples) {
for (const auto& value : tuple) {
cout << value << " ";
}
cout << endl;
}
}*/
vector<string> queries = testQueries();
for (const string& query : queries)
{
cout << "Query: " << query << endl;
Relation result = executeQuery(query);
cout << "\t\t" << result.name << endl;
cout << "|-----------------------------------------------------------------------------------------------|" << endl;
for (const string& attribute : result.attributes)
{
cout << "|\t" << attribute << "\t";
}
cout << "|" << endl;
cout << "|-----------------------------------------------------------------------------------------------|" << endl;
for (const vector<string>& tuple : result.tuples)
{
for (const string& value : tuple)
{
cout << "|\t" << value << "\t";
}
cout << "|" << endl;
cout << "|-----------------------------------------------------------------------------------------------|" << endl;
}
cout << endl;
}
return 0;
}
C++数据库系统原理实验——选择,投影、连接的模拟
于 2023-11-19 17:52:25 首次发布