1. Altibase CLI 소개#
이 장은 Altibase CLI의 배경 및 사용법을 소개하고, 프로그래밍 순서 등에 대해 간략히 설명한다.
개요#
X/Open CLI와 ODBC는 데이터베이스에 접근하기 위한 표준 개방형 응용 프로그램 인터페이스로써, 호출 가능한 SQL 프로그래밍 인터페이스이다. 호출 가능한 SQL 프로그래밍 인터페이스란, CLI 함수를 호출하여 데이터베이스에 액세스하고 SQL문을 실행하는 인터페이스를 의미한다.
X/Open CLI와 ODBC#
X/Open CLI 또는 SAG CLI라 불리는 호출 가능한 SQL 프로그래밍 인터페이스는 X/Open 사 및 SQL Access Group (SAG)에 의해 만들어졌다.
마이크로소프트가 개발한 윈도우용 ODBC 역시 X/Open CLI 스펙을 기반으로 개발되었다.
Altibase CLI란?#
Altibase CLI는 Altibase 환경에서 지원되는 호출 가능한 SQL 프로그래밍 인터페이스이다. Altibase CLI 드라이버는 CLI 애플리케이션을 위해 단독으로 사용될 수도 있고, 아래 라이브러리의 하위 라이브러리로 사용될 수도 있다.
-
libalticapi.a: Altibase C API 라이브러리
-
libapre.a: APRE C/C++ 라이브러리
-
libiloader.a: iLoader API 라이브러리
Altibase CLI 드라이버는 Altibase 서버 및 클라이언트 패키지에 라이브러리 형태로 포함되어 있으며, 아래 애플리케이션을 빌드하거나 실행할 때 필요하다.
-
Altibase CLI 애플리케이션
-
Altibase C API 애플리케이션
-
APRE C/C++ 애플리케이션
-
XA 애플리케이션
-
iLoader API 애플리케이션
Altibase ODBC 드라이버#
ODBC 애플리케이션이 데이터베이스에 접근하기 위해서는 ODBC Driver Manager 같은 ODBC 소프트웨어 외에 접근하려는 데이터베이스에서 제공하는 별도의 모듈이나 드라이버가 필요하다. 이를 위해 Altibase는 ODBC 드라이버를 제공한다. Altibase ODBC 드라이버에 대한 자세한 내용은 ODBC User's Manual을 참조한다.
CLI와 ODBC의 차이점#
Altibase CLI는 X/Open CLI 표준과 ODBC 스펙을 최대한 준수하여 ODBC 인터페이스와 아주 유사하다. 그러나 런타임시 Altibase CLI 애플리케이션은 ODBC Driver Manager를 통하지 않으므로, ODBC 애플리케이션보다 빠른 응답속도를 보장한다.
[그림 1‑1] CLI 드라이버와 ODBC 드라이버의 데이터베이스 접근 개요
본 문서를 읽기 전에#
Altibase CLI는 X/Open CLI 표준뿐만 아니라 ODBC 스펙도 준수한다. 그리고, 위의 [그림 1-1]처럼 Altibase CLI 핵심 모듈이 Altibase ODBC Driver의 하부에서 동작하므로, Altibase CLI 드라이버와 Altibase ODBC 드라이버의 내부 동작은 대부분이 유사하다.
본 문서의 내용은 ODBC 드라이버에도 대부분 적용되고 있으며, Altibase CLI 대신에 ODBC 용어를 사용하거나 함께 언급되었음을 미리 밝혀둔다.
기본 사용법#
본 절에서는 Altibase CLI를 이용한 애플리케이션 작성에 필요한 사전 지식을 살펴본다.
Altibase CLI 애플리케이션 프로그램은 아래 [그림 1-1]과 같이 전형적으로 크게 세 단계로 구성된다.
-
초기설정
-
트랜잭션 처리
-
종료
위의 세 가지 외에도 진단 메세지 처리와 같은 작업 등이 있는데, 이러한 작업은 애플리케이션 전반에 걸쳐 발생한다.
[그림 1‑2] Altibase CLI 애플리케이션 단계
초기설정#
초기화는 환경 및 연결 핸들을 할당하고 초기화한다. 각 단계에서 다음 단계로의 전환은 적절한 핸들을 전달함으로써 이전 단계의 실행 결과에 관한 정보를 전달하는 것으로 이루어진다. Altibase CLI에서 제공하는 핸들의 종류는 다음과 같다.
환경 핸들#
환경 핸들은 애플리케이션 상태에 대한 전체적인 환경을 참조한다. 환경 핸들은 연결 핸들이 할당되기 전에 할당되어야 하며, 하나의 애플리케이션 내에서 여러 개의 환경 핸들을 할당할 수 있다.
연결 핸들#
연결 핸들은 Altibase CLI가 관리하는 연결과 관련된 정보를 참조한다. 이 정보에는 일반적인 상태 정보, 트랜잭션 상태, 진단 정보가 포함된다. 애플리케이션은 각 연결에 대한 연결 핸들을 할당하여 Altibase 서버로의 연결을 시도하게 된다.
명령문 핸들#
명령문 핸들은 Altibase CLI가 관리하는 SQL문에 대한 정보를 참조한다. 명령문 핸들은 연결 핸들과 연관이 있다. 명령문을 실행하기 위해 명령문 핸들을 할당한다. 하나의 연결에 최대 1024개의 명령문을 할당할 수 있다.
트랜잭션 처리#
[그림 1-2]는 일반적인 함수 호출 순서를 보여준다.
[그림 1‑3] 함수 호출 순서
종료#
애플리케이션에서 할당되었던 핸들을 단절하고, 할당되었던 메모리를 반환한 후 애플리케이션을 종료한다.
진단 메세지 처리#
진단이란 애플리케이션 내에서 생성된 경고나 오류 상태를 처리하는 것을 말한다.
애플리케이션의 결과 값#
결과값 | 설명 |
---|---|
SQL_SUCCESS | 함수가 성공적으로 완료 |
SQL_SUCCESS_WITH_INFO | 경고 및 기타 정보와 함께 실행이 성공적으로 완료 |
SQL_NO_DATA | 함수가 성공적이지만 관련 자료가 없다 |
SQL_ERROR | 함수가 실패 |
SQL_INVALID_HANDLE | 입력 핸들이 유효하지않아 함수 실패 |
SQL_SUCCESS, SQL_NO_DATA, SQL_INVALID_HANDLE을 제외하고는 진단 메세지를 생성한다. 진단 메세지를 확인하려면 SQLGetDiagRec() 및 SQLGetDiagField()를 호출하여 확인할 수 있다.
진단 메세지#
진단 메세지는 5자(바이트)로 된 영어/숫자의 스트링이다. 여기에서 상위 2자는 클래스, 하위 3자는 하위 클래스를 나타낸다.
Altibase CLI가 제공하는 진단 메세지는 X/Open SQL CAE가 정의하는 표준을 준수한다.
SIGPIPE 처리시 주의사항#
Altibase 클라이언트 라이브러리는 신호 처리를 하지 않는다.
따라서 외부 원인에 의해 네트워크 접속이 종료된 경우, SIGPIPE 신호를 받아 진행중인 응용 프로그램이 강제로 종료될 수 있다. 이러한 강제 종료를 막기 위해서는 SIGPIPE 신호를 사용자 애플리케이션에서 처리해야 한다. SIGPIPE 신호 처리를 처리하는 함수 내에서 Altibase 클라이언트 라이브러리 함수를 호출하면 프로그램이 멈출 수도 있으므로, 신호 처리 함수 작성에 주의해야 한다. 하지만 신호 처리가 끝난 후에는 Altibase 클라이언트 라이브러리 함수를 호출하는 것이 가능하다.
기본 프로그래밍 순서#
단계 1: Connect to the Database#
어떤 애플리케이션에건 첫 번째 단계는 데이터베이스에 연결하는 것이다. 이 단계에서 필요한 함수는 다음 그림과 같다.
데이터베이스에 연결하는 첫 번째 작업은 SQLAllocHandle()을 이용하여 환경 핸들을 할당하는 것이다.
애플리케이션은 SQLSetEnvAttr()을 호출하여 현재 환경에 대한 환경 속성을 설정한다.
다음으로 애플리케이션은 SQLAllocHandle()로 연결 핸들을 할당하고 SQLDriverConnect()을 호출하여 데이터 소스에 연결한다.
그런 다음 애플리케이션은 SQLSetConnectAttr()을 이용하여 연결 속성값을 설정한다.
단계 2: Initialize the Application#
두 번째 단계는 다음 그림에 설명된 것처럼 애플리케이션을 초기화 하는 것이다. 정확한 작업은 애플리케이션마다 다르다.
애플리케이션은 SQLAllocStmt()로 명령문 핸들을 할당하고, 대부분의 애플리케이션들은 SQLSetStmtAttr()로 커서 종류와 같은 속성을 지정한다.
단계 3: Build and Execute an SQL Statement#
세번째 단계는 다음 그림에 보이는 것처럼 SQL 명령문(statement)을 만들고 실행하는 것이다. 이단계의 처리 형태는 매우 다양하다. 애플리케이션은 사용자가 입력한 SQL 문에 기초하여 SQL 문을 만들거나 실행한다.
SQL 문이 만들어지고 인자들이 바인드되면, 명령문(statement)은 SQLExecDirect로 실행된다. 만약 여러 번 수행되는 구문은 SQLPrepare()로 준비하고, SQLExecute로 반복 실행하는 것이 성능면에서 더 유리하다.
만약 SQL문이 파라미터 마커(?)들을 포함하면, 애플리케이션은 SQLBindParameter()를 호출하여 각 인자들을 애플리케이션 변수에 바인드시킨다. 인자를 바인딩하기 전에 SQLPrepare()를 실행해야 하며, 바인딩 후에 SQLExecute()을 실행할 수 있다.
애플리케이션은 SQL문 실행을 보류하고 카탈로그 정보를 포함한 결과 집합을 리턴하는 함수를 호출할 수도 있다.
애플리케이션의 다음 취할 행동은 SQL문의 실행 형태에 달려있다.
SQL 문의 종류 | 다음 취할 행동 |
---|---|
SELECT 또는 카탈로그 함수 | 단계 4a: 결과를 가져온다. |
UPDATE, DELETE 또는 INSERT | 단계 4b: 행의 개수를 가져온다. |
그 밖의 SQL문 | 단계 3: SQL문을 만들고 실행한다. 또는 단계 5: 트랜잭션을 반영(commit)한다. |
단계 4a: Fetch the Results#
다음 단계는 다음 그림처럼 결과를 fetch하는 것이다.
만약 단계 3에서 실행된 명령문(statement)이 SELECT문이나 카탈로그 함수라면, 애플리케이션은 먼저 결과 집합의 칼럼 수를 알아보기 위해 SQLNumResultCols()를 호출한다. 애플리케이션은 이미 결과 집합 열의 개수를 알고 있다면 이 단계는 필요없다.
그 다음, 애플리케이션은 SQLDescribeCol()로 각 결과 집합열의 이름, 데이터형, 정밀도 등을 가져온다. 마찬가지로 애플리케이션이 이런 정보들을 미리 알고있다면 이단계도 필요없다. 그 후 애플리케이션은 애플리케이션 변수와 결과 집합의 열을 바인드하는 SQLBindCol()에 이런 정보를 보낸다.
이제 애플리케이션은 SQLFetch()를 호출하여 첫번째 행데이터를 가져오고 SQLBindCol()로 바인드 된 변수에 데이터를 저장한다. 행에 긴 데이터가 있으면 SQLGetData()로 데이터를 가져올 수도 있다. 애플리케이션은 추가적으로 데이터를 가져오기위해 SQLFetch()와 (필요하다면) SQLGetData()의 호출을 계속한다.
위의 과정을 거쳐 모든 data를 fetch 해 온 후에는 다른 명령문(statement)을 SQLPrepare() 와 SQLExecute() 를 이용하여 실행하기 전에 반드시 SQLCloseCursor()를 호출하여 데이터를 fetch 하기 위해 열려 있던 커서를 닫아 주어야 한다.
애플리케이션은 같은 트랜잭션 내의 다른 명령문(statement)을 실행하기 위해 단계 3으로 되돌아가거나 트랜잭션을 반영하거나 롤백하기 위해 단계 5로 넘어간다.
단계 4b: Fetch the Row Count#
만일 단계 3에서 수행된 명령문(statement)이 UPDATE, DELETE, INSERT 였다면, 애플리케이션은 SQLRowCount()로 영향을 받은 행들의 개수를 가져온다.
만약 array bind 등을 이용하여 여러 개의 명령문(statement) 를 실행하였다면 각각의 명령문(statement)의 실행으로 영향을 받은 행들을 SQLMoreResults() 함수와 SQLRowCount() 함수의 조합을 이용하여 가져올 수 있다.
애플리케이션은 같은 트랜잭션내의 다른 명령문(statement)을 실행하기위해 단계 3으로 되돌아가거나 트랜잭션을 반영 또는 롤백하기위해 단계 5로 넘어간다.
단계 5: Commit the Transation#
다섯번째 단계는 트랜잭션을 반영하거나 롤백하기 위해 SQLEndTran()을 호출한다. 애플리케이션은 트랜잭션 반영모드가 수동반영(non-auto-commit)으로 설정되어 있을 때만 이 단계를 수행한다. 만일 트랜잭션 반영모드가 자동반영(auto-commit) 이면, 트랜잭션은 명령문(statement)이 실행되었을 때 자동으로 반영된다.
새로운 트랜잭션에서 명령문을 수행하기 위해, 애플리케이션은 단계 3으로 되돌아 간다. 데이터베이스와 단절하기 위해선 단계 6으로 진행한다.
단계 6: Disconnect from the Altibase#
마지막 단계는 다음 그림과 같이, 데이터베이스로부터 단절(disconnect)하는 것이다. 먼저, 애플리케이션은 SQLFreeHandle()을 호출하여 핸들을 반환(free)시킨다.
다음 애플리케이션은 SQLDisconnect()를 이용해 데이터베이스로부터 단절하고, SQLFreeConnect()를 이용해 연결 핸들을 반환시킨다.
마지막으로 애플리케이션은 SQLFreeEnv()을 가지고 환경 핸들을 반환시키고 프로그램을 종료한다.
Altibase CLI 애플리케이션 빌드#
이 절은 Altibase CLI 애플리케이션을 빌드하는 방법을 설명한다.
헤더 파일과 라이브러리#
Altibase CLI를 이용하여 애플리케이션을 작성하고 빌드하기 위해서는 $ALTIBASE_HOME 디렉토리의 서브 디렉토리인 include와 lib에 있는 아래의 헤더 파일과 라이브러리 파일이 필요하다.
$ALTIBASE_HOME/include/sqlcli.h
$ALTIBASE_HOME/lib/libodbccli.a
컴파일#
컴파일시에는 컴파일 명령어에 다음의 옵션을 사용하라.
-I$ALTIBASE_HOME/include
링크시에는 링크 명령어에 다음의 옵션을 사용하라.
-L$ALTIBASE_HOME/lib -lodbccli