#include "data.h"
#include <string>
#include <utility>
namespace
{
mw::Error unsupportedVersionError(std::int64_t version)
{
return mw::runtimeError(
"Database schema version " + std::to_string(version) +
" is newer than supported version " +
std::to_string(DB_SCHEMA_VERSION) + ".");
}
mw::Error migrationVersionError(
std::int64_t expected_version,
std::int64_t actual_version)
{
return mw::runtimeError(
"Database migration should have produced schema version " +
std::to_string(expected_version) + ", but produced version " +
std::to_string(actual_version) + ".");
}
} // namespace
mw::E<std::int64_t> DataSourceTransactionInterface::insertCard(
[[maybe_unused]] const Card& card,
[[maybe_unused]] const std::vector<GameFieldValue>& field_values,
[[maybe_unused]] const std::vector<std::int64_t>& series_ids)
{
return std::unexpected(mw::runtimeError(
"Dynamic game card persistence is unavailable"));
}
mw::E<void> DataSourceTransactionInterface::updateCard(
[[maybe_unused]] const Card& card,
[[maybe_unused]] const std::vector<GameFieldValue>& field_values,
[[maybe_unused]] const std::vector<std::int64_t>& series_ids)
{
return std::unexpected(mw::runtimeError(
"Dynamic game card persistence is unavailable"));
}
mw::E<std::optional<GameDefinitionSnapshot>>
DataSourceTransactionInterface::getGameDefinitionForUpdate(
[[maybe_unused]] const std::string& short_name)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<GameUsage> DataSourceTransactionInterface::getGameUsage(
[[maybe_unused]] const std::string& short_name)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::insertGame(
[[maybe_unused]] const Game& game)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::updateGame(
[[maybe_unused]] const std::string& short_name,
[[maybe_unused]] const std::string& display_name,
[[maybe_unused]] const std::string& description,
[[maybe_unused]] GameVisibility visibility,
[[maybe_unused]] std::int64_t expected_revision)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::deleteGame(
[[maybe_unused]] const std::string& short_name)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::insertGameField(
[[maybe_unused]] const GameField& field,
[[maybe_unused]] const std::vector<GameChoice>& choices)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::updateGameField(
[[maybe_unused]] std::int64_t field_id,
[[maybe_unused]] const std::string& label,
[[maybe_unused]] const std::vector<GameChoice>& choices)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::deleteGameField(
[[maybe_unused]] std::int64_t field_id)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::countFieldUsage(
[[maybe_unused]] std::int64_t field_id)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::countChoiceUsage(
[[maybe_unused]] std::int64_t field_id,
[[maybe_unused]] const std::string& value)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::updateGameFieldOrder(
[[maybe_unused]] const std::string& short_name,
[[maybe_unused]] const std::vector<std::int64_t>& field_ids)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::incrementGameRevision(
[[maybe_unused]] const std::string& short_name,
[[maybe_unused]] std::int64_t expected_revision)
{
return std::unexpected(mw::runtimeError(
"Game definition transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::seriesBelongToGame(
[[maybe_unused]] const std::string& short_name,
[[maybe_unused]] const std::vector<std::int64_t>& series_ids)
{
return std::unexpected(mw::runtimeError(
"Transactional series validation is unavailable"));
}
mw::E<std::optional<User>>
DataSourceTransactionInterface::getUserForUpdate(
[[maybe_unused]] std::int64_t user_id)
{
return std::unexpected(mw::runtimeError(
"User transactions are unavailable"));
}
mw::E<std::optional<User>>
DataSourceTransactionInterface::getUserByEmailKeyForUpdate(
[[maybe_unused]] const std::string& email_key)
{
return std::unexpected(mw::runtimeError(
"User transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::userOwnsCardForUpdate(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] std::int64_t card_id)
{
return std::unexpected(mw::runtimeError(
"Collection transactions are unavailable"));
}
mw::E<std::vector<Card>>
DataSourceTransactionInterface::getPoolCardsForUpdate()
{
return std::unexpected(mw::runtimeError(
"Collection transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::insertUser(
[[maybe_unused]] const User& user)
{
return std::unexpected(mw::runtimeError(
"User transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::updateUsername(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] const std::string& username,
[[maybe_unused]] const std::string& username_key)
{
return std::unexpected(mw::runtimeError(
"User transactions are unavailable"));
}
mw::E<bool> DataSourceTransactionInterface::promoteUser(
[[maybe_unused]] std::int64_t user_id)
{
return std::unexpected(mw::runtimeError(
"User transactions are unavailable"));
}
mw::E<AuthenticationReservation>
DataSourceTransactionInterface::reserveAuthenticationEmail(
[[maybe_unused]] const std::string& email_key,
[[maybe_unused]] std::int64_t now,
[[maybe_unused]] bool use_global_quota,
[[maybe_unused]] std::int64_t utc_day,
[[maybe_unused]] std::uint32_t daily_limit)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<std::int64_t>
DataSourceTransactionInterface::insertAuthenticationChallenge(
[[maybe_unused]] const std::string& email,
[[maybe_unused]] const std::string& email_key,
[[maybe_unused]] const TokenHash& token_hash,
[[maybe_unused]] std::int64_t created_at,
[[maybe_unused]] std::int64_t expires_at)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<bool>
DataSourceTransactionInterface::markAuthenticationChallengeDelivered(
[[maybe_unused]] std::int64_t challenge_id,
[[maybe_unused]] std::int64_t delivered_at)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<void>
DataSourceTransactionInterface::deleteAuthenticationChallenge(
[[maybe_unused]] std::int64_t challenge_id)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<std::optional<AuthenticationChallenge>>
DataSourceTransactionInterface::consumeAuthenticationChallenge(
[[maybe_unused]] const TokenHash& token_hash,
[[maybe_unused]] std::int64_t now)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<void>
DataSourceTransactionInterface::invalidateAuthenticationChallenges(
[[maybe_unused]] const std::string& email_key,
[[maybe_unused]] std::int64_t except_challenge_id,
[[maybe_unused]] std::int64_t now)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::insertSession(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] const TokenHash& token_hash,
[[maybe_unused]] const std::string& csrf_token,
[[maybe_unused]] std::int64_t created_at,
[[maybe_unused]] std::int64_t expires_at)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::deleteSession(
[[maybe_unused]] const TokenHash& token_hash)
{
return std::unexpected(mw::runtimeError(
"Authentication transactions are unavailable"));
}
mw::E<void> DataSourceTransactionInterface::updatePullState(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] std::uint32_t stored_pulls,
[[maybe_unused]] std::int64_t refresh_day)
{
return std::unexpected(mw::runtimeError(
"Collection transactions are unavailable"));
}
mw::E<std::int64_t> DataSourceTransactionInterface::incrementHolding(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] std::int64_t card_id)
{
return std::unexpected(mw::runtimeError(
"Collection transactions are unavailable"));
}
mw::E<std::vector<Card>> DataSourceInterface::getCardsByCreator(
[[maybe_unused]] std::int64_t creator_user_id,
[[maybe_unused]] GameContentScope scope) const
{
return std::unexpected(mw::runtimeError("User data is unavailable"));
}
mw::E<std::vector<Card>> DataSourceInterface::getPoolCards() const
{
return std::unexpected(mw::runtimeError(
"Collection data is unavailable"));
}
mw::E<std::optional<User>> DataSourceInterface::getUser(
[[maybe_unused]] std::int64_t user_id) const
{
return std::unexpected(mw::runtimeError("User data is unavailable"));
}
mw::E<std::optional<User>> DataSourceInterface::getUserByEmailKey(
[[maybe_unused]] const std::string& email_key) const
{
return std::unexpected(mw::runtimeError("User data is unavailable"));
}
mw::E<std::vector<User>> DataSourceInterface::getUsers() const
{
return std::unexpected(mw::runtimeError("User data is unavailable"));
}
mw::E<std::optional<SessionContext>> DataSourceInterface::getSession(
[[maybe_unused]] const TokenHash& token_hash,
[[maybe_unused]] std::int64_t now) const
{
return std::unexpected(mw::runtimeError(
"Authentication data is unavailable"));
}
mw::E<std::optional<AuthenticationChallenge>>
DataSourceInterface::getAuthenticationChallenge(
[[maybe_unused]] const TokenHash& token_hash,
[[maybe_unused]] std::int64_t now) const
{
return std::unexpected(mw::runtimeError(
"Authentication data is unavailable"));
}
mw::E<std::vector<CollectionEntry>> DataSourceInterface::getCollection(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] GameContentScope scope) const
{
return std::unexpected(mw::runtimeError(
"Collection data is unavailable"));
}
mw::E<bool> DataSourceInterface::userOwnsCard(
[[maybe_unused]] std::int64_t user_id,
[[maybe_unused]] std::int64_t card_id) const
{
return std::unexpected(mw::runtimeError(
"Collection data is unavailable"));
}
mw::E<User> DataSourceInterface::reconcileAdministrator(
[[maybe_unused]] const std::string& email,
[[maybe_unused]] const std::string& email_key,
[[maybe_unused]] std::int64_t created_at,
[[maybe_unused]] std::int64_t pull_refresh_day)
{
return std::unexpected(mw::runtimeError("User data is unavailable"));
}
mw::E<void> DataSourceInterface::cleanupAuthentication(
[[maybe_unused]] std::int64_t now)
{
return std::unexpected(mw::runtimeError(
"Authentication data is unavailable"));
}
mw::E<std::vector<Game>> DataSourceInterface::getGames(
[[maybe_unused]] GameContentScope scope) const
{
return std::unexpected(mw::runtimeError("Game data is unavailable"));
}
mw::E<std::optional<GameDefinitionSnapshot>>
DataSourceInterface::getGameDefinition(
[[maybe_unused]] const std::string& short_name,
[[maybe_unused]] GameContentScope scope) const
{
return std::unexpected(mw::runtimeError("Game data is unavailable"));
}
mw::E<std::optional<CardGameFields>>
DataSourceInterface::getCardFieldValues(
[[maybe_unused]] std::int64_t card_id,
[[maybe_unused]] GameContentScope scope) const
{
return std::unexpected(mw::runtimeError("Game data is unavailable"));
}
mw::E<void> DataSourceInterface::migrateToLatest()
{
auto version_result = getSchemaVersion();
if(!version_result)
{
return std::unexpected(std::move(version_result.error()));
}
std::int64_t version = *version_result;
if(version > DB_SCHEMA_VERSION)
{
return std::unexpected(unsupportedVersionError(version));
}
while(version < DB_SCHEMA_VERSION)
{
const std::int64_t expected_version = version + 1;
mw::E<void> migration_result = migrateSchema0To1();
if(!migration_result)
{
return std::unexpected(std::move(migration_result.error()));
}
version_result = getSchemaVersion();
if(!version_result)
{
return std::unexpected(std::move(version_result.error()));
}
version = *version_result;
if(version != expected_version)
{
return std::unexpected(
migrationVersionError(expected_version, version));
}
}
return {};
}