Posting

Machbase의 최신 소식을 지금 만나보세요

C언어로 Binary data를 Machbase에 넣기

1.개요

Data를 다루다 보면 numeric, varchar 형 데이터뿐만 아니라 JPG, PNG, MP3와 같은 Binary data도 database에 저장해야 할 때가 존재한다.

그러나 일반 data들과는 달리 Binary data는 파일 형식으로 저장되어 있기 때문에 사용자가 작성하여 넣을 수가 없다.

이 글에서는 Machbase cli에서 지원하는 형식 및 코드를 이용하여 Binary 파일을 machbase에 저장하는 과정을 다룬다.

2.준비

소스 및 바이너리 파일 : https://github.com/MACHBASE/binary_sample

마크베이스 최신버전: https://kr.machbase.com/home/download/

3.코드진행

이 글에서는 여러분들이 ‘DB connection, SQLExecute, 등 기본적인 ODBC 표준 함수를 사용할 수 있다’ 라는 전제하에 진행된다.

따라서 Binary 데이터 입력과 조회를 중점으로 설명을 한다

int main()
{
…. 코드
appendData(sStmt);
….
}

위의 코드는 github에서 다운 받을 수 있는 sample_binary.c의 main 함수의 일부분이다.

데이터를 입력하는 부분은 appendData라는 함수로 진행한다.

다음은 appendData 함수이다.

int appendData(SQLHSTMT aStmt)
{
SQL_APPEND_PARAM sParam[2];
SQLRETURN sRC;

char sVarchar[128] = {0,};
struct stat sStatBuf;
FILE *sFp = NULL;
int sFileSize = 0;
char sFileName[40] = “binary.png”;
char *sBinaryData = NULL;

sFp = fopen(sFileName, “rb”);
if( sFp == NULL )
{
printf(“File Open Error : %s\n”, sFileName );
return RC_FAILURE;
}
stat(sFileName, &sStatBuf);
sFileSize = sStatBuf.st_size;
sBinaryData = (char *)malloc( sizeof(char) * sFileSize);
fread(sBinaryData, sStatBuf.st_size, 1, sFp);
fclose(sFp);

}

차례대로 코드를 확인해보자. 가장 처음 fopen(sFileName, “rb”) 를 통해서 sFileName 파일을 “rb” 형식으로 읽는다는 것인데

이 rb는 read binary 이다. 이후 fclose까지의 과정은 file의 정보를 sBinaryData 변수에 담아두는 과정이다.

Binary File에 대한 정보를 sBinaryData 변수에 담았다면 이제 데이터를 마크베이스의 형식에 맞게 담고 보내는 과정을 수행해야 한다.

아래의 코드를 보자.

int appendData(SQLHSTMT aStmt)
{
    …
memset(sParam, 0, sizeof(sParam));
    strcpy(sVarchar, “binary.png”);
    sParam[0].mVar.mLength = strlen(sVarchar);
    sParam[0].mVar.mData = sVarchar;
    sParam[1].mBlob.mLength = sFileSize;
    sParam[1].mBlob.mData = sBinaryData;

    sRC = SQLAppendDataV2(aStmt, sParam);
    CHECK_APPEND_RESULT(sRC, gEnv, gCon, aStmt);
    if( sBinaryData )
    {
        free(sBinaryData);
        sBinaryData = NULL;
    }
    return RC_SUCCESS;
}

같은 코드 내에서 정의된 createTable() 함수에서 2개의 Column(각각 varchar, binary 형식)을 가진 Table을 생성했다.

따라서 데이터도 varchar, binary를 저장할 수 있는 크기가 2인 sParam 배열을 셋팅해준다.

데이터 입력순서는 반드시 Column의 순서에 맞게 입력해야한다.

마크베이스는 Blob(바이너리 라지 오브젝트)형식의 멤버변수를 지원한다. Binary 파일을 입력하려면  mBlob.mData에 Binary data를 입력해줘야 한다.

sParam에 입력이 전부 끝나면 SQLAppendDataV2 함수를 호출하여 stmt와 데이터가 들어 있는 sParam 변수를 매개변수로 넘겨주면 된다.

입력이 끝나면 메모리를 할당한(malloc 함수로) sBinaryData 변수는 free를 하고 SUCCESS값을 return하고 종료한다

이후 해당 코드를 실행하여 실제 데이터가 어떻게 들어갔는지 확인해보자.

FILENAME에는 변수 sFileName 값이 들어갔으며 RAWDATA에는 의미를 알수 없는 숫자와 글자가 조합된 텍스트가 들어갔다. 그럼 이 데이터를 어떻게 다시 Binary화 시킬 수 있을까? 아래의 selectData() 함수 코드를 보자.

int selectData()
{
    ….
    if( SQLExecute(sStmt) != SQL_SUCCESS )
    {
        printError(gEnv, gCon, sStmt, “SQLExecute Error”);
        goto error;
    }
    sRC = SQLBindCol(sStmt, 1, SQL_C_CHAR, sFileName, sizeof(sFileName), &sFileNameLen);
    CHECK_STMT_RESULT(sRC, sStmt, “SQLBindCol 1 Error”);
    sRC = SQLBindCol(sStmt, 2, SQL_C_BINARY, sBinaryData, sBinaryLimitLength, &sBinaryLen);
    CHECK_STMT_RESULT(sRC, sStmt, “SQLBindCol 2 Error”);
    while( SQLFetch(sStmt) == SQL_SUCCESS )
    {
        printf(“DB filename : %s, filesize : %ld\n”, sFileName, sBinaryLen);
        sprintf(sNewFile, “%s2”, sFileName);
        sFp = fopen(sNewFile, “wb”);
        if( sFp != NULL )
        {
            fwrite(sBinaryData, 1, sBinaryLen, sFp);
            fclose(sFp);
        }
        printf(“new filename : %s\n”, sNewFile);
    }

SQLexecute에서 실행되는 Query 다음과 같다

SELECT * FROM BINARY_SAMPLE;

해당 Query가 실행된다면 Binary_sample에 들어있는 데이터들을 모두 가져올 준비를 끝맞쳤을 것이다.

그 밑의 코드는 자세히 보자

우선 SQLBindCol 함수이다.

SQLRETURN SQLBindCol( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN * StrLen_or_IndPtr);

SQLBindCol(sStmt, 1, SQL_C_CHAR, sFileName, sizeof(sFileName), &sFileNameLen);

SQLBindCol(sStmt, 2, SQL_C_BINARY, sBinaryData, sBinaryLimitLength, &sBinaryLen);

SQLBindCol 함수는 Table에서 Select한 Column의 data를 어떤 변수에다 입력할지 binding 하는 함수이다.

입력한 코드 첫 번째 Bind는 sFileName의 변수에 1번째 Column의 data를 CHAR 형식의 데이터로 Binding 하는 것이고

입력한 코드 두 번째 Bind는 sBinaryData의 변수에 2번째 Column의 data를 Binary 형식의 데이터로 Binding 한다는 것이다.

Bind가 끝나면 이제 SQLFetch 함수를 통해 실제 데이터들을 변수에 담는 작업을 한다. 이 함수는 SQLExecute에서 나온 결과 값에 대해 결과를 반환하는데 1회 호출 시 1행을 반환 하고 다음 행으로 포인터를 옮긴다.

SQLFetch를 호출했기 때문에 sBinaryData 변수에 데이터가 SQL_C_BINARY 형식으로 저장되며 파일 함수들을 통해 파일화 되어 저장된다.

file 이름은 extract_file.png로 기존의 파일과 겹치지 않도록 저장한다.

파일명을 보면 알겠지만 해당 파일은 MACHBASE로고가 들어간 image 파일로 정상적이라면 아래의 화면을 확인 할수 있어야 한다.

4. 마치며

이걸로 Machbase에 Binary 파일을 저장하는 방법에 대해서 알아보았다. DB에 Binary파일을 저장하는 경우는 흔하지 않다. 해당 파일의 위치를 저장하여 빠르게 불러오는 방법으로 채택하고 있으나 부득이하게 Binary 파일을 저장해야 한다면 이 글이 많은 도움이 됬을거라 생각한다.

연관 포스트

[MACHBASE 연동] Android studio에서 JDBC 연결하기

마크베이스 기술지원본부 이현민 1. 개요 수많은 데이터들이 많은 환경에서 생성되고 있는 오늘날, 우리 현대인들의 동반자인 스마트폰 또한 데이터생성의 주체로써 또는 전달자로서 알게 모르게 그 구실을

[MACHBASE 기초] Machbase에서 Sequence 컬럼 사용하기

개요 이번 포스트에서는 Machbase 6.5에 새로 추가될 예정인 Sequence(시퀀스) 기능에 대해서 알아보고자 한다. 시퀀스는 순차적으로 자동으로 증가하는 컬럼을 만들기 위해 사용된다.순자적으로 증가하여 중복된 값이 없으므로