diff --git a/components/brave_ads/core/internal/account/transactions/transaction_info.cc b/components/brave_ads/core/internal/account/transactions/transaction_info.cc index 1f288b1c3a29..d0aa830867e8 100644 --- a/components/brave_ads/core/internal/account/transactions/transaction_info.cc +++ b/components/brave_ads/core/internal/account/transactions/transaction_info.cc @@ -41,9 +41,9 @@ bool TransactionInfo::operator!=(const TransactionInfo& other) const { } bool TransactionInfo::IsValid() const { - return !id.empty() && !creative_instance_id.empty() && - ad_type != AdType::kUndefined && - confirmation_type != ConfirmationType::kUndefined && created_at; + return !id.empty() && created_at && !creative_instance_id.empty() && + !segment.empty() && ad_type != AdType::kUndefined && + confirmation_type != ConfirmationType::kUndefined; } } // namespace brave_ads diff --git a/components/brave_ads/core/internal/account/transactions/transactions_database_table.cc b/components/brave_ads/core/internal/account/transactions/transactions_database_table.cc index 4541fc73ca2c..a0f1ae9f1ebe 100644 --- a/components/brave_ads/core/internal/account/transactions/transactions_database_table.cc +++ b/components/brave_ads/core/internal/account/transactions/transactions_database_table.cc @@ -294,6 +294,63 @@ void MigrateToV39(mojom::DBTransactionInfo* const transaction) { transaction->commands.push_back(std::move(command)); } +void MigrateToV40(mojom::DBTransactionInfo* const transaction) { + CHECK(transaction); + + { + // Delete legacy transactions with an undefined `creative_instance_id`, + // `segment` or `ad_type`. + mojom::DBCommandInfoPtr command = mojom::DBCommandInfo::New(); + command->type = mojom::DBCommandInfo::Type::EXECUTE; + command->sql = + R"( + DELETE FROM + transactions + WHERE + COALESCE(creative_instance_id, '') = '' + OR COALESCE(segment, '') = '' + OR ad_type = '';)"; + transaction->commands.push_back(std::move(command)); + } + + { + // Create a temporary table: + // - with a new `creative_instance_id` column constraint. + // - with a new `segment` column constraint. + // - with a new `reconciled_at` default value. + mojom::DBCommandInfoPtr command = mojom::DBCommandInfo::New(); + command->type = mojom::DBCommandInfo::Type::EXECUTE; + command->sql = + R"( + CREATE TABLE transactions_temp ( + id TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE, + created_at TIMESTAMP NOT NULL, + creative_instance_id TEXT NOT NULL, + value DOUBLE NOT NULL, + segment TEXT NOT NULL, + ad_type TEXT NOT NULL, + confirmation_type TEXT NOT NULL, + reconciled_at TIMESTAMP DEFAULT 0 + );)"; + transaction->commands.push_back(std::move(command)); + + // Copy legacy columns to the temporary table, drop the legacy table, rename + // the temporary table and create an index. + const std::vector columns = { + "id", "created_at", "creative_instance_id", "value", + "segment", "ad_type", "confirmation_type", "reconciled_at"}; + + CopyTableColumns(transaction, "transactions", "transactions_temp", columns, + /*should_drop=*/true); + + RenameTable(transaction, "transactions_temp", "transactions"); + } + + // Optimize database query for `GetForDateRange`. + CreateTableIndex(transaction, /*table_name=*/"transactions", + /*columns=*/{"created_at"}); +} + } // namespace void Transactions::Save(const TransactionList& transactions, @@ -427,12 +484,12 @@ void Transactions::Create(mojom::DBTransactionInfo* transaction) { CREATE TABLE transactions ( id TEXT NOT NULL PRIMARY KEY ON CONFLICT REPLACE, created_at TIMESTAMP NOT NULL, - creative_instance_id TEXT, + creative_instance_id TEXT NOT NULL, value DOUBLE NOT NULL, - segment TEXT, + segment TEXT NOT NULL, ad_type TEXT NOT NULL, confirmation_type TEXT NOT NULL, - reconciled_at TIMESTAMP + reconciled_at TIMESTAMP DEFAULT 0 );)"; transaction->commands.push_back(std::move(command)); @@ -474,6 +531,11 @@ void Transactions::Migrate(mojom::DBTransactionInfo* transaction, MigrateToV39(transaction); break; } + + case 40: { + MigrateToV40(transaction); + break; + } } } diff --git a/components/brave_ads/core/internal/legacy_migration/database/database_constants.h b/components/brave_ads/core/internal/legacy_migration/database/database_constants.h index f81025912adc..7cf497cbf908 100644 --- a/components/brave_ads/core/internal/legacy_migration/database/database_constants.h +++ b/components/brave_ads/core/internal/legacy_migration/database/database_constants.h @@ -8,8 +8,8 @@ namespace brave_ads::database { -inline constexpr int kVersion = 39; -inline constexpr int kCompatibleVersion = 39; +inline constexpr int kVersion = 40; +inline constexpr int kCompatibleVersion = 40; } // namespace brave_ads::database diff --git a/components/brave_ads/core/test/data/database/database_schema_40.sqlite b/components/brave_ads/core/test/data/database/database_schema_40.sqlite new file mode 100644 index 000000000000..c4ac00450bbb Binary files /dev/null and b/components/brave_ads/core/test/data/database/database_schema_40.sqlite differ diff --git a/components/brave_ads/core/test/data/database/invalid_database_schema_40.sqlite b/components/brave_ads/core/test/data/database/invalid_database_schema_40.sqlite new file mode 100644 index 000000000000..c69cbc01e628 Binary files /dev/null and b/components/brave_ads/core/test/data/database/invalid_database_schema_40.sqlite differ