bool CheckUnqiueAndPrimaryKey(const TableInfo& table, const std::vector<std::string>& values){ IndexManager index_manager; RecordManager record_manager; std::vector<std::string> attributes_to_be_checked; attributes_to_be_checked = table.unique(); attributes_to_be_checked.push_back(table.primary_key()); for (auto it : attributes_to_be_checked){ int attribute_index = table.attribute_index(it); if (!table.attribute(it).index_names().empty()){//has index std::string index_name = table.attribute(it).index_names().at(0); IndexInfo index_info(index_name, table.table_name(), it); if (index_manager.FindValue(table,index_info,values.at(attribute_index))){ // has value return false; } } else{ WhereClause where; where.kColumnName = it; where.kOperator ="="; where.kCondition = values.at(attribute_index); if (!record_manager.FindRecordsWithNoIndex(table,where).empty()){ return false; } } } return true; }
Info API::CreateIndex(SqlCommandCreateIndex* command){ IndexManager index_manager; CatalogManager catalog_manager; RecordManager record_manager; std::string index_name = command->index_name(); std::string attribute_name = command->column_name(); std::string table_name = command->table_name(); if (catalog_manager.HasIndex(index_name)){ std::string error_info; error_info = "Index \"" + index_name + "\" already exists."; return Info(error_info); } if (!catalog_manager.HasTable(table_name)){ std::string error_info; error_info = "table \"" + table_name + "\" not exists."; return Info(error_info); } TableInfo table = catalog_manager.GetTableInfo(table_name); if(!table.HasAttribute(attribute_name)){ std::string error_info; error_info = "attribute \"" + attribute_name + "\" not exists."; return Info(error_info); } if (!table.attribute(attribute_name).is_unique() && !table.attribute(attribute_name).is_primary_key()){ std::string error_info; error_info = "attribute \"" + attribute_name + "\" is not an unique attribute."; return Info(error_info); } else{ IndexInfo index_info(index_name, table_name, attribute_name); //create index in index manager if(index_manager.CreateIndex(table.attribute(attribute_name).type(),table.attribute(attribute_name).length(), index_info)){ auto all_records = record_manager.SelectAllRecords(table); for (auto record : all_records){ if(!index_manager.AddRecord(table,index_info,record.first.at(table.attribute_index(index_info.attribute_name())),record.second)){ return Info("Update index failed."); } } if (!catalog_manager.RegisterIndex(index_info)) { return Info("Register Index failed."); } //update table info in catalog manager table.add_index(attribute_name, index_name); catalog_manager.WriteTableInfo(table); return Info(); } else{ return Info("Create index failed."); } } }
Info API::SelectFrom(SqlCommandSelectFrom* command){ CatalogManager catalog_manager; RecordManager record_manager; IndexManager index_manager; bool select_all_columns = command->select_all_columns(); bool select_all_records = command->select_all_records(); std::vector<std::string> column_names = command->column_names(); std::string table_name = command->table_name(); std::vector<WhereClause> where_clause = command->where_clause(); if (!catalog_manager.HasTable(table_name)){ std::string error_info; error_info = "Table \"" + table_name + "\" not exists."; return Info(error_info); } TableInfo table = catalog_manager.GetTableInfo(table_name); if (column_names.empty()){ column_names = table.attribute_names_ordered(); } else{ for (auto it : column_names){ if(!table.HasAttribute(it)){ std::string error_info; error_info = "attribute \"" + it + "\" not exists."; return Info(error_info); } } } for (auto it: where_clause){ if(!table.HasAttribute(it.kColumnName)){ std::string error_info; error_info = "attribute \"" + it.kColumnName + "\"in where clause \""+it.kColumnName + it.kOperator + it.kCondition +"\" not exists."; return Info(error_info); } } std::vector<std::pair<int,int> > results; std::vector<std::vector<std::string> > records; if (select_all_records){ auto records_offset_pairs = record_manager.SelectAllRecords(table); for (auto i : records_offset_pairs){ records.push_back(i.first); } } else{ std::vector<WhereClause> where_clause_with_index; std::vector<WhereClause> where_clause_without_index; for (auto it : where_clause){ if (!table.attribute(it.kColumnName).index_names().empty() && it.kOperator != "!="){ where_clause_with_index.push_back(it); } else{ where_clause_without_index.push_back(it); } } if (!where_clause_with_index.empty()) //条件里有属性有 index { for (auto it : where_clause_with_index){ std::string index_name = table.attribute(it.kColumnName).index_names().at(0); IndexInfo index = catalog_manager.GetIndexInfo(index_name); std::vector<int> offsets_of_a_clause = index_manager.FindRecords(table,index, it); std::sort(offsets_of_a_clause.begin(), offsets_of_a_clause.end()); offsets_of_a_clause.erase(std::unique(offsets_of_a_clause.begin(), offsets_of_a_clause.end()), offsets_of_a_clause.end()); std::vector<std::pair<int,int>> results_of_a_clause = record_manager.FindRecordsWithIndex(offsets_of_a_clause, table, it); if (results.empty()){ results = results_of_a_clause; } else{ std::vector<std::pair<int,int> > results_temp; std::set_intersection(results.begin(),results.end(), results_of_a_clause.begin(),results_of_a_clause.end(), std::back_inserter(results_temp)); results = results_temp; } } for(auto it : where_clause_without_index){ results = record_manager.RecordsFilter(results, table, it); } } else{ //条件里属性都没有 index for (auto it: where_clause_without_index){ if (results.empty()){ results = record_manager.FindRecordsWithNoIndex(table, it); } else{ results = record_manager.RecordsFilter(results,table, it); } } } records = record_manager.SelectRecords(results, table); } //print table for (auto it : column_names){ std::cout<<"+" << "--------------"; } std::cout<<"+"<<std::endl; //表头 for (auto it : column_names){ std::cout<<"| " << std::setw(12) << it <<" "; } std::cout<<"|"<<std::endl; for (auto it : column_names){ std::cout<<"+" << "--------------"; } std::cout<<"+"<<std::endl; std::vector<int> index; for (auto it: column_names){ auto attribute_names_ordered = table.attribute_names_ordered(); auto i = std::find(attribute_names_ordered.begin(), attribute_names_ordered.end(),it); int position= std::distance(attribute_names_ordered.begin(),i); index.push_back(position); } //print records for (auto it : records){ for (auto i : index){ std::cout<<"| "<<std::setw(12) << it.at(i)<<" "; } std::cout<<"|"<<std::endl; } for (auto it : column_names){ std::cout<<"+" << "--------------"; } std::cout<<"+"<<std::endl; return Info(); }
Info API::InsertInto(SqlCommandInsertInto* command){ CatalogManager catalog_manager; RecordManager record_manager; IndexManager index_manager; int offset; std::string table_name = command->table_name(); auto values = command->values(); if (!catalog_manager.HasTable(table_name)){ std::string error_info; error_info = "Table \"" + table_name + "\" not exists."; return Info(error_info); } TableInfo table = catalog_manager.GetTableInfo(table_name); if (table.attribute_names_ordered().size()!=values.size()){ return Info("Number of values not equals to the number of attributes"); } auto ano = table.attribute_names_ordered(); //Check string length and overflow for (int i = 0; i<values.size(); ++i){ int type = table.attribute(ano.at(i)).type(); int length = table.attribute(ano.at(i)).length(); if (type == 0){ if (!is_int_overflow_notchecked(values.at(i))){ std::string error_info; error_info = "Value \"" + values.at(i) + "\" is not a int number."; return Info(error_info); } try{ int v = std::stoi(values.at(i)); } catch(const std::out_of_range& e){ std::string error_info; error_info = "Value \"" + values.at(i) + "\" is out of range of int."; return Info(error_info); } } if (type == 1){ if (!is_float_overflow_notchecked(values.at(i))&&!is_int_overflow_notchecked(values.at(i))){ std::string error_info; error_info = "Value \"" + values.at(i) + "\" is not a float number."; return Info(error_info); } try{ float v = std::stof(values.at(i)); } catch(const std::out_of_range& e){ std::string error_info; error_info = "Value \"" + values.at(i) + "\" is out of range of float."; return Info(error_info); } } if (type == 2){ if (values.at(i).length() > length){ std::string error_info; error_info = "Value \"" + values.at(i) + "\" is out of range of char("+ std::to_string(length) +")."; return Info(error_info); } } } if (!CheckUnqiueAndPrimaryKey(table,values)){ return Info("Violation of uniqueness"); } offset = record_manager.InsertRecord(table,values); if (offset == -1){ return Info("Insert failed"); } //update index std::vector<std::string> index_names = table.index_names(); for (auto it : index_names){ IndexInfo index_info = catalog_manager.GetIndexInfo(it); if(!index_manager.AddRecord(table,index_info,values.at(table.attribute_index(index_info.attribute_name())),offset)){ return Info("Update index failed."); } } return Info(); }