C ++ MySQL ++ Удалить запрос запроса мозг убийца вопрос - PullRequest
1 голос
/ 10 февраля 2011

Я относительно новичок в коннекторе 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 ]

2 голосов
/ 10 февраля 2011

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

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

this->_con = Connection(false);

Здесь три проблемы:

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

    Вместо этого вы сделали следующее: а) создайте объект Connection по умолчанию, затем б) создайте другой объект Connection с отключенными исключениями, затем в) перезапишите первыйсо вторым.Если это работает, это очень неэффективно.У объектов 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.

Перемещениеon ...

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 ++ Maintainer

0 голосов
/ 10 февраля 2011

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

...