Revert "Change DB API to find constant key IDs."
diff --git a/include/llbuild/Core/BuildDB.h b/include/llbuild/Core/BuildDB.h
index af08ce3..a6dd467 100644
--- a/include/llbuild/Core/BuildDB.h
+++ b/include/llbuild/Core/BuildDB.h
@@ -16,8 +16,6 @@
 #include "llbuild/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
 
-#include "llbuild/Core/BuildEngine.h"
-
 #include <cstdint>
 #include <memory>
 #include <string>
@@ -32,16 +30,6 @@
 public:
   virtual ~BuildDB();
 
-  /// Get a unique ID for the given key.
-  ///
-  /// This method is thread safe, and cannot fail.
-  virtual KeyID getKeyID(const KeyType& key) = 0;
-
-  /// Get the key corresponding to a key ID.
-  ///
-  /// This method is thread safe, and cannot fail.
-  virtual KeyType getKeyForID(KeyID key) = 0;
-  
   /// Get the current build iteration.
   ///
   /// \param success_out [out] Whether or not the query succeeded.
@@ -55,7 +43,6 @@
 
   /// Look up the result for a rule.
   ///
-  /// \param keyID The keyID for the rule.
   /// \param rule The rule to look up the result for.
   /// \param result_out [out] The result, if found.
   /// \param error_out [out] Error string if an error occurred.
@@ -66,7 +53,7 @@
   // FIXME: Figure out if we want a more lazy approach where we make the
   // database cache result objects and we query them only when needed. This may
   // scale better to very large build graphs.
-  virtual bool lookupRuleResult(KeyID keyID, const Rule& rule, Result* result_out, std::string* error_out) = 0;
+  virtual bool lookupRuleResult(const Rule& rule, Result* result_out, std::string* error_out) = 0;
 
   /// Update the stored result for a rule.
   ///
@@ -77,9 +64,8 @@
   /// The database *MUST*, however, correctly maintain the order of the
   /// dependencies.
   ///
-  /// \param keyID The keyID for the rule.
   /// \param error_out [out] Error string if return value is false.
-  virtual bool setRuleResult(KeyID keyID, const Rule& rule, const Result& result, std::string* error_out) = 0;
+  virtual bool setRuleResult(const Rule& rule, const Result& result, std::string* error_out) = 0;
 
   /// Called by the build engine to indicate that a build has started.
   ///
diff --git a/include/llbuild/Core/BuildEngine.h b/include/llbuild/Core/BuildEngine.h
index 1154471..b42ce59 100644
--- a/include/llbuild/Core/BuildEngine.h
+++ b/include/llbuild/Core/BuildEngine.h
@@ -20,7 +20,6 @@
 #include <utility>
 #include <vector>
 
-#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 
 namespace llbuild {
@@ -28,7 +27,6 @@
 
 // FIXME: Need to abstract KeyType;
 typedef std::string KeyType;
-typedef uint64_t KeyID;
 typedef std::vector<uint8_t> ValueType;
 
 class BuildDB;
@@ -63,7 +61,7 @@
   //
   // FIXME: At some point, figure out the optimal representation for this field,
   // which is likely to be a lot of the resident memory size.
-  std::vector<KeyID> dependencies;
+  std::vector<KeyType> dependencies;
 };
 
 /// A task object represents an abstract in-progress computation in the build
@@ -89,6 +87,8 @@
 /// complete its computation and provide the output. The Task is responsible for
 /// providing the engine with the computed value when ready using \see
 /// BuildEngine::taskIsComplete().
+//
+// FIXME: Define parallel execution semantics.
 class Task {
 public:
   Task() {}
diff --git a/lib/Core/BuildEngine.cpp b/lib/Core/BuildEngine.cpp
index 3b34a3c..6175471 100644
--- a/lib/Core/BuildEngine.cpp
+++ b/lib/Core/BuildEngine.cpp
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
 // See http://swift.org/LICENSE.txt for license information
@@ -15,7 +15,6 @@
 #include "llbuild/Core/BuildDB.h"
 
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
 
 #include "BuildEngineTrace.h"
 
@@ -55,12 +54,6 @@
 
   BuildEngineDelegate& delegate;
 
-  /// The key table, used when there is no database.
-  llvm::StringMap<bool> keyTable;
-
-  /// The mutex that protects the key table.
-  std::mutex keyTableMutex;
-  
   /// The build database, if attached.
   std::unique_ptr<BuildDB> db;
 
@@ -134,14 +127,9 @@
       Complete
     };
 
-    RuleInfo(KeyID keyID, Rule&& rule) : keyID(keyID), rule(rule) {}
+    RuleInfo(Rule&& rule) : rule(rule) {}
 
-    /// The ID for the rule key.
-    KeyID keyID;
-
-    /// The rule this information describes.
     Rule rule;
-    
     /// The state dependent record for in-progress information.
     union {
       RuleScanRecord* pendingScanRecord;
@@ -226,9 +214,8 @@
   // NOTE: We currently rely on the unordered_map behavior that ensures that
   // references to elements are not invalidated by insertion. We will need to
   // move to an alternate allocation strategy if we switch to DenseMap style
-  // table. This is probably a good idea in any case, because we would benefit
-  // from pool allocating RuleInfo instances.
-  std::unordered_map<KeyID, RuleInfo> ruleInfos;
+  // table.
+  std::unordered_map<KeyType, RuleInfo> ruleInfos;
 
   /// Information tracked for executing tasks.
   //
@@ -257,7 +244,7 @@
     /// provided.
     unsigned waitCount = 0;
     /// The list of discovered dependencies found during execution of the task.
-    std::vector<KeyID> discoveredDependencies;
+    std::vector<KeyType> discoveredDependencies;
 
 #ifndef NDEBUG
     void dump() const {
@@ -516,8 +503,8 @@
     do {
       // Look up the input rule info, if not yet cached.
       if (!request.inputRuleInfo) {
-        const auto& inputID = ruleInfo.result.dependencies[request.inputIndex];
-        request.inputRuleInfo = &getRuleInfoForKey(inputID);
+        const auto& inputKey = ruleInfo.result.dependencies[request.inputIndex];
+        request.inputRuleInfo = &getRuleInfoForKey(inputKey);
       }
       auto& inputRuleInfo = *request.inputRuleInfo;
 
@@ -729,7 +716,7 @@
         // * Record at the time it is popped off the input request queue.
         // * Record at the time the input is supplied (here).
         request.taskInfo->forRuleInfo->result.dependencies.push_back(
-            request.inputRuleInfo->keyID);
+          request.inputRuleInfo->rule.key);
 
         // Provide the requesting task with the input.
         //
@@ -824,15 +811,14 @@
         // approach for discovered dependencies instead of just providing
         // support for taskNeedsInput() even after the task has started
         // computing and from parallel contexts.
-        for (KeyID inputID: taskInfo->discoveredDependencies) {
-          inputRequests.push_back({ nullptr, &getRuleInfoForKey(inputID) });
+        for (const auto& inputKey: taskInfo->discoveredDependencies) {
+          inputRequests.push_back({ nullptr, &getRuleInfoForKey(inputKey) });
         }
 
         // Update the database record, if attached.
         if (db) {
           std::string error;
-          bool result = db->setRuleResult(
-              ruleInfo->keyID, ruleInfo->rule, ruleInfo->result, &error);
+          bool result = db->setRuleResult(ruleInfo->rule, ruleInfo->result, &error);
           if (!result) {
             delegate.error(error);
             completeRemainingTasks();
@@ -1074,50 +1060,14 @@
     return currentTimestamp;
   }
 
-  KeyID getKeyID(const KeyType& key) {
-    // Delegate if we have a database.
-    if (db) {
-      return db->getKeyID(key);
-    }
-
-    // Otherwise use our builtin key table.
-    {
-      std::lock_guard<std::mutex> guard(keyTableMutex);
-      auto it = keyTable.insert(std::make_pair(key, false)).first;
-      return (KeyID)(uintptr_t)it->getKey().data();
-    }
-  }
-
   RuleInfo& getRuleInfoForKey(const KeyType& key) {
-    auto keyID = getKeyID(key);
-    
     // Check if we have already found the rule.
-    auto it = ruleInfos.find(keyID);
+    auto it = ruleInfos.find(key);
     if (it != ruleInfos.end())
       return it->second;
 
     // Otherwise, request it from the delegate and add it.
-    return addRule(keyID, delegate.lookupRule(key));
-  }
-
-  RuleInfo& getRuleInfoForKey(KeyID keyID) {
-    // Check if we have already found the rule.
-    auto it = ruleInfos.find(keyID);
-    if (it != ruleInfos.end())
-      return it->second;
-
-    // Otherwise, we need to resolve the full key so we can request it from the
-    // delegate.
-    KeyType key;
-    if (db) {
-      key = db->getKeyForID(keyID);
-    } else {
-      // Note that we don't need to lock `keyTable` here because the key entries
-      // themselves don't change once created.
-      key = llvm::StringMapEntry<bool>::GetStringMapEntryFromKeyData(
-          (const char*)(uintptr_t)keyID).getKey();
-    }
-    return addRule(keyID, delegate.lookupRule(key));
+    return addRule(delegate.lookupRule(key));
   }
 
   TaskInfo* getTaskInfo(Task* task) {
@@ -1130,11 +1080,7 @@
   /// @{
 
   RuleInfo& addRule(Rule&& rule) {
-    return addRule(getKeyID(rule.key), std::move(rule));
-  }
-  
-  RuleInfo& addRule(KeyID keyID, Rule&& rule) {
-    auto result = ruleInfos.emplace(keyID, RuleInfo(keyID, std::move(rule)));
+    auto result = ruleInfos.emplace(rule.key, RuleInfo(std::move(rule)));
     if (!result.second) {
       // FIXME: Error handling.
       std::cerr << "error: attempt to register duplicate rule \""
@@ -1150,7 +1096,7 @@
     RuleInfo& ruleInfo = result.first->second;
     if (db) {
       std::string error;
-      db->lookupRuleResult(ruleInfo.keyID, ruleInfo.rule, &ruleInfo.result, &error);
+      db->lookupRuleResult(ruleInfo.rule, &ruleInfo.result, &error);
       if (!error.empty()) {
         delegate.error(error);
         completeRemainingTasks();
@@ -1279,10 +1225,9 @@
     // Write out all of the rules.
     for (const auto& ruleInfo: orderedRuleInfos) {
       fprintf(fp, "\"%s\"\n", ruleInfo->rule.key.c_str());
-      for (KeyID inputID: ruleInfo->result.dependencies) {
-        const auto& dependency = getRuleInfoForKey(inputID);
+      for (auto& input: ruleInfo->result.dependencies) {
         fprintf(fp, "\"%s\" -> \"%s\"\n", ruleInfo->rule.key.c_str(),
-                dependency.rule.key.c_str());
+                input.c_str());
       }
       fprintf(fp, "\n");
     }
@@ -1349,8 +1294,7 @@
       return;
     }
 
-    auto dependencyID = getKeyID(key);
-    taskInfo->discoveredDependencies.push_back(dependencyID);
+    taskInfo->discoveredDependencies.push_back(key);
   }
 
   void taskIsComplete(Task* task, ValueType&& value, bool forceChange) {
diff --git a/lib/Core/SQLiteBuildDB.cpp b/lib/Core/SQLiteBuildDB.cpp
index c956a44..216bb9f 100644
--- a/lib/Core/SQLiteBuildDB.cpp
+++ b/lib/Core/SQLiteBuildDB.cpp
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
 // See http://swift.org/LICENSE.txt for license information
@@ -16,12 +16,10 @@
 #include "llbuild/Core/BuildEngine.h"
 
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
 
 #include <cassert>
 #include <cerrno>
 #include <cstring>
-#include <mutex>
 #include <sstream>
 
 #include <sqlite3.h>
@@ -42,10 +40,6 @@
 
   sqlite3 *db = nullptr;
 
-  /// The mutex that protects the key ID table (which must support concurrent
-  /// access).
-  std::mutex keyIDMutex;
-
   std::string getCurrentErrorMessage() {
     int err_code = sqlite3_errcode(db);
     const char* err_message = sqlite3_errmsg(db);
@@ -235,11 +229,6 @@
       db, findKeyIDForKeyStmtSQL,
       -1, &findKeyIDForKeyStmt, nullptr);
     assert(result == SQLITE_OK);
-
-    result = sqlite3_prepare_v2(
-      db, findKeyNameForKeyIDStmtSQL,
-      -1, &findKeyNameForKeyIDStmt, nullptr);
-    assert(result == SQLITE_OK);
     
     result = sqlite3_prepare_v2(
       db, findIDForKeyInRuleResultsStmtSQL,
@@ -294,7 +283,6 @@
 
     // Destroy prepared statements.
     sqlite3_finalize(findKeyIDForKeyStmt);
-    sqlite3_finalize(findKeyNameForKeyIDStmt);
     sqlite3_finalize(findRuleDependenciesStmt);
     sqlite3_finalize(findRuleResultStmt);
     sqlite3_finalize(deleteFromKeysStmt);
@@ -359,23 +347,22 @@
     return true;
   }
 
-  static constexpr const char *deleteFromKeysStmtSQL = (
-      "DELETE FROM key_names WHERE key == ?;");
+  static constexpr const char *deleteFromKeysStmtSQL =
+  "DELETE FROM key_names WHERE key == ?;";
   sqlite3_stmt* deleteFromKeysStmt = nullptr;
   
-  static constexpr const char *findRuleResultStmtSQL = (
-      "SELECT id, value, built_at, computed_at FROM rule_results "
-      "WHERE key_id == ?;");
+  static constexpr const char *findRuleResultStmtSQL =
+  "SELECT rule_results.id, value, built_at, computed_at FROM rule_results "
+  "INNER JOIN key_names ON key_names.id = rule_results.key_id WHERE key == ?;";
   sqlite3_stmt* findRuleResultStmt = nullptr;
 
-  static constexpr const char *findRuleDependenciesStmtSQL = (
-      "SELECT key_id FROM rule_dependencies WHERE rule_id == ?"
-      "ORDER BY rule_dependencies.ordinal;");
+  static constexpr const char *findRuleDependenciesStmtSQL =
+  "SELECT key FROM key_names INNER JOIN rule_dependencies "
+  "ON key_names.id = rule_dependencies.key_id WHERE rule_id == ?"
+  "ORDER BY rule_dependencies.ordinal;";
   sqlite3_stmt* findRuleDependenciesStmt = nullptr;
 
-  virtual bool lookupRuleResult(KeyID keyID, const Rule& rule,
-                                Result* result_out,
-                                std::string *error_out) override {
+  virtual bool lookupRuleResult(const Rule& rule, Result* result_out, std::string *error_out) override {
     assert(result_out->builtAt == 0);
 
     // Fetch the basic rule information.
@@ -385,7 +372,9 @@
     assert(result == SQLITE_OK);
     result = sqlite3_clear_bindings(findRuleResultStmt);
     assert(result == SQLITE_OK);
-    result = sqlite3_bind_int64(findRuleResultStmt, /*index=*/1, keyID);
+    result = sqlite3_bind_text(findRuleResultStmt, /*index=*/1,
+                               rule.key.data(), rule.key.size(),
+                               SQLITE_STATIC);
     assert(result == SQLITE_OK);
 
     // If the rule wasn't found, we are done.
@@ -428,8 +417,9 @@
         return false;
       }
       assert(sqlite3_column_count(findRuleDependenciesStmt) == 1);
-      auto dependencyID = sqlite3_column_int64(findRuleDependenciesStmt, 0);
-      result_out->dependencies.push_back(dependencyID);
+      result_out->dependencies.push_back(std::string(
+                (const char*)sqlite3_column_text(findRuleDependenciesStmt, 0),
+                sqlite3_column_bytes(findRuleDependenciesStmt, 0)));
     }
 
     return true;
@@ -462,16 +452,11 @@
     "DELETE FROM rule_dependencies WHERE rule_id == ?;";
   sqlite3_stmt* deleteFromRuleDependenciesStmt = nullptr;
 
-  static constexpr const char *findKeyIDForKeyStmtSQL = (
-      "SELECT id FROM key_names "
-      "WHERE key == ? LIMIT 1;");
+  static constexpr const char *findKeyIDForKeyStmtSQL =
+  "SELECT id FROM key_names "
+  "WHERE key == ? LIMIT 1;";
   sqlite3_stmt* findKeyIDForKeyStmt = nullptr;
 
-  static constexpr const char *findKeyNameForKeyIDStmtSQL = (
-      "SELECT key FROM key_names "
-      "WHERE id == ? LIMIT 1;");
-  sqlite3_stmt* findKeyNameForKeyIDStmt = nullptr;
-
   static constexpr const char *insertIntoKeysStmtSQL =
   "INSERT OR IGNORE INTO key_names(key) VALUES (?);";
   sqlite3_stmt* insertIntoKeysStmt = nullptr;
@@ -479,8 +464,7 @@
   /// Inserts a key if not present and always returns keyID
   /// Sometimes key will be inserted for a lookup operation
   /// but that is okay because it'll be added at somepoint anyway
-  virtual KeyID getKeyID(const KeyType& key) override {
-    std::lock_guard<std::mutex> guard(keyIDMutex);
+  uint64_t getOrInsertKey(const KeyType& key, std::string *error_out) {
     int result;
 
     // Seach for the key.
@@ -511,43 +495,24 @@
     assert(result == SQLITE_OK);
     result = sqlite3_step(insertIntoKeysStmt);
     if (result != SQLITE_DONE) {
-      // FIXME: We need to support error reporting here, but the engine cannot
-      // handle it currently.
-      abort();
+      *error_out = getCurrentErrorMessage();
+      return UINT64_MAX;
     }
 
     return sqlite3_last_insert_rowid(db);
   }
-
-  virtual KeyType getKeyForID(KeyID keyID) override {
-    std::lock_guard<std::mutex> guard(keyIDMutex);
-    int result;
-
-    // Seach for the key.
-    result = sqlite3_reset(findKeyNameForKeyIDStmt);
-    assert(result == SQLITE_OK);
-    result = sqlite3_clear_bindings(findKeyNameForKeyIDStmt);
-    assert(result == SQLITE_OK);
-    result = sqlite3_bind_int64(findKeyNameForKeyIDStmt, /*index=*/1, keyID);
-    assert(result == SQLITE_OK);
-
-    result = sqlite3_step(findKeyNameForKeyIDStmt);
-    assert(result == SQLITE_ROW);
-    assert(sqlite3_column_count(findKeyNameForKeyIDStmt) == 1);
-
-    // Found a keyID, return.
-    auto size = sqlite3_column_bytes(findKeyNameForKeyIDStmt, 0);
-    auto text = (const char*) sqlite3_column_text(findKeyNameForKeyIDStmt, 0);
-    return KeyType(text, size);
-  }
-
-  virtual bool setRuleResult(KeyID keyID,
-                             const Rule& rule,
+  
+  virtual bool setRuleResult(const Rule& rule,
                              const Result& ruleResult,
                              std::string *error_out) override {
     int result;
     uint64_t ruleID = 0;
 
+    uint64_t keyID = getOrInsertKey(rule.key, error_out);
+    if (keyID == UINT64_MAX) {
+      return false;
+    }
+
     // Find the existing rule id, if present.
     //
     // We rely on SQLite3 not using 0 as a valid rule ID.
@@ -633,7 +598,7 @@
 
     // Insert all the dependencies.
     for (unsigned i = 0; i != ruleResult.dependencies.size(); ++i) {
-      KeyID dependencyKeyID = ruleResult.dependencies[i];
+      const auto& dependency = ruleResult.dependencies[i];
 
       // Reset the insert statement.
       result = sqlite3_reset(insertIntoRuleDependenciesStmt);
@@ -647,8 +612,12 @@
       assert(result == SQLITE_OK);
 
       // Bind the dependency key ID.
+      uint64_t dependencyKeyID = getOrInsertKey(dependency, error_out);
+      if (dependencyKeyID == UINT64_MAX) {
+        return false;
+      }
       result = sqlite3_bind_int64(insertIntoRuleDependenciesStmt, /*index=*/2,
-                                  dependencyKeyID);
+                                 dependencyKeyID);
       assert(result == SQLITE_OK);
 
       // Bind the index of the dependency.
diff --git a/unittests/Core/BuildEngineTest.cpp b/unittests/Core/BuildEngineTest.cpp
index 74968eb..ed1dea1 100644
--- a/unittests/Core/BuildEngineTest.cpp
+++ b/unittests/Core/BuildEngineTest.cpp
@@ -14,7 +14,6 @@
 
 #include "llbuild/Core/BuildDB.h"
 
-#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/ErrorHandling.h"
 
 #include "gtest/gtest.h"
@@ -420,32 +419,18 @@
   // Attach a custom database, used to get the results.
   class CustomDB : public BuildDB {
   public:
-    llvm::StringMap<bool> keyTable;
-    
-    std::unordered_map<KeyType, Result> ruleResults;
+    std::unordered_map<core::KeyType, Result> ruleResults;
 
-    virtual KeyID getKeyID(const KeyType& key) override {
-      auto it = keyTable.insert(std::make_pair(key, false)).first;
-      return (KeyID)(uintptr_t)it->getKey().data();
-    }
-
-    virtual KeyType getKeyForID(KeyID keyID) override {
-      return llvm::StringMapEntry<bool>::GetStringMapEntryFromKeyData(
-          (const char*)(uintptr_t)keyID).getKey();
-    }
-    
     virtual uint64_t getCurrentIteration(bool* success_out, std::string* error_out) override {
       return 0;
     }
     virtual bool setCurrentIteration(uint64_t value, std::string* error_out) override { return true; }
-    virtual bool lookupRuleResult(KeyID keyID,
-                                  const Rule& rule,
+    virtual bool lookupRuleResult(const Rule& rule,
                                   Result* result_out,
                                   std::string* error_out) override {
       return false;
     }
-    virtual bool setRuleResult(KeyID key,
-                               const Rule& rule,
+    virtual bool setRuleResult(const Rule& rule,
                                const Result& result,
                                std::string* error_out) override {
       ruleResults[rule.key] = result;