1

我对 C++ 中的 MySQL++ 连接器比较陌生,并且已经遇到了一个非常烦人的问题!

我已经设法让存储过程正常工作,但是我遇到了删除语句的问题。我看了看高低,没有找到带有示例的文档。

首先我想也许代码需要在调用存储过程后释放查询/连接结果,但当然 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 服务器)上

非常感谢,肖恩

4

2 回答 2

2

MySQL++ 没有 free_result 方法......还是有?

它不需要一个。当结果对象在 结束时超出范围时GetQueue(),与其关联的所有内存都会自动释放。

this->_con = Connection(false);

这里有三个问题:

  1. 创建RepositoryChecker对象时,您已经创建了一个Connection对象。如果您需要将不同的参数传递给它的构造函数,您应该在RepositoryChecker构造函数的初始化列表中执行此操作,而不是在其主体中。阅读您的 C++ 书籍。

    您在这里所做的是 a) 创建一个默认Connection对象,然后 b) 创建一个Connection关闭异常的不同对象,然后 c) 用第二个覆盖第一个对象。如果这样行得通,那就是非常低效的。MySQL++Connection对象过去曾在其复制 ctor 方面遇到过问题,因此如果您使用的是旧版本的库,它可以解释您的问题。

  2. 你告诉Connection对象(以及它创建的每个对象,甚至是间接的,这意味着 MySQL++ 中的几乎所有东西)你不希望它抛出异常,但是你将它包装在一个大块中try。选一个。

    鉴于您的代码当前的结构方式,我建议使用异常(MySQL++ 中的默认设置)。如果在 中出现查询错误DeleteQueuedRepository(),则无法查看发生了什么,因为您只需将其传递false给调用者,由于调用中没有else子句,因此将被忽略。如果您这样做,请将e.what()消息记录在您的catch块中。你现在只是把这些信息扔掉。

  3. 有几个地方你使用的结构看起来更像 Python(或者可能是 JavaScript)而不是 C++。这让我想知道您的问题是否不是由其他滥用 C++ 造成的损坏。

    特别是在这一行上,您this显式地使用了指针,C++ 中不需要。这段代码做同样的事情:

     _con = Connection(false);
    

    尽管如此,应该使用RepositoryCheckerctor 初始化器列表来完全替换该行。

继续...

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++ 中,您不会免费获得线程安全。您的问题可能是由于内存损坏。

Warren Young,MySQL++ 维护者

于 2011-02-10T07:23:25.193 回答
0

尝试在 sprintf 中将“%d”更改为“%u”。

于 2011-02-09T23:34:07.437 回答