| 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_) {
|
|
|