Получение списка нарушений внешнего ключа SQLite C++

Я добавляю для своей программы возможность удалять любую строку в базе данных, но эта база данных использует общие ключи с шестью другими базами данных. Для начала я убедился, что внешние ключи включены:

void SQLitePatternSet::enableForeignKeys() 
{
    char *msg;

    int result = sqlite3_exec(db1, "PRAGMA foreign_keys=ON;", nullptr,
                          nullptr, &msg);
    if (result != SQLITE_OK)
    {
        std::string errMsg = "Failed to enable foreign key support: ";
        errMsg += msg;
        sqlite3_free(msg);
        throw std::runtime_error(errMsg);
    }
}

И что к соответствующим строкам в базе данных прикреплен ON DELETE CASCADE. Несмотря на это, я все еще получаю сообщение об ошибке SQLITE_CONSTRAINT_FOREIGNKEY. Теперь хотелось бы перечислить, какие ключи нарушаются при удалении:

bool SQLitePatternSet::removeRow(const std::int64_t db1RowID)
{
    bool removed = true;
    std::string sql = "DELETE FROM Database1 WHERE RowID = :id;";
    sqlite3_stmt *removeStmt;
    prepStatement(sql, removeStmt);

    sqlite3_bind_int64(removeStmt, 1, db1RowID);

    int sqlResult = sqlite3_step(removeStmt);
    if (sqlResult != SQLITE_DONE)
    {
        if (sqlite3_extended_errcode(db1) == SQLITE_CONSTRAINT_FOREIGNKEY)
        {
            removed = false;
            result = sqlite3_exec(db1, "PRAGMA foreign_key_check(Database1);", foreignKeyCheckCallback, nullptr, nullptr);
        }
        else
        {
            auto errMsg = formatErrMsg("removeRow failed");
            throw pset_errors::storage_error(errMsg);
        }
    }
    data1.erase(db1RowID);
    sqlite3_finalize(removeStmt);
    return removed;
}

Но здесь я застрял. Кажется, проверка внешнего ключа должна работать, где:

int foreignKeyCheckCallback(void *a_param, int argc, char **argv, char **column){
    std::string msg = "Foreign key check:\n";
    for (int i = 0; i < argc; i++) {
        msg += argv[i];
        if (i < argc - 1)
            msg += "\n";
    }
    throw std::runtime_error(msg);
    return 1;
}

Результат возвращает 0, что означает отсутствие ошибок в синтаксисе sqlite3_exec(). Но после нескольких тестов обратный вызов никогда не запускается, что (на самом деле) означает, что нет ключей, которые вызывают рассматриваемую ошибку внешнего ключа. Как такое может быть? Или Foreign_key_check по своей природе просто не выводится в обратный вызов?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, оказывается, что ошибку вызывали не внешние ключи в базе данных 1, а ключи в другой базе данных, которые ссылались на первичный ключ в базе данных 1. Выбор всех строк в базе данных 2, которые ссылаются на 1, а затем удаление их из 2. , решил проблему:

bool SQLitePatternSet::removeRow(const std::int64_t db1RowID)
{
std::string sql1 = "SELECT DB2RowID FROM Database2 WHERE DB1RowID = :id;";
sqlite3_stmt *selStmt;
prepStatement(sql1, selStmt);
sqlite3_bind_int64(selStmt, 1, db1RowID);

int sqlresult1;
std::vector<std::int64_t> db2RowIDs;
do
{
    sqlresult1 = sqlite3_step(selStmt);
    if (sqlresult1 == SQLITE_ROW)
    {
        std::int64_t db2RowID = sqlite3_column_int64(selStmt, 0);
        db2RowIDs.push_back(db2RowID);
    }
    else if (sqlresult1 != SQLITE_DONE)
    {
        throw pset_errors::storage_error(
            formatSQLErr("removeRow failed"));
    }
} while(sqlresult1 != SQLITE_DONE);
sqlite3_finalize(selStmt);

bool removed = true;
for (std::int64_t db2RowID: db2RowIDs) {
    std::string sql2 = "DELETE FROM Database2 WHERE DB2RowID = :id;";
    sqlite3_stmt *removeStmt;
    prepStatement(sql2, removeStmt);
    sqlite3_bind_int64(removeStmt, 1, db2RowID );

    int sqlResult2 = sqlite3_step(removeStmt);
    if (sqlResult2 != SQLITE_DONE)
    {
        if (sqlite3_extended_errcode(db1) == SQLITE_CONSTRAINT_FOREIGNKEY)
        {
            removed = false;
        }
        else
        {
            auto errMsg = formatErrMsg("removeRow failed");
            throw pset_errors::storage_error(errMsg);
        }
    }
    data1.erase(db1RowID);
    sqlite3_finalize(removeStmt);
}
return removed;

}

Другие вопросы по теме

Похожие вопросы

Устранение ошибки компилятора при вызове большинства производных методов с помощью ссылки «выведено это»
Как GHC фиксирует окружение переменных, когда лямбда-выражения используются по значению или по ссылке?
Хотя программа на C++ компилируется без ошибок во время выполнения, я использую std::bad_alloc
Совместное использование обратного вызова члена класса с другим классом
C++ Cmake: как проверить, существует ли компилятор, и выбрать его
Исключение формата журнала 4688 с помощью FormatMessageW
OpenCV не читает изображение, даже если путь правильный, строка кажется пустой (imread_(''): невозможно открыть/прочитать файл: проверьте путь/целостность файла)
Нет соответствия для 'operator==' в GCC 12
C++ — функция недоступна, если неконстантная версия существует как защищенная
Как использовать Enable_if для специализации шаблона с неопределенными аргументами