전문가칼럼

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

모바일 데이터베이스 SQLite 일곱번째 이야기(2)

전문가칼럼
DBMS별 분류
DB일반
작성자
dataonair
작성일
2001-12-31 23:30
조회
21448




◎ 연재기사 ◎


모바일 데이터베이스 SQLite의 첫 번째 이야기


모바일 데이터베이스 SQLite의 두 번째 이야기


모바일 데이터베이스 SQLite의 세 번째 이야기


모바일 데이터베이스 SQLite의 네 번째 이야기(1)


모바일 데이터베이스 SQLite의 네 번째 이야기(2)


모바일 데이터베이스 SQLite의 다섯번째 이야기


모바일 데이터베이스 SQLite의 여섯번째 이야기


모바일 데이터베이스 SQLite의 일곱번째 이야기(1)


모바일 데이터베이스 SQLite 일곱번째 이야기(2)


모바일 데이터베이스 SQLite 여덟번째 이야기(1)


모바일 데이터베이스 SQLite 여덟번째 이야기(2)


모바일 데이터베이스 SQLite 아홉번째 이야기


모바일 데이터베이스 SQLite 열번째 이야기


모바일 데이터베이스 SQLite의 마지막 이야기



김형훈의 DB이야기

모바일 데이터베이스 SQLite 일곱번째 이야기(2)

모바일을 위한 다양한 요구사항을 만족시키기 위한 데이터베이스 솔루션으로 대표적인 것이 SQLite이다. SQLite는 구글의 안드로이드나 애플의 아이폰 등에서 사용되는 솔루션으로 사용자 측면과 관리자 측면에서 모두 뛰어난 접근성을 가지고 있는 데이터베이스 관리 시스템이다. SQLite에 대해서 현재까지 기본적인 여섯 가지 이야기를 공유하였는데, 지금의 일곱 번째 이야기에서는 검색을 위한 요소인 R-트리에 대해서 살펴보도록 한다.

argv[0] : 모듈 이름
argv[1] : 데이터베이스 이름
argv[2] : 테이블 이름
argv[...] : 칼럼 이름
static int rtreeInit(
sqlite3 *db, /* 데이터베이스 연결 */
void *pAux, /* RTREE_COORD_* 상수 중 하나*/
int argc, const char *const*argv, /* CREATE TABLE 문장에 대한 파라미터 */
sqlite3_vtab **ppVtab, /* OUT: 새 가상 테이블 */
char **pzErr, /* OUT: 에러메시지 */
int isCreate /* True (xCreate), False (xConnect) */
){
int rc = SQLITE_OK;
int iPageSize = 0;
Rtree *pRtree;
int nDb; /* 문자열 argv[1]의 길이 */
int nName; /* 문자열 argv[2]의 길이 */
int eCoordType = (int)pAux;
const char *aErrMsg[] = {
0, /* 0 */
"Wrong number of columns for an rtree table", /* 1 */
"Too few columns for an rtree table", /* 2 */
"Too many columns for an rtree table" /* 3 */
};
int iErr = (argc<6) 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) 3 : argc%2;
if( aErrMsg[iErr] ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
return SQLITE_ERROR;
}
rc = getPageSize(db, argv[1], &iPageSize);
if( rc!=SQLITE_OK ){
return rc;
}
/* sqlite3_vtab 구조체 할당 */
nDb = strlen(argv[1]);
nName = strlen(argv[2]);
pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
if( !pRtree ){
return SQLITE_NOMEM;
}
memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
pRtree->nBusy = 1;
pRtree->base.pModule = &rtreeModule;
pRtree->zDb = (char *)&pRtree[1];
pRtree->zName = &pRtree->zDb[nDb+1];
pRtree->nDim = (argc-4)/2;
pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
pRtree->eCoordType = eCoordType;
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
/* 사용할 노드 사이즈를 파악한다.
** 기본적으로 데이터베이스 페이지 크기보다 작은 64 바이트를 사용한다.
** 이 값을 사용함으로서 단일 데이터베이스 페이지에 저장될 수 있음을 보장한다.
** 만약에 페이지 크기가 RTREE_MAXCELLS보다 크다면 작은 노드크기를 사용한다.
*/
pRtree->iNodeSize = iPageSize-64;
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)iNodeSize ){
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
}
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else{
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
char *zTmp;
int ii;
for(ii=4; zSql && ii

static int rtreeSqlInit(
Rtree *pRtree,
sqlite3 *db,
const char *zDb,
const char *zPrefix,
int isCreate
){
int rc = SQLITE_OK;
#define N_STATEMENT 9
static const char *azSql[N_STATEMENT] = {
/* xxx_node table 읽기/쓰기 */
"SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
/* xxx_rowid 테이블 읽기/쓰기 */
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
/* xxx_parent 테이블 읽기/쓰기 */
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
};
sqlite3_stmt **appStmt[N_STATEMENT];
int i;
pRtree->db = db;
if( isCreate ){
char *zCreate = sqlite3_mprintf(
"CREATE TABLE \%w\".\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""%w_node\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""(nodeno INTEGER PRIMARY KEY

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""