예제 프로그램은 CUBRID 설치 과정에서 기본적으로 배포되는 demodb DB를 활용하여 CCI를 사용하는 응용 프로그램을 간단하게 작성한 것이다. 예제를 통하여 CAS와 연결하기, 질의 준비, 질의 수행, 응답 처리, 연결 끊기 등의 과정을 따라한다. 예제는 Linux 기반의 동적 링크를 적용하는 방법으로 작성되었다.
다음은 예제에서 사용하는 demodb 데이터베이스의 olympic 클래스(테이블)의 스키마 정보이다.
예제 프로그램을 수행하기 전에 반드시 확인해야 할 사항은 demodb 데이터베이스와 브로커의 가동 여부이다. demodb 데이터베이스와 브로커는 CUBRID 매니저를 통해 시작할 수 있다. 다음은 demodb 데이터베이스가 가동 중인 상황을 CUBRID 매니저에서 확인한 것이다.
다음은 브로커가 가동 중인 상태를 CUBRID 매니저를 통해서 확인한 것이다.
프로그램 소스와 Makefile이 준비된 상태에서 make를 수행하면 test라는 실행 파일이 생성된다. 정적 라이브러리를 사용하면 추가로 파일을 배포할 필요가 없고 속도가 빠르다. 하지만, 프로그램의 크기와 메모리 사용량이 커지는 단점이 있다. 동적 라이브러리를 사용하면 성능상의 오버헤드는 있지만, 메모리와 프로그램 크기에 있어 최적화를 이룰 수 있다.
다음은 Linux에서 make를 사용하지 않고 동적인 라이브러리를 사용하여 테스트 프로그램을 빌드하는 명령 행의 예제이다.
cc -o test test.c -I$CUBRID/include -L$CUBRID/lib -lnsl -lcascci
#include <stdio.h>
#include <cas_cci.h>
char *cci_client_name = "test";
int main (int argc, char *argv[])
{
int con = 0, req = 0, res, ind, i, col_count;
T_CCI_ERROR error;
T_CCI_COL_INFO *res_col_info;
T_CCI_SQLX_CMD cmd_type;
char *buffer, db_ver[16];
printf("Program started!\n");
if ((con=cci_connect("localhost", 30000, "demodb", "PUBLIC", ""))<0) {
printf( "%s(%d): cci_connect fail\n", __FILE__, __LINE__);
return -1;
}
if ((res=cci_get_db_version(con, db_ver, sizeof(db_ver)))<0) {
printf( "%s(%d): cci_get_db_version fail\n", __FILE__, __LINE__);
goto handle_error;
}
printf("DB Version is %s\n",db_ver);
if ((req=cci_prepare(con, "select * from event", 0,&error))<0) {
printf( "%s(%d): cci_prepare fail(%d)\n", __FILE__, __LINE__,error.err_code);
goto handle_error;
}
printf("Prepare ok!(%d)\n",req);
res_col_info = cci_get_result_info(req, &cmd_type, &col_count);
if (!res_col_info) {
printf( "%s(%d): cci_get_result_info fail\n", __FILE__, __LINE__);
goto handle_error;
}
printf("Result column information\n"
"========================================\n");
for (i=1; i<=col_count; i++) {
printf("name:%s type:%d(precision:%d scale:%d)\n",
CCI_GET_RESULT_INFO_NAME(res_col_info, i),
CCI_GET_RESULT_INFO_TYPE(res_col_info, i),
CCI_GET_RESULT_INFO_PRECISION(res_col_info, i),
CCI_GET_RESULT_INFO_SCALE(res_col_info, i));
}
printf("========================================\n");
if ((res=cci_execute(req, 0, 0, &error))<0) {
printf( "%s(%d): cci_execute fail(%d)\n", __FILE__, __LINE__,error.err_code);
goto handle_error;
}
if ((res=cci_fetch_size(req, 100))<0) {
printf( "%s(%d): cci_fetch_size fail\n", __FILE__, __LINE__);
goto handle_error;
}
while (1) {
res = cci_cursor(req, 1, CCI_CURSOR_CURRENT, &error);
if (res == CCI_ER_NO_MORE_DATA) {
printf("Query END!\n");
break;
}
if (res<0) {
printf( "%s(%d): cci_cursor fail(%d)\n", __FILE__, __LINE__,error.err_code);
goto handle_error;
}
if ((res=cci_fetch(req, &error))<0) {
printf( "%s(%d): cci_fetch fail(%d)\n", __FILE__, __LINE__,error.err_code);
goto handle_error;
}
for (i=1; i<=col_count; i++) {
if ((res=cci_get_data(req, i, CCI_A_TYPE_STR, &buffer, &ind))<0) {
printf( "%s(%d): cci_get_data fail\n", __FILE__, __LINE__);
goto handle_error;
}
printf("%s \t|", buffer);
}
printf("\n");
}
if ((res=cci_close_req_handle(req))<0) {
printf( "%s(%d): cci_close_req_handle fail", __FILE__, __LINE__);
goto handle_error;
}
if ((res=cci_disconnect(con, &error))<0) {
printf( "%s(%d): cci_disconnect fail(%d)", __FILE__, __LINE__,error.err_code);
goto handle_error;
}
printf("Program ended!\n");
return 0;
handle_error:
if (req > 0)
cci_close_req_handle(req);
if (con > 0)
cci_disconnect(con, &error);
printf("Program failed!\n");
return -1;
}