그럼 이 둘을 한데 합쳐서 만들게 된다면 다음 코드 정도가 된다.
void makeFileDB2SqliteDB(const pconnstrct connOpts)
{
int rc;
char err[5112];
char *errmsg;
int total_cnt =0;
int fileCnt = 0;
sqlite3_stmt *stmt;
sqlite3 *ptrSqliteConv;
makeSqliteDBTable(connOpts);
FileDBMgr->openSqliteConv(connOpts);
FileDBMgr->openRNoSql(connOpts);
ptrSqliteConv = FileDBMgr->ptrSqliteConv();
loadSQLStmtParam(connOpts, MISS_FILE_INFO_TABLE_NAME, "insert");
rc = sqlite3_prepare_v2(ptrSqliteConv, getSQLStmt(connOpts), -1, &stmt, 0);
LOG_TRACE(LOG_INFO, "2. [%s]\n%s\n", __FUNCTION__, getSQLStmt(connOpts));
LOG_TRACE(LOG_INFO, "\n2. [%s]The statement has %d wildcards\n", __FUNCTION__, sqlite3_bind_parameter_count(stmt));
if (rc != SQLITE_OK) {
LOG_TRACE(LOG_ERROR, "Failed to execute statement: %s\n", sqlite3_errmsg(ptrSqliteConv));
return;
}
string ckey, cvalue;
DB::Cursor* cur;
fileCnt = 0;
sqlite3_exec(ptrSqliteConv, "BEGIN TRANSACTION", NULL, NULL, &errmsg);
cur = FileDBMgr->ptrRNoSqlDB()->cursor();
cur->jump();
while (cur->get(&ckey, &cvalue, true)) {
fileCnt++;
insertArrangMissingFileInfo(ptrSqliteConv, stmt, ckey, cvalue);
if(((fileCnt % PRINT_CNT) == 0))
{
LOG_TRACE(LOG_ERROR, ".");
}
ckey.clear();
cvalue.clear();
}
delete cur;
sqlite3_exec(ptrSqliteConv, "END TRANSACTION", NULL, NULL, &errmsg);
sqlite3_exec(ptrSqliteConv, "COMMIT TRANSACTION", NULL, NULL, &errmsg);
LOG_TRACE(LOG_ERROR, "\r\n");
sqlite3_finalize(stmt);
LOG_TRACE(LOG_ERROR, "total...: %d\n", fileCnt);
FileDBMgr->closeSqlite(ptrSqliteConv);
FileDBMgr->closeRNoSql();
}
1. 선행 작업 진행
데이터를 집어 넣기 전에 테이블을 생성 한다.
makeSqliteDBTable(connOpts);
코드의 내용은 별 것 없으니, 설명한다면 sqlite 데이터베이스 열고, 테이블 스키마 대로 테이블을 생성하고, 인덱스를 생성 해 준 다음 열어논 sqlite 데이터베이스를 닫는 함수 이다.
2. 데이터 베이스 열기
sqlite과 kyotocabinet 데이터베이스를 다음과 같이 열어 준다.
FileDBMgr->openSqliteConv(connOpts);
FileDBMgr->openRNoSql(connOpts);
해당 sqlite 데이터베이스의 포인터를 얻는다.
ptrSqliteConv = FileDBMgr->ptrSqliteConv();
물론, 열면서 바로 얻을 수 있을 것인데, 그냥 내 맘대로 그렇게 했다.
3. 쿼리 문장 얻기
그런 다음, prepared 할 sql 문장을 xml 파일에서 준비한다.
loadSQLStmtParam(connOpts, MISS_FILE_INFO_TABLE_NAME, "insert");
사실 여기에는 약간의 히스토리가 있는 데, 다음 문서에 위의 내용이 있다.
[C-tinyXML] Sqlite 데이터베이스에 도로명 주소 테이블 만들어 보기 – XML 파일 바인딩
함수가 약간 변형 되긴 했는데...다음과 같이 했다.
내부적으로 loadQueryScheme 라는 함수를 사용하는 wrapper 함수 정도로 생각하면 된다.
void loadQueryScheme(const char *filename, char *elem, char *subelem, char **text)
{
#ifdef USING_POINTER_XML
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument(true, COLLAPSE_WHITESPACE);
doc->LoadFile( filename );
XMLElement* element = doc->RootElement();
doc->PrintError();
#else
tinyxml2::XMLDocument doc( true, COLLAPSE_WHITESPACE );
doc.LoadFile( filename );
//doc.Print();
const XMLElement* element = doc.RootElement();
doc.PrintError();
#endif
const char *contents = element->FirstChildElement(elem)->FirstChildElement(subelem)->GetText();
memcpy(*text, contents, strlen(contents) + 1);
#ifdef USING_POINTER_XML
delete doc;
#endif
return;
}
그리고 본 함수는 다음과 같다.
int loadSQLStmt(pconnstrct constr)
{
char *psqlbuf;
psqlbuf = constr->sqlbuf;
loadQueryScheme(constr->schemefile, constr->table_name, constr->operation, &psqlbuf);
LOG_TRACE(LOG_DEBUG, "[%s]/%s/%s/%s/%s\n\n",
__FUNCTION__, constr->schemefile, constr->table_name, constr->operation, constr->sqlbuf);
//LOG_TRACE(LOG_ERROR, "%s \n", constr->sqlbuf);
return 0;
}
4. 쿼리 문장 바인딩하기.
찾은 쿼리 문장을 다음과 같이 prepare 한다.
rc = sqlite3_prepare_v2(ptrSqliteConv, getSQLStmt(connOpts), -1, &stmt, 0);
5. kyotocabinet 데이터 검색하기.
여기서는 파일 내에 있는 데이터를 모두 검색 하는 것으로 진행 하는 데, 주요 원형은 다음과 같다.
string ckey, cvalue;
DB::Cursor* cur;
fileCnt = 0;
cur = FileDBMgr->ptrRNoSqlDB()->cursor();
cur->jump();
while (cur->get(&ckey, &cvalue, true)) {
fileCnt++;
insertInfo(ptrSqliteConv, stmt, ckey, cvalue);
if(((fileCnt % PRINT_CNT) == 0))
{
LOG_TRACE(LOG_ERROR, ".");
}
ckey.clear();
cvalue.clear();
}
delete cur;
내용은 코드에서 짐작 하듯이 string 값에다 key,value을 얻어와서는 해당 정보를 넣어 주는 것이다.
6. 트랜잭션 처리하기- sqlite
트랜잭션은 다음과 같이 처리 한다.
sqlite3_exec(ptrSqliteConv, "BEGIN TRANSACTION", NULL, NULL, &errmsg);
....코드 ....
sqlite3_exec(ptrSqliteConv, "END TRANSACTION", NULL, NULL, &errmsg);
sqlite3_exec(ptrSqliteConv, "COMMIT TRANSACTION", NULL, NULL, &errmsg);
7, 데이터베이스 닫아 주기
FileDBMgr->closeSqlite(ptrSqliteConv);
FileDBMgr->closeRNoSql();
사진 설명을 입력하세요.
8. 데이터 바인딩
여기서는 insert를 사용 할 것인데, 다음과 같이 사용 하면 된다.
nline void insertInfo(sqlite3 *ptrSqlite, sqlite3_stmt *stmt, const std::string key, const std::string value)
{
std::vector<std::string> output
= UtilW32::split(value, '\\');
string atch_fle_nm_kor, atch_fle_path, atch_fle_py_nm, path_tmp;
cmp_cod = output.at(1);
std::size_t found = value.find_last_of("/\\");
//마지막은 파일 이름이라고 생각하고 짤라 준다.
atch_fle_path = value;
atch_fle_path = value.substr(0,found);
atch_fle_nm = value.substr(found+1);
//한글의 경우에는 만들어진 sqlite 데이터베이스 문자셑이
//UTF-8 이므로 CP949에서 UTF-8로 변환 해 준다.
atch_fle_nm_kor
= UtilW32::convert(atch_fle_nm.c_str(), "CP949", "utf-8");
atch_fle_py_nm = atch_fle_nm_kor;
//UTF-8에서 한글 변환
path_tmp = UtilW32::convert(atch_fle_path.c_str(), "CP949", "utf-8");
if(bind_str(ptrSqlite, stmt, 1, reinterpret_cast<const char*>(key.c_str()) ) == false)
{ LOG_TRACE(LOG_ERROR, "\nFail to insert column 1: %s => %s\n", sqlite3_errmsg(ptrSqlite), key.c_str());}
if(bind_str(ptrSqlite, stmt, 2, reinterpret_cast<const char*>(cmp_cod.c_str()) ) == false)
{ LOG_TRACE(LOG_ERROR, "\nFail to insert column 2: %s => %s\n", sqlite3_errmsg(ptrSqlite), cmp_cod.c_str());}
//제대로 수행 했는 지 알아본다.
if (sqlite3_step(stmt) != SQLITE_DONE) {
LOG_TRACE(LOG_ERROR, "Could not step (execute) rows stmt: %s\n", sqlite3_errmsg(ptrSqlite));
}
//바인딩 했던 변수들을 모두 정리 해주는 작업
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
return;
}
:bind_str 함수
bool bind_str(sqlite3 *db, sqlite3_stmt *stmt, int index, const char *pstr)
{
int sz = strlen(pstr);
if (sqlite3_bind_text (
stmt, index, // Index of wildcard
pstr, sz, // length of text
SQLITE_STATIC
)!= SQLITE_OK
){
return false;
}
return true;
}
이상으로 sqlite과 Nosql 데이터베이스인 kyotocabinet를 사용하는 법에 대해서 알아봤다.
'프로그래밍' 카테고리의 다른 글
Pro*C 프로그래밍 (0) | 2023.03.18 |
---|---|
[Win32]현재 디렉토리 내 모든 파일 리스트 만들기 (1) | 2023.03.16 |
Maraa 와 wiringPi 라이브러리로 라즈베리 파이에서 센서 제어해 보기 (0) | 2023.03.13 |
개발하고 있는 웹페이지의 javascript 파일이 갱신 되지 않을때 (0) | 2023.03.12 |
MICROSOFT C Run-Time Win32 1 (2) | 2023.03.11 |