Carray() 테이블-값 함수

Carray() 테이블-값 함수

Carray()는 단일 컬럼(value)을 가진 테이블-값 함수랍니다. SQL 쿼리에 C언어 배열을 바인딩할 수 있는 편리한 메커니즘을 제공해요. C언어 배열을 SQL 쿼리에 직접 연결해서 쓰고 싶을 때 아주 유용하죠.

출처: 문서

본문

Carray()는 이름이 value인 컬럼 하나와 0개 이상의 행을 가진 테이블-값 함수예요. carray()의 각 행에 들어가는 value는 애플리케이션이 파라미터 바인딩을 통해 제공하는 C언어 배열에서 가져옵니다. 이렇게 해서 C언어 배열을 SQL 쿼리에 편리하게 바인딩할 수 있어요.

2. 사용 가능 여부

SQLite 3.51.0 (2025-11-04) 버전부터 carray() 확장은 amalgamation에 내장되어 있어요. 다만 기본적으로 비활성화되어 있고, -DSQLITE_ENABLE_CARRAY로 컴파일하지 않으면 동작하지 않아요. 3.51.0 이전에는 carray()가 별도 소스 파일에 있어서 독립적으로 컴파일한 뒤 로더블 확장으로 SQLite에 추가해야 했어요.

carray() 함수는 SQLite 3.14 (2016-08-08) 버전에서 처음 추가되었고, sqlite3_carray_bind() 인터페이스와 carray()의 단일-인자 변형은 3.34.0 (2020-12-01) 버전에 추가되었어요. BLOB로 해석되는 struct iovec 객체 배열을 바인딩하는 기능은 3.41.0 (2023-02-21) 버전에 추가되었죠.

3. 상세 사항

carray() 함수는 인자를 1개, 2개, 또는 3개 받아요. 1-인자 변형을 사용하는 걸 권장해요.

3.1. 단일-인자 CARRAY

carray()의 단일-인자 형태는 값을 붙이기 위해 sqlite3_carray_bind()라는 특별한 C언어 인터페이스가 필요해요:


  int sqlite3_carray_bind(
    sqlite3_stmt *pStmt,         /* Statement containing the CARRAY */
    int idx,                     /* Parameter number for CARRAY argument */
    void *aData,                 /* Data array */
    int nData,                   /* Number of entries in the array */
    int mFlags,                  /* Datatype flag */
    void (*xDestroy)(void*)      /* Destructor for aData */
  );

sqlite3_carray_bind()의 mFlags 파라미터는 다음 중 하나여야 해요:


  #define SQLITE_CARRAY_INT32   0
  #define SQLITE_CARRAY_INT64   1
  #define SQLITE_CARRAY_DOUBLE  2
  #define SQLITE_CARRAY_TEXT    3
  #define SQLITE_CARRAY_BLOB    4

SQLITE_CARRAY_INT32 형은 배열이 int 배열임을 의미해요. SQLITE_CARRAY_INT64sqlite3_int64 배열, SQLITE_CARRAY_DOUBLEdouble 배열을 뜻하죠. SQLITE_CARRAY_TEXT는 각 요소가 NULL 포인터 또는 0으로 끝나는 문자열 포인터인 char* 배열을 의미해요.

SQLITE_CARRAY_BLOB 인자는 배열이 struct iovec 객체 배열임을 뜻해요. struct iovec 형은 표준 Posix 데이터 구조로, 보통 #include <sys/uio.h>로 선언해요. 형식은 다음과 같아요:


struct iovec {
  void  *iov_base; /* Starting address */
  size_t iov_len;  /* Number of bytes to transfer */
};

mFlags 파라미터의 하위 비트들은 지금은 모두 0이어야 하지만, 향후 개선에서 사용될 수 있어요.

sqlite3_carray_bind() 루틴의 xDestroy 인자는 입력 배열을 해제하는 함수 포인터예요. SQLite는 데이터 사용이 끝난 뒤 이 함수를 호출해요. xDestroy 인자는 "sqlite3.h"에 정의된 다음 상수 중 하나일 수도 있어요:

  • SQLITE_STATIC → sqlite3_carray_bind()를 호출한 애플리케이션이 데이터 배열의 소유권을 갖는다는 뜻이에요. 애플리케이션은 prepared statement가 finalize될 때까지 데이터를 변경하거나 해제하지 않겠다고 SQLite에 약속해요.

  • SQLITE_TRANSIENT → 이 특수 값은 sqlite3_carray_bind() 인터페이스가 반환되기 전에 데이터의 개인 복사본을 만들라고 SQLite에 지시해요.

3.2. 다중-인자 CARRAY

원래 carray() 설계는 인자를 2개 또는 3개 받았어요. 이 방법은 하위 호환성을 위해 여전히 지원되지만, 새 애플리케이션은 위에서 설명한 단일-인자 carray() 설계를 사용하는 걸 권장해요.

2-인자 및 3-인자 버전의 carray()에서 첫 번째 인자는 배열에 대한 포인터예요. 포인터 값은 SQL에서 직접 지정할 수 없으므로, 첫 번째 인자는 sqlite3_bind_pointer() 인터페이스를 사용해 "carray" 포인터-형식으로 바인딩된 파라미터여야 해요. 두 번째 인자는 배열의 요소 수예요. 선택적인 세 번째 인자는 C언어 배열 요소의 데이터타입을 정하는 문자열이에요. 세 번째 인자에 허용되는 값은 다음과 같아요:

  • 'int32'
  • 'int64'
  • 'double'
  • 'char*'
  • 'struct iovec'

기본 데이터타입은 'int32'예요. carray() 함수에 인자가 두 개뿐이면 'int32' 데이터타입으로 간주해요.

4. 사용법

carray() 함수는 쿼리의 FROM 절에서 사용할 수 있어요. 예를 들어, 주소 $PTR의 C언어 배열에서 가져온 rowid로 OBJ 테이블의 두 엔트리를 조회하려면 이렇게 해요:

SELECT obj.* FROM obj, carray($PTR) AS x
 WHERE obj.rowid=x.value;

이 쿼리도 같은 결과를 줘요:

SELECT * FROM obj WHERE rowid IN carray($PTR);

더 알아보기 (Learn more)