ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [sqlite3] wrapper class in c++ and STL on linux
    sqlite3 2013. 5. 24. 20:55
    728x90
    반응형

    sqlite3에 대한 C++ wrapper class 를 만들어 보았다. 


    간단하게 INSERT와 SELECT 정도만 편하게 했으면 좋겠다 싶은데, sqlite라는게 그리 간단하지가 않다. (gdbm 정도의 편리함을 기대했다면 오산이다). db를 open하고 close하는 사이에 prepare하고 free, finalize 하는게 생각보다 까다롭다. 


    그래서 요것만 후다닥 구현.


    class TSqlite

    {

    protected :

    bool m_isError;

    sqlite3 *m_db;


    private :

    bool Send(const char *strQuery);


    public:

    TSqlite(const char *strFileName)

    {

    m_isError = (sqlite3_open(strFileName, &m_db) == SQLITE_OK) ? false : true;

    }


    ~TSqlite()

    {

    if(m_db) sqlite3_close(m_db);

    }


    bool isError()

    {

    return m_isError;

    }


    int Execute(const char *strQuery);

    int Select (const char *strQuery, list< vector<string> > &rResult);

    };

    소스1 : sqlite.h


    bool TSqlite::Send(const char *strQuery)

    {

        sqlite3_stmt *stmt;

        bool result = true;


        int rc = sqlite3_prepare(this->m_db, strQuery, strlen(strQuery), &stmt, NULL);

        if(rc != SQLITE_OK) return false;


        if(sqlite3_step(stmt) != SQLITE_DONE) {

            fprintf(stderr, "line %d: %s (%s)\n", __LINE__, sqlite3_errmsg(this->m_db), strQeury);

            result = false;

        }

        sqlite3_reset(stmt);

        sqlite3_finalize(stmt);


        return result;

    };


    int TSqlite::Select(const char *strQuery, list< vector<string> >  &rResult)

    {

    int  nColumn = 0;

    char tbuf[64];

    sqlite3_stmt *stmt;

    vector<string> row1;


    sqlite3_prepare(this->m_db, strQuery, -1, &stmt, NULL);


    while(sqlite3_step(stmt) == SQLITE_ROW)

    {

    nColumn = sqlite3_column_count(stmt);


    row1.clear();

    for(int i = 0; i < nColumn ; i++) {

    switch(sqlite3_column_type(stmt, i)){

    case SQLITE_TEXT:

    row1.push_back((const char *)sqlite3_column_text(stmt, i));

    break;

    case SQLITE_INTEGER:

    sprintf(tbuf, "%d:", sqlite3_column_int(stmt, i));

    row1.push_back(tbuf);

    break;

    case SQLITE_FLOAT:

    sprintf(tbuf, "%f:", sqlite3_column_double(stmt, i));

    row1.push_back(tbuf);

    break;

    case SQLITE_NULL:

    break;

    default:

    break;

    }

    }

    rResult.push_back(row1);

    }

    sqlite3_reset(stmt);

    sqlite3_finalize(stmt);


    return rResult.size();

    }


    int TSqlite::Execute(const char *strQuery)

    {

    sqlite3_stmt *stmt;

    int result = 0;


    sqlite3_prepare(this->m_db, strQuery, -1, &stmt, NULL);


    // begin

    this->Send("BEGIN;");

    if(sqlite3_step(stmt) != SQLITE_DONE){

    fprintf(stderr, "line %d: %s  (%s)\n", __LINE__, sqlite3_errmsg(this->m_db), strQuery);

    result = -1;

    }

    // commit

    this->Send("COMMIT;");


    result = sqlite3_total_changes(this->m_db);


    sqlite3_reset(stmt);

    sqlite3_finalize(stmt);


    return result;

    }

    소스2 sqlite.cc



    이렇게 클래스를 만들어 두고 나니, 아래처럼 아주 간단하게 사용할 수 있다. 

    TSqlite sql(FILE_MY_DB);

    if(sql.isError()) return -1;


    // 결과를 받아올 리스트 생성

    list< vector<string> > rows;


    // 쿼리만들기 & 결과 가져오기

    sprintf(strQuery, "SELECT * from table WHERE id = '%s';", strId);

    int nRows = sql.Select(strQuery, rows);


    // 루프돌면서 결과값 출력

    list< vector<string> >::iterator it = rows.begin();

    while(it != rows.end()){

          // 레코드 1개 얻어오기

    vector<string> &rRow = *it;


    // 컬럼별로 출력

    for(int i=0; i< rRow.size(); i++)

        cout << rRow[i] << endl;


    it++;

    }







Designed by Tistory.