CUBRID2008 R3.1에서 LOB타입의 데이터타입이 추가 되면서 glo타입은 제거되었다. CUBRID에서 제공하는 LOB타입은 FBO형태로 DB외에 저장되면 자세한 설명은 아래의 링크를 참조하기 바란다.
기타 API에서의 사용법은 아래와 같다.
JDBC로 BLOB/CLOB 사용하기
JDBC에서 LOB 데이터를 처리하는 인터페이스는 JDBC 4.0 스펙을 기반으로 구현되었으며, 다음과 같은 제약 사항을 가진다..
- BLOB, CLOB 객체를 생성할 때에는 순차 쓰기만을 지원한다. 임의 위치에 대한 쓰기는 지원하지 않는다.
- ResultSet에서 얻어온 BLOB, CLOB 객체의 메소드를 호출하여 BLOB, CLOB 데이터를 변경할 수 없다.
- Blob.truncate, Clob.truncate, Blob.position, Clob.position 메소드는 지원하지 않는다.
- BLOB/CLOB 타입 컬럼에 대해 PreapredStatement.setAsciiStream, PreparedStatement.setBinaryStream,PreparedStatement.setCharacterStream 메소드를 호출하여 LOB 데이터를 바인딩할 수 없다.
- JDBC 4.0을 지원하지 않는 환경(예: JDK 1.5 이하)에서 BLOB/CLOB 타입을 사용하기 위해서는 conn 객체를 CUBRIDConnection로 명시적 타입 변환하여 사용하여야 한다. 아래 예제를 참고한다.
// JDK 1.6 이상
import java.sql.*;
Connection conn = DriverManager.getConnection(url, id, passwd);
Blob blob = conn.createBlob();
…
// JDK 1.6 미만
import java.sql.*;
import cubrid.jdbc.driver.*;
Connection conn = DriverManager.getConnection(url, id, passwd);
Blob blob = ((CUBRIDConnection)conn).createBlob();
…
LOB 타입 데이터를 바인딩하는 방법은 다음과 같다.
- java.sql.Blob 또는 java.sql.Clob 객체를 생성하고 그 객체에 파일 내용을 저장한 다음, PreparedStatement의 setBlob() 혹은 setClob()을 사용한다. (예제 1)
- 질의를 한 다음, 그 ResultSet 객체에서 java.sql.Blob 혹은 java.sql.Clob 객체를 얻고, 그 객체를 PreparedStatement에서 바인딩한다. (예제 2)
예제 1
Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:::", "", "");
PreparedStatement pstmt1 = conn.prepareStatement("INSERT INTO doc(image_id, doc_id, image) VALUES (?,?,?)");
pstmt1.setString(1, "image-21");
pstmt1.setString(2, "doc-21");
//Creating an empty file in the file system
Blob bImage = conn.createBlob();
byte[] bArray = new byte[256];
…
//Inserting data into the external file. Position is start with 1.
bImage.setBytes(1, bArray);
//Appending data into the external file
bImage.setBytes(257, bArray);
…
pstmt1.setBlob(3, bImage);
pstmt1.executeUpdate();
…
예제 2
Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:::", "", "");
conn.setAutoCommit(false);
PreparedStatement pstmt1 = conn.prepareStatement("SELECT image FROM doc WHERE image_id = ? ");
pstmt1.setString(1, "image-21");
ResultSet rs = pstmt1.executeQuery();
while (rs.next())
{
Blob bImage = rs.getBlob(1);
PreparedStatement pstmt2 = conn.prepareStatement("INSERT INTO doc(image_id, doc_id, image) VALUES (?,?,?)");
pstmt2.setString(1, "image-22")
pstmt2.setString(2, "doc-22")
pstmt2.setBlob(3, bImage);
pstmt2.executeUpdate();
pstmt2.close();
}
pstmt1.close();
conn.commit();
conn.setAutoCommit(true);
conn.close();
…
LOB 타입 데이터를 조회하는 방법은 다음과 같다.
- ResultSet에서 getBytes() 혹은 getString() 메소드를 사용하여 데이터를 바로 인출한다. (예제 1)
- ResultSet에서 getBlob() 혹은 getClob() 메소드를 호출하여 java.sql.Blob 혹은 java.sql.Clob 객체를 얻은 다음, 이 객체에 대해getBytes() 혹은 getSubString() 메소드를 사용하여 데이터를 인출한다. (예제 2)
예제 1
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:::", "", "");
// ResetSet에서 직접 데이터 인출
PrepareStatement pstmt1 = conn.prepareStatement("SELECT content FROM doc_t WHERE doc_id = ? ");
pstmt2.setString(1, "doc-10");
ResultSet rs = pstmt1.executeQuery();
while (rs.next())
{
String sContent = rs.getString(1);
System.out.println("doc.content= "+sContent.);
}
예제 2
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:::", "", "");
//ResultSet에서 Blob 객체를 얻고 Blob 객체로부터 데이터 인출
PrepareStatement pstmt2 = conn.prepareStatement(“SELECT image FROM image_t WHERE image_id = ?”);
pstmt2.setString(1,”image-20”);
ResultSet rs = pstmt2.executeQuery();
while (rs.next())
{
Blob bImage = rs.getBlob(1);
Bytes[] bArray = bImange.getBytes(1, (int)bImage.length());
}
PHP로 BLOB/CLOB 사용하기
CUBRID R3.1 PHP Driver에서 LOB지원이 업데이트 되었으며, GLO관련 함수는 새로운 PHP에서 제거 되었다. 아래의 함수들이 LOB데이터 타입을 지원을 위해 추가되었다.
Function |
Description |
cubrid_lob_get |
Retrieve LOB data |
cubrid_lob_close |
Close handle/Free memory |
cubrid_lob_size |
Retrieve LOB data size |
cubrid_lob_export |
Export data from a LOB field |
cubrid_lob_send |
Save LOB data |
삭제된 GLO관련 함수는 아래와 같다.
- cubrid_new_glo
- cubrid_save_to_glo
- cubrid_load_from_glo
- cubrid_send_glo
CCI로 BLOB/CLOB 사용하기
CCI 응용 프로그램에서 다음 함수를 사용하여 LOB 데이터 파일을 생성하고 데이터를 바인딩할 수 있다.
- LOB 데이터 파일 생성하기 (관련 함수: cci_blob_new( ), cci_blob_write( ))
- LOB 데이터를 바인딩하기 (관련 함수: cci_bind_param( ))
- LOB 구조체에 대한 메모리 해제하기 (관련 함수: cci_blob_free( ))
int con = 0; /* connection handle */
int req = 0; /* request handle */
int res;
int n_executed;
int i;
T_CCI_ERROR error;
T_CCI_BLOB blob = NULL;
char data[1024] = “bulabula”;
con = cci_connect ("localhost", 33000, “tdb", "PUBLIC", "");
if (con < 0) {
goto handle_error;
}
req = cci_prepare (con, “insert into doc (doc_id, content) values (?,?)”, 0, &error);
if (req< 0)
{
goto handle_error;
}
res = cci_bind_param (req, 1 /* binding index*/, CCI_A_TYPE_STR, “doc-10”, &ind, CCI_U_TYPE_STRING);
/* Creating an empty LOB data file
res = cci_blob_new (con, &blob, &error);
res = cci_blob_write (con, blob, 0 /* start position */, 1024 /* length */, data, &error);
/* Binding BLOB data */
res = cci_bind_param (req, 2 /* binding index*/, CCI_A_TYPE_BLOB, (void *)blob, CCI_U_TYPE_BLOB, CCI_BIND_PTR);
n_executed = cci_execute (req, 0, 0, &error);
if (n_executed < 0)
{
goto handle_error
}
/* Memory free */
cci_blob_free(blob);
return 0;
handle_error:
if (blob != NULL)
{
cci_blob_free(blob);
}
if (req > 0)
{
cci_close_req_handle (req);
}
if (con > 0)
{
cci_disconnect(con, &error);
}
return -1;
CCI 응용 프로그램에서 다음 함수를 사용하여 LOB 데이터를 조회할 수 있다. LOB 타입 컬럼에 데이터를 입력하면 실제 LOB 데이터는 외부 저장소 내 파일에 저장되고 LOB 타입 컬럼에는 해당 파일을 참조하는 Locator 값이 저장되므로, 파일에 저장된 LOB 데이터를 조회하기 위해서는 cci_get_data( )가 아닌 cci_blob_read( ) 함수를 호출하여야 한다.
- LOB 타입 컬럼 값(Locator) 인출하기 (관련 함수: cci_get_data( ))
- LOB 데이터를 인출하기 (관련 함수: cci_blob_read( ))
- LOB 구조체에 대한 메모리 해제하기 (관련 함수: cci_blob_free( ))
int con = 0; /* connection handle */
int req = 0; /* request handle */
int ind; /* NULL indicator, 0 if not NULL, -1 if NULL*/
int res;
int i;
T_CCI_ERROR error;
T_CCI_BLOB blob;
char buffer[1024];
con = cci_connect ("localhost", 33000, "image_db", "PUBLIC", "");
if (con < 0)
{
goto handle_error;
}
req = cci_prepare (con, "select content from doc_t", 0 /*flag*/, &error);
if (req< 0)
{
goto handle_error;
}
res = cci_execute (req, 0/*flag*/, 0/*max_col_size*/, &error);
res = cci_fetch_size (req, 100 /* fetch size */);
while (1) {
res = cci_cursor (req, 1/* offset */, CCI_CURSOR_CURRENT/* cursor position */, &error);
if (res == CCI_ER_NO_MORE_DATA)
{
break;
}
res = cci_fetch (req, &error);
/* Fetching CLOB Locator */
res = cci_get_data (req, 1 /* colume index */, CCI_A_TYPE_BLOB,
(void *)&blob /* BLOB handle */, &ind /* NULL indicator */);
/* Fetching CLOB data */
res = cci_blob_read (con, blob, 0 /* start position */, 1024 /* length */, buffer, &error);
printf ("content = %sn", buffer);
}
/* Memory free */
cci_blob_free(blob);
res=cci_close_req_handle(req);
res = cci_disconnect (con, &error);
return 0;
handle_error:
if (req > 0)
{
cci_close_req_handle (req);
}
if (con > 0)
{
cci_disconnect(con, &error);
}
return -1;