1

私は C++ の MySQL++ コネクタに比較的慣れていないので、すでに非常に厄介な問題を抱えています。

ストアド プロシージャを機能させることができましたが、delete ステートメントに問題があります。私は高低を調べましたが、例を含むドキュメントは見つかりませんでした。

最初に、ストアド プロシージャを呼び出した後、コードでクエリ/接続の結果を解放する必要があるのではないかと考えましたが、もちろん 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 OS (Ubuntu サーバー) 上にあります。

どうもありがとう、ショーン

4

2 に答える 2

2

MySQL++ には free_result メソッドがありません... それともありますか?

それは必要ありません。の最後に結果オブジェクトが範囲外になるとGetQueue()、それに関連付けられているすべてのメモリが自動的に解放されます。

this->_con = Connection(false);

ここでの 3 つの問題:

  1. オブジェクトを作成するとRepositoryChecker、すでにオブジェクトが作成されていConnectionます。コンストラクターに異なるパラメーターを渡す必要がある場合は、RepositoryCheckerコンストラクターの本体ではなく、コンストラクターの初期化リストで行います。C++ の本を読んでください。

    ここで代わりに行ったことは、a) デフォルト オブジェクトを作成し、次に b)例外をオフにしConnectionて別のオブジェクトを作成し、c) 最初のものを 2 番目のもので上書きすることです。Connectionそれが機能する場合、それは非常に非効率的です。MySQL++Connectionオブジェクトは、過去にコピー ctor に問題があったため、古いバージョンのライブラリを使用している場合、問題が説明できる可能性があります。

  2. Connectionオブジェクト (およびそれが作成するすべてのオブジェクト、間接的であっても、MySQL++ のほとんどすべてを意味します) に例外をスローさせたくないことを伝えていますが、それを大きなブロックでラップしますtry。一つを選ぶ。

    現在のコードの構造を考えると、例外 (MySQL++ のデフォルト) を使用することをお勧めします。でクエリ エラーが発生した場合、呼び出し元にDeleteQueuedRepository()渡すだけなので、何が起こったのかを確認する方法はありません。呼び出しには句falseがないため、呼び出し元は無視されます。elseこれを行う場合は、e.what()メッセージをcatchブロックに記録します。あなたは今、その情報を捨てているだけです。

  3. C++ よりも Python (またはおそらく JavaScript) に似た構造を使用している場所がいくつかあります。これは、あなたの問題が 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()ここでは代わりにnonportable を使用できますが、なぜでしょうか?

に本当に満足している場合は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 に答える