C++ MySQL++ Удалить запрос запроса мозг убийца вопрос

Я относительно новичок в коннекторе MySQL++ в C++, и у меня уже есть действительно раздражающая проблема!

Мне удалось заставить хранимые процедуры работать, но у меня возникли проблемы с операторами удаления. Я посмотрел высоко и низко и не нашел документации с примерами.

Сначала я подумал, что, возможно, код должен освободить результаты запроса / соединения после вызова хранимой процедуры, но, конечно, MySQL++ не имеет метода free_result... или так?

В любом случае, вот что у меня есть:

#include <iostream>
#include <stdio.h>
#include <queue>
#include <deque>
#include <sys/stat.h>
#include <mysql++/mysql++.h>
#include <boost/thread/thread.hpp>
#include "RepositoryQueue.h"

using namespace boost;
using namespace mysqlpp;

class RepositoryChecker
{
private:
    bool _isRunning;
Connection _con;
public:
RepositoryChecker()
{
    try
    {
        this->_con = Connection(false);
        this->_con.set_option(new MultiStatementsOption(true));
        this->_con.set_option(new ReconnectOption(true));
        this->_con.connect("**", "***", "***", "***");

        this->ChangeRunningState(true);
    }
    catch(const Exception& e)
    {
        this->ChangeRunningState(false);
    }
}
/**
* Thread method which runs and creates the repositories
*/
void CheckRepositoryQueues()
{
    //while(this->IsRunning())
    //{
        std::queue<RepositoryQueue> queues = this->GetQueue();

        if(queues.size() > 0)
        {
            while(!queues.empty())
            {
                RepositoryQueue &q = queues.front();
                char cmd[256];
                sprintf(cmd, "svnadmin create /home/svn/%s/%s/%s", q.GetPublicStatus().c_str(),
                    q.GetUsername().c_str(), q.GetRepositoryName().c_str());
                    if(this->DeleteQueuedRepository(q.GetQueueId()))
                    {
                        printf("query deleted?\n");
                    }
                    printf("Repository created!\n");
                queues.pop();
            }
        }
        boost::this_thread::sleep(boost::posix_time::milliseconds(500));
    //}
}
protected:
/**
* Gets the latest queue of repositories from the database
* and returns them inside a cool queue defined with the 
* RepositoryQueue class.
*/
std::queue<RepositoryQueue> GetQueue()
{
    std::queue<RepositoryQueue> queues;

    Query query = this->_con.query("CALL sp_GetRepositoryQueue();");
    StoreQueryResult result = query.store();
    RepositoryQueue rQ;

    if(result.num_rows() > 0)
    {
        for(unsigned int i = 0;i < result.num_rows(); ++i)
        {
            rQ = RepositoryQueue((unsigned int)result[i][0],
                                (unsigned int)result[i][1],
                                (String)result[i][2],
                                (String)result[i][3],
                                (String)result[i][4],
                                (bool)result[i][5]);
            queues.push(rQ);
        }
    }

    return queues;
}
/**
* Allows the thread to be shut off.
*/
void ChangeRunningState(bool isRunning)
{
    this->_isRunning = isRunning;
}
/**
* Returns the running value of the active thread.
*/
bool IsRunning()
{
    return this->_isRunning;
}
/**
* Deletes the repository from the mysql queue table. This is
* only called once it has been created.
*/
bool DeleteQueuedRepository(unsigned int id)
{
    char cmd[256];
    sprintf(cmd, "DELETE FROM RepositoryQueue WHERE Id = %d LIMIT 1;", id);
    Query query = this->_con.query(cmd);
    return (query.exec());
}
};

Я удалил все остальные методы, так как они не нужны...

По сути, это метод DeleteQueuedRepository, который не работает, GetQueue работает нормально.

PS: это на ОС Linux (сервер Ubuntu)

Большое спасибо, Шон

2 ответа

Решение

MySQL++ не имеет метода free_result... или он есть?

Это не нужно. Когда объект результата выходит из области видимости в конце GetQueue()вся связанная с ним память автоматически освобождается.

this->_con = Connection(false);

Три проблемы здесь:

  1. Когда вы создаете RepositoryChecker объект, вы уже создали Connection объект. Если вам нужно передать различные параметры его конструктору, вы должны сделать это в списке инициализации RepositoryChecker конструктор, а не в его теле. Прочитайте свою книгу C++.

    Вместо этого вы сделали: а) создать по умолчанию Connection объект, а затем б) создать другой Connection Объект с исключениями отключен, затем c) перезаписать первое вторым. Если это работает, это очень неэффективно. MySQL++ Connection В прошлом у объектов были проблемы с копиями, поэтому если вы используете старую версию библиотеки, это может объяснить ваши проблемы.

  2. Вы говорите Connection объект (и каждый объект, который он создает, даже косвенно, что означает почти все в MySQL++), вы не хотите, чтобы он генерировал исключения, но затем вы оборачиваете его в большой try блок. Выбери один.

    Я бы предложил использовать исключения - по умолчанию в MySQL++ - с учетом структуры вашего кода в настоящее время. Если в запросе есть ошибка DeleteQueuedRepository()нет никакого способа увидеть, что случилось, потому что ты просто прошел false до вызывающего абонента, который игнорируется, потому что нет else пункт по вызову. Если вы сделаете это, войдите e.what() сообщение в вашем catch блок. Вы просто выбрасываете эту информацию прямо сейчас.

  3. Есть несколько мест, где вы используете конструкции, которые больше похожи на Python (или, возможно, JavaScript), чем на C++. Это заставляет меня задуматься, не является ли ваша проблема ущербом, вызванным каким-либо другим неправильным использованием C++.

    В частности, в этой строке вы используете this указатель явно, для которого нет необходимости в C++. Этот код делает то же самое:

     _con = Connection(false);
    

    Хотя опять же, линия должна быть полностью заменена, используя RepositoryChecker вместо этого список инициализатора ctor.

Двигаясь дальше...

sprintf(cmd, "DELETE FROM RepositoryQueue WHERE Id = %d LIMIT 1;", id);

Как прокомментировали другие, вам лучше использовать Query интерфейс потока:

Query q = _con.query();
q << "DELETE FROM RepositoryQueue WHERE Id = " << id << " LIMIT 1";

Это имеет несколько преимуществ:

  • Исправляет проблему безопасности типов, подразумеваемую тем, кто предложил изменить ваш %d в %u, C++ IOStreams позаботится об этом за вас.

  • Автоматическое цитирование данных, вставленных в поток, при необходимости. (В данном случае это не так.)

  • Предотвращает любую возможность запуска за пределы буфера. Вы могли бы использовать непортативный snprintf() вместо здесь, но почему?

Если вы действительно довольны printf()вместо этого есть интерфейс запроса шаблона.

boost::this_thread::sleep(boost::posix_time::milliseconds(500));

Вы прочитали главу темы в руководстве пользователя? Вы не получаете безопасность потока бесплатно в MySQL++. Ваша проблема может быть связана с повреждением памяти.

Уоррен Янг, сопровождающий MySQL++

Попробуйте изменить "%d" на "%u" в sprintf.

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