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::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(); }