Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed contribution queue not being deleted (1.4.x) #4353

Merged
merged 1 commit into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ bool DatabaseContributionQueue::Init(sql::Database* db) {
return false;
}

// We need to clear queue if user has corrupted foreign key
// more info: https://github.com/brave/brave-browser/issues/7579
if (publishers_->HasCorruptedForeignKey(db)) {
if (!DeleteAllRecords(db)) {
return false;
}
}

return transaction.Commit();
}

Expand Down Expand Up @@ -148,8 +156,13 @@ ledger::ContributionQueuePtr DatabaseContributionQueue::GetFirstRecord(
bool DatabaseContributionQueue::DeleteRecord(
sql::Database* db,
const uint64_t id) {
if (!db->Execute("PRAGMA foreign_keys=1;")) {
LOG(ERROR) << "Error: deleting record for contribution queue with id" << id;
DCHECK(db);
if (id == 0 || !db) {
return false;
}

sql::Transaction transaction(db);
if (!transaction.Begin()) {
return false;
}

Expand All @@ -163,11 +176,41 @@ bool DatabaseContributionQueue::DeleteRecord(

bool success = statement.Run();

if (!db->Execute("PRAGMA foreign_keys=0;")) {
if (!success) {
return false;
}

if (!publishers_->DeleteRecordsByQueueId(db, id)) {
return false;
}

return transaction.Commit();
}

bool DatabaseContributionQueue::DeleteAllRecords(sql::Database* db) {
DCHECK(db);
if (!db) {
return false;
}

return success;
sql::Transaction transaction(db);
if (!transaction.Begin()) {
return false;
}

const std::string query = base::StringPrintf("DELETE FROM %s", table_name_);
sql::Statement statement(db->GetUniqueStatement(query.c_str()));
bool success = statement.Run();

if (!success) {
return false;
}

if (!publishers_->DeleteAllRecords(db)) {
return false;
}

return transaction.Commit();
}

} // namespace brave_rewards
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class DatabaseContributionQueue: public DatabaseTable {

bool DeleteRecord(sql::Database* db, const uint64_t id);

bool DeleteAllRecords(sql::Database* db);

private:
std::string GetIdColumnName();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "sql/statement.h"
#include "sql/transaction.h"

namespace {
const char kCorruptedForeignKey[] = "publisher_info_old";
} // namespace

namespace brave_rewards {

DatabaseContributionQueuePublishers::DatabaseContributionQueuePublishers(
Expand Down Expand Up @@ -121,4 +125,56 @@ DatabaseContributionQueuePublishers::GetRecords(
return list;
}

bool DatabaseContributionQueuePublishers::DeleteRecordsByQueueId(
sql::Database* db,
const uint64_t queue_id) {
DCHECK(db);
if (queue_id == 0 || !db) {
return false;
}

const std::string query = base::StringPrintf(
"DELETE FROM %s WHERE %s_id = ?",
table_name_,
parent_table_name_);

sql::Statement statement(db->GetUniqueStatement(query.c_str()));
statement.BindInt64(0, queue_id);

return statement.Run();
}

bool DatabaseContributionQueuePublishers::HasCorruptedForeignKey(
sql::Database* db) {
DCHECK(db);
if (!db) {
return false;
}

const std::string query = base::StringPrintf(
"PRAGMA foreign_key_list(%s)",
table_name_);

sql::Statement statement(db->GetUniqueStatement(query.c_str()));

while (statement.Step()) {
if (statement.ColumnString(2) == kCorruptedForeignKey) {
return true;
}
}

return false;
}

bool DatabaseContributionQueuePublishers::DeleteAllRecords(sql::Database* db) {
DCHECK(db);
if (!db) {
return false;
}

const std::string query = base::StringPrintf("DELETE FROM %s", table_name_);
sql::Statement statement(db->GetUniqueStatement(query.c_str()));
return statement.Run();
}

} // namespace brave_rewards
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class DatabaseContributionQueuePublishers: public DatabaseTable {
sql::Database* db,
const uint64_t queue_id);

bool DeleteRecordsByQueueId(sql::Database* db, const uint64_t queue_id);

bool HasCorruptedForeignKey(sql::Database* db);

bool DeleteAllRecords(sql::Database* db);

private:
const char* table_name_ = "contribution_queue_publishers";
const int minimum_version_ = 9;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ class PublisherInfoDatabaseTest : public ::testing::Test {
int end_version) {
const std::string file_name = "publisher_info_db_v" +
std::to_string(start_version);

LoadDatabaseFile(temp_dir, db_file, file_name, "migration", end_version);
}

void LoadDatabaseFile(
base::ScopedTempDir* temp_dir,
base::FilePath* db_file,
const std::string& file_name,
const std::string& folder,
int end_version) {
ASSERT_TRUE(temp_dir->CreateUniqueTempDir());
*db_file = temp_dir->GetPath().AppendASCII(file_name);

Expand All @@ -69,7 +79,7 @@ class PublisherInfoDatabaseTest : public ::testing::Test {
ASSERT_TRUE(base::PathService::Get(brave::DIR_TEST_DATA, &path));
path = path.AppendASCII("rewards-data");
ASSERT_TRUE(base::PathExists(path));
path = path.AppendASCII("migration");
path = path.AppendASCII(folder);
ASSERT_TRUE(base::PathExists(path));
path = path.AppendASCII(file_name);
ASSERT_TRUE(base::PathExists(path));
Expand Down Expand Up @@ -1509,4 +1519,36 @@ TEST_F(PublisherInfoDatabaseTest, RemoveAllPendingContributions) {
EXPECT_EQ(CountTableRows("pending_contribution"), 0);
}

TEST_F(PublisherInfoDatabaseTest,
ContributionQueueKeyCorrupted) {
base::ScopedTempDir temp_dir;
base::FilePath db_file;
LoadDatabaseFile(
&temp_dir,
&db_file,
"contribution_queue_key_corrupted",
"database",
9);
EXPECT_TRUE(publisher_info_database_->Init());

EXPECT_EQ(CountTableRows("contribution_queue"), 0);
EXPECT_EQ(CountTableRows("contribution_queue_publishers"), 0);
}

TEST_F(PublisherInfoDatabaseTest,
ContributionQueueKeyOk) {
base::ScopedTempDir temp_dir;
base::FilePath db_file;
LoadDatabaseFile(
&temp_dir,
&db_file,
"contribution_queue_key_ok",
"database",
9);
EXPECT_TRUE(publisher_info_database_->Init());

EXPECT_EQ(CountTableRows("contribution_queue"), 1);
EXPECT_EQ(CountTableRows("contribution_queue_publishers"), 1);
}

} // namespace brave_rewards
Binary file not shown.
Binary file not shown.