Index: sql/connection.cc |
diff --git a/sql/connection.cc b/sql/connection.cc |
index 95d09c24ff532114518806ab4be262c6ef9ff003..d44758cee3b871e2ade1153f4b70456c0cf5013a 100644 |
--- a/sql/connection.cc |
+++ b/sql/connection.cc |
@@ -94,6 +94,21 @@ int BackupDatabase(sqlite3* src, sqlite3* dst, const char* db_name) { |
return rc; |
} |
+// Be very strict on attachment point. SQLite can handle a much wider |
+// character set with appropriate quoting, but Chromium code should |
+// just use clean names to start with. |
+bool ValidAttachmentPoint(const char* attachment_point) { |
+ for (size_t i = 0; attachment_point[i]; ++i) { |
+ if (!((attachment_point[i] >= '0' && attachment_point[i] <= '9') || |
+ (attachment_point[i] >= 'a' && attachment_point[i] <= 'z') || |
+ (attachment_point[i] >= 'A' && attachment_point[i] <= 'Z') || |
+ attachment_point[i] == '_')) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
} // namespace |
namespace sql { |
@@ -205,6 +220,10 @@ bool Connection::OpenInMemory() { |
return OpenInternal(":memory:", NO_RETRY); |
} |
+bool Connection::OpenTemporary() { |
+ return OpenInternal("", NO_RETRY); |
+} |
+ |
void Connection::CloseInternal(bool forced) { |
// TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point |
// will delete the -journal file. For ChromiumOS or other more |
@@ -412,9 +431,7 @@ bool Connection::RazeAndClose() { |
} |
// Raze() cannot run in a transaction. |
- while (transaction_nesting_) { |
- RollbackTransaction(); |
- } |
+ RollbackAllTransactions(); |
bool result = Raze(); |
@@ -428,6 +445,21 @@ bool Connection::RazeAndClose() { |
return result; |
} |
+void Connection::Poison() { |
+ if (!db_) { |
+ DLOG_IF(FATAL, !poisoned_) << "Cannot poison null db"; |
+ return; |
+ } |
+ |
+ RollbackAllTransactions(); |
+ CloseInternal(true); |
+ |
+ // Mark the database so that future API calls fail appropriately, |
+ // but don't DCHECK (because after calling this function they are |
+ // expected to fail). |
+ poisoned_ = true; |
+} |
+ |
// TODO(shess): To the extent possible, figure out the optimal |
// ordering for these deletes which will prevent other connections |
// from seeing odd behavior. For instance, it may be necessary to |
@@ -513,6 +545,35 @@ bool Connection::CommitTransaction() { |
return commit.Run(); |
} |
+void Connection::RollbackAllTransactions() { |
+ if (transaction_nesting_ > 0) { |
+ transaction_nesting_ = 0; |
+ DoRollback(); |
+ } |
+} |
+ |
+bool Connection::AttachDatabase(const base::FilePath& other_db_path, |
+ const char* attachment_point) { |
+ DCHECK(ValidAttachmentPoint(attachment_point)); |
+ |
+ Statement s(GetUniqueStatement("ATTACH DATABASE ? AS ?")); |
+#if OS_WIN |
+ s.BindString16(0, other_db_path.value()); |
+#else |
+ s.BindString(0, other_db_path.value()); |
+#endif |
+ s.BindString(1, attachment_point); |
+ return s.Run(); |
+} |
+ |
+bool Connection::DetachDatabase(const char* attachment_point) { |
+ DCHECK(ValidAttachmentPoint(attachment_point)); |
+ |
+ Statement s(GetUniqueStatement("DETACH DATABASE ?")); |
+ s.BindString(0, attachment_point); |
+ return s.Run(); |
+} |
+ |
int Connection::ExecuteAndReturnErrorCode(const char* sql) { |
AssertIOAllowed(); |
if (!db_) { |