int Database::search(const vector<SearchCriterion>& searchCriteria, const vector<SortCriterion>& sortCriteria, vector<int>& results) { results.clear(); if (searchCriteria.empty()) // no search criteria return ERROR_RESULT; // Search // The result of our query is the intersection of all search criteria. To do this, // for each search criteria, we plug our results into the unordered_set cur_query. // For each subsequent search criteria, we replace prev_query with cur_query, clear // cur_query, then check if each new value exists within prev_query: if it does, we // have an intersection, and we enter the value into cur_query. unordered_set<int> cur_query, prev_query; for (int i = 0; i < searchCriteria.size(); ++i) { if (searchCriteria[i].minValue == "" && searchCriteria[i].maxValue == "") return ERROR_RESULT; // lacks both min AND max values // Find fieldName within m_schema prev_query = cur_query; cur_query.clear(); int j = 0; for (; j < m_schema.size(); ++j) { if (searchCriteria[i].fieldName == m_schema[j].name) { if (m_schema[j].index == it_none) // field name is non-indexed return ERROR_RESULT; // Find all rows between minValue and maxValue, inclusive. // If minValue or maxValue is empty, min and max iterators will be set to the // smallest and largest nodes, respectively. MultiMap::Iterator min = m_fieldIndex[j]->findEqualOrSuccessor(searchCriteria[i].minValue), max = m_fieldIndex[j]->findEqualOrPredecessor(searchCriteria[i].maxValue); for (; min.valid(); min.next()) { bool add = true; if (i > 0) // only check the previous query if this is not our first { unordered_set<int>::const_iterator found = prev_query.find(min.getValue()); if (found == prev_query.end()) // not found, so no intersection add = false; } if (add) cur_query.insert(min.getValue()); // inserts row # to current unordered_set if (min.getKey() == max.getKey() && min.getValue() == max.getValue()) break; } break; } } if (j == m_schema.size()) // no fieldName match found return ERROR_RESULT; } // Sort for (auto it = cur_query.begin(); it != cur_query.end(); ++it) results.push_back(*it); if (!sortCriteria.empty()) quicksort(results, 0, cur_query.size(), sortCriteria); return cur_query.size(); }
int main() { /*Database db; db.loadFromURL("http://cs.ucla.edu/classes/winter14/cs32/Projects/4/Data/census.csv"); */ MultiMap m; m.insert("D", 8); m.insert("B", 4); m.insert("F", 12); m.insert("A", 1); m.insert("C", 5); m.insert("E", 9); m.insert("G", 13); m.insert("A", 2); m.insert("C", 6); m.insert("E", 10); m.insert("G", 14); m.insert("A", 3); m.insert("C", 7); m.insert("E", 11); m.insert("G", 15); MultiMap::Iterator c(m.findEqual("D")); assert(c.valid()); MultiMap::Iterator d; for (; c.valid(); c.prev()) d = c; for (; d.valid(); d.next()) cout << d.getKey() << " " << d.getValue() << endl; cout << endl; MultiMap::Iterator a(m.findEqual("D")); assert(a.valid()); MultiMap::Iterator b; for (; a.valid(); a.next()) b = a; for (; b.valid(); b.prev()) cout << b.getKey() << " " << b.getValue() << endl; MultiMap::Iterator t; t = m.findEqual("A"); if (t.valid()) { cout << endl; cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; } t = m.findEqualOrSuccessor("Fz"); if (t.valid()) { cout << endl; cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; } t = m.findEqualOrPredecessor("E"); t.next(); MultiMap::Iterator after = t; t.next(); MultiMap::Iterator afterafter = t; t.prev(); t.prev(); if (t.valid() && after.valid() && afterafter.valid()) { cout << endl; cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; t.next(); cout << t.getKey() << " " << t.getValue() << endl; } Database database; Database::FieldDescriptor fd1, fd2, fd3; fd1.name = "username"; fd1.index = Database::it_indexed; // username is an indexed field fd2.name = "phonenum"; fd2.index = Database::it_indexed; // phone # is an indexed field fd3.name = "age"; fd3.index = Database::it_none; // age is NOT an indexed field std::vector<Database::FieldDescriptor> schema; schema.push_back(fd1); schema.push_back(fd2); schema.push_back(fd3); database.specifySchema(schema); vector<string> row; string username = "******"; string phonenum = "6265375521"; string age = "17"; row.push_back(username); row.push_back(phonenum); row.push_back(age); database.addRow(row); vector<string> row2; username = "******"; phonenum = "5403317654"; age = "20"; row2.push_back(username); row2.push_back(phonenum); row2.push_back(age); database.addRow(row2); vector<string> row3; username = "******"; phonenum = "6265375521"; age = "25"; row3.push_back(username); row3.push_back(phonenum); row3.push_back(age); database.addRow(row3); vector<int> results; vector<Database::SortCriterion> sortCrit; vector<Database::SearchCriterion> searchCrit; Database::SearchCriterion s1; s1.fieldName = "username"; s1.minValue = "A"; s1.maxValue = "C"; Database::SearchCriterion s2; s2.fieldName = "phonenum"; s2.minValue = "6000000000"; s2.maxValue = ""; searchCrit.push_back(s1); searchCrit.push_back(s2); database.search(searchCrit, sortCrit, results); cout << endl << "Passed all tests" << endl; }