sqlite32013.06.11 16:57

그냥 보통 방법으로 INSERT와 DELETE등의 쿼리를 반복적으로 수행할때에 sqlite3의 성능은 형편없이 떨어지는데, 이럴때에는 Transaction을 이용해야 한다. 100개의 INSERT에 5초이상 걸리기도 하니 Transaction은 필수적이다.


int TSqlite::ExecuteMulti(const list<string> &queries)

{

// begin

sqlite3_exec(this->m_db, "BEGIN TRANSACTION;", 0, 0, 0);


list<string>::const_iterator ils = queries.begin();

while(ils != queries.end()){

sqlite3_exec(this->m_db, ils->c_str(), 0, 0, 0);

ils++;

}


// end

sqlite3_exec(this->m_db, "END TRANSACTION;", 0, 0, 0);


return sqlite3_total_changes(this->m_db);

}


sqlite3 stmt를 사용하지 않고, 간단히 구성해 보았다.  BEGIN - query - END 형식으로, 최종적으로 Effected Rows를 돌려주도록 하였다. 

테스트로 INSERT 600개를 연속으로 보냈을때에, 실행시간은 약 5초-> 0.05초로 백배 이상 빨라졌다. 

Posted by Jadumate

댓글을 달아 주세요

sqlite32013.05.24 20:55

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

}







Posted by Jadumate

댓글을 달아 주세요

분류없음2013.04.15 12:50




텍스트모드일때의 메모리주소는 B800:0000 이고, 화면의 각 한글자는 2byte로 글자와 속성의 쌍으로 구성되어 있다. 

이것을 활용하면, 단지 비디오메모리에 데이터를 넣어주는 것만으로도 화면에 글자 출력가능!


하지만 이 코드는 무려 20년전 DOS시절의 코드라 Turbo C에서나 컴파일 가능.

Posted by Jadumate

댓글을 달아 주세요

  1. pooh오빠

    바이오스에서 글자를 찍어주죠...ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

    2015.06.02 01:18 [ ADDR : EDIT/ DEL : REPLY ]

분류없음2012.11.28 17:55

보통 일반 편집기(윈도우라면 메모장)으로 편집한 텍스트파일은 인코딩정보를 담고 있지 않다. 


그런데, 윈도우 메모장에서 유니코드 혹은 UTF-8로 저장하면 텍스트파일 앞 부분에 2~3바이트의 인코딩정보가 기록된다. 이 이유로 프로그램에서 txt, cfg, xml 또는 csv 파일을 이용할때에, 이 2~3바이트의 BOM(Byte Order Mark)가 존재하는지를 체크해야만 한다. 





Text File 에서의 BOM

FF FE  UCS-2LE or UTF-16LE

FE FF  UCS-2BE or UTF-16BE

EF BB BF  UTF-8



XML File 에서의 BOM

3C 00  UCS-2LE or UTF-16LE

00 3C  UCS-2BE or UTF-16BE

3C XX  UTF-8 (where XX is non-zero)



html 이나, xml 에서는 좀 더 유연한 방법으로 인코딩 정보를 담는다.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<?xml version="1.0" encoding="iso-8859-1"?>




보다 자세한 정보, 출처 : http://codesnipers.com/?q=node/68

Posted by Jadumate

댓글을 달아 주세요