2011-02-09 8 views
1

私はC++のMySQL ++コネクタには比較的新しいので、既にそれは本当に厄介な問題があります!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のサーバ)

多くのおかげで、 ショーン

+1

あなたのクエリをフォーマットするためにはsprintfを使用している場合は、その理由だけではなく、は、MySQL/C APIを使用していませんか? MySQL ++の主な利点の1つは、クエリを構築するためにoperator <<を使用できるようにすることです(また、自動的にものをエスケープするストリーム修飾子もあります...ところで、十分にエスケープしないでください)。 –

答えて

2

MySQL ++にはfree_resultメソッドがありませんか?

これは必要ありません。結果オブジェクトがGetQueue()の末尾にあるスコープから外れると、それに関連付けられたすべてのメモリは自動的に解放されます。ここ

this->_con = Connection(false); 

三つの問題:あなたはRepositoryCheckerオブジェクトを作成すると

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

    ここでは、a)既定のConnectionオブジェクトを作成し、b)例外を無効にして別のConnectionオブジェクトを作成し、次にc)最初のものを2番目のものに上書きします。それがうまくいくならば、それは非常に非効率的です。 MySQL ++ Connectionオブジェクトには過去のコピーマネージャに問題がありました。そのため、古いバージョンのライブラリを使用している場合は、問題を説明することができます。

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

    私は、コードが現在構造化されているので、— MySQLのデフォルトで—を使用することをお勧めします。 DeleteQueuedRepository()にクエリーエラーが発生した場合、falseを呼び出し側に渡すだけなので、何が起こったのかわかりません。コールにはelse句がないため無視されます。これを行う場合は、catchブロックにe.what()メッセージを記録してください。その情報をすぐに投げているだけです。

  3. C++よりもPython(またはJavaScript)のように見える構文を使用している場所がいくつかあります。これはあなたの問題がC++の他の誤用によって引き起こされた損害ではないかと思います。

    特にこの行では、thisポインタを明示的に使用しています。そのため、C++では必要ありません。再び、ラインではなくRepositoryChecker CTOR初期化子リストを使用して、完全に交換する必要がありますけれども

    _con = Connection(false); 
    

    :このコードはまったく同じことを行います。他の人のよう

上を移動する...

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()には本当に満足している場合は、代わりにtemplate query interfaceがあります。

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

あなたはthreads chapterのユーザーマニュアルを読んでいますか? MySQL ++でスレッドセーフティを無料で取得することはありません。あなたの問題はメモリの破損に起因する可能性があります。

ウォーレン・ヤングは、MySQL ++メンテナ

+0

あなたの返信にウォーレンさんありがとうございました。頼んだことをやったことがありました.BudQueryの例外によってスローされた次の例外が表示されます: "コマンドが同期していない;このコマンドを今実行することはできません"それは、接続が閉じられていないか、または私が間違った順序でメソッド呼び出しを使用した場合、そのエラーがスローされることを読んだことがあります。 – shauny

+0

あなたのケースでは、ストアドプロシージャコールからすべての結果セットを消費していないことをほぼ確実に意味します。少なくとも2つ、つまりストアド・プロシージャ自体からの少なくとも1つの結果セットと、ストアド・プロシージャ・コールの終了ステータスを含む1つ以上の結果セットが得られます。 MySQL ++の 'examples/multiquery.cpp'の' print_multiple_results() 'を調べてください。 –

+0

ウォーレン、私はあなたにビールを借りている!私を助けてくれてありがとう。 – shauny

0

に "%U" はsprintfでの "%d" を変更してみてください。

+0

ありがとうSteve、私はウォーレンがクエリー<< "query" << param; – shauny