Swarmvtab 가상 테이블
Swarmvtab 가상 테이블 (Swarmvtab Virtual Table)
swarmvtab 가상 테이블은 유사한 스키마를 가졌지만 rowid 값 범위가 서로 다른 다수의 테이블(이하 "컴포넌트" 테이블)을 하나의 데이터베이스 테이블처럼 질의할 수 있게 해줘요. 테이블들은 서로 다른 데이터베이스에 위치할 수 있고(보통 그렇고), 읽기 전용이에요. 이 문서는 swarmvtab의 개요, 컴파일 방법, 그리고 고급 사용법을 다뤄요.
출처: 문서
본문
1. 개요
"swarmvtab" 가상 테이블은 유사한 스키마를 가졌지만 rowid 값 범위가 서로 다른 수많은 테이블(이하 "컴포넌트" 테이블)을 마치 하나의 데이터베이스 테이블인 것처럼 질의할 수 있게 해줘요. 테이블들은 (그리고 보통은) 서로 다른 데이터베이스에 위치할 수 있어요. Swarmvtab 테이블은 읽기 전용이에요.
컴포넌트 테이블은 WITHOUT ROWID로 선언하면 안 되고, 모두 동일한 스키마를 가져야 하며, 데이터베이스 내에서 서로 다른 이름을 가질 수 있어요. 이 문맥에서 "동일한 스키마"란 다음을 의미해요:
-
모든 컴포넌트 테이블은 동일한 컬럼 집합을 동일한 순서로 가져야 해요.
-
각 컬럼에 붙은 타입과 기본 collation 순서가 모든 컴포넌트 테이블에서 동일해야 해요.
-
모든 컴포넌트 테이블은 동일한 PRIMARY KEY 선언을 가져야 해요(있다면).
swarmvtab 테이블은 각 컴포넌트 테이블과 동일한 스키마를 가져요.
swarmvtab 가상 테이블은 다음과 같이 생성돼요:
CREATE VIRTUAL TABLE temp.<name> USING swarmvtab(<sql-statement>);
Swarmvtab 가상 테이블은 temp 스키마에 만들어져야 해요. main 또는 ATTACH된 데이터베이스에 swarmvtab을 만들려 하면 오류예요.
CREATE VIRTUAL TABLE 문의 인자로 제공된 SQL 문은 테이블이 생성될 때 실행돼요. 이 문은 4개 또는 5개의 컬럼을 반환해야 해요. 반환된 각 행은 컴포넌트 테이블 중 하나를 설명해요. 처음 네 개의 컬럼은 첫 번째부터 순서대로 다음과 같이 해석돼요:
-
데이터베이스 URI. 컴포넌트 테이블을 포함하는 데이터베이스를 여는 데 사용할 수 있는 파일 이름 또는 URI.
-
테이블 이름. 데이터베이스 내 컴포넌트 테이블의 이름.
-
최소 rowid. 컴포넌트 테이블이 포함할 수 있는 가장 작은 rowid 값.
-
최대 rowid. 컴포넌트 테이블이 포함할 수 있는 가장 큰 rowid 값.
마지막 컬럼이 있다면 그 해석은 여기에 설명돼 있어요.
예를 들어, SQL 문이 실행될 때 다음 데이터를 반환한다고 해봐요:
| Database URI | Table name | Minimum rowid | Maximum rowid |
|---|---|---|---|
| test.db1 | t1 | 0 | 10 |
| test.db2 | t2 | 11 | 20 |
| test.db3 | t1 | 21 | 30 |
| test.db4 | t1 | 31 | 40 |
사용자가 rowid 값 25인 행을 swarmvtab 테이블에서 질의한다면, swarmvtab 테이블은 데이터베이스 파일 "test.db3"을 열고 "t1" 테이블에서 반환할 데이터를 읽어요 (25가 "test.db3"의 "t1" 테이블에 할당된 rowid 범위 안에 있기 때문이에요).
Swarmvtab은 rowid(또는 다른 INTEGER PRIMARY KEY) 필드에 대한 범위 및 동등 제약만 효율적으로 처리해요. 쿼리에 그러한 제약이 없으면, swarmvtab은 각 데이터베이스를 차례로 열고 컴포넌트 테이블을 선형으로 스캔해 결과를 찾아요. 이는 올바른 결과를 만들지만 흔히 느려요.
SQL 문이 반환한 행에서 rowid 범위가 겹치면 안 돼요. 겹치면 오류예요.
swarmvtab 구현은 언제든 데이터베이스를 열거나 닫을 수 있어요. 기본적으로 동시에 열려 있는 데이터베이스 파일의 최대 수를 9개로 제한하려 해요. 이는 하드 한도가 아니에요 — swarmvtab이 그 한도를 초과하게 만드는 시나리오를 구성하는 것이 가능해요.
2. Swarmvtab 컴파일 및 사용
swarmvtab 가상 테이블의 코드는 기본 SQLite 소스 트리의 ext/misc/unionvtab.c 파일에 있어요. 다음과 같은 명령으로 SQLite 로드 가능 확장으로 컴파일할 수 있어요:
gcc -g -fPIC -shared unionvtab.c -o unionvtab.so
대안으로 unionvtab.c 파일을 애플리케이션에 컴파일할 수도 있어요. 이 경우 각 새 데이터베이스 연결에 확장을 등록하기 위해 다음 함수를 호출해야 해요:
int sqlite3_unionvtab_init(sqlite3 *db, void*, void*);
첫 번째 인자는 확장을 등록할 데이터베이스 핸들이에요. 두 번째와 세 번째 인자는 모두 0을 전달해야 해요.
소스 파일과 진입점(entry point)은 "swarmvtab"이 아니라 "unionvtab"이라는 이름을 가져요. Unionvtab은 swarmvtab과 함께 번들로 제공되는 별도로 문서화된 가상 테이블이에요.
3. 고급 사용법
대부분의 swarmvtab 사용자는 위에서 설명한 기능만 사용할 거예요. 이 절은 더 난해한 사용 사례를 위해 설계된 기능을 설명해요. 이 기능들은 모두 CREATE VIRTUAL TABLE 명령의 일부로 SQL 문 뒤에 추가 선택적 매개변수를 지정하는 것과 관련돼요. 선택적 매개변수는 이름 뒤에 "=" 문자, 그리고 선택적으로 따옴표로 묶인 값을 붙여서 지정해요. 공백이 이름, "=" 문자, 값 사이를 구분할 수 있어요. 예를 들어:
CREATE VIRTUAL TABLE temp.sv USING swarmvtab (
'SELECT ...', -- the SELECT statement
maxopen = 20, -- An optional parameter
missing='missing_udf' -- Another optional parameter
);
다음 절들은 지원되는 매개변수를 설명해요. 인식되지 않는 매개변수 이름을 지정하면 오류예요.
3.1. SQL 매개변수
매개변수 이름이 ":"으로 시작하면, 실행 전에 SQL 문에 바인딩할 값으로 간주돼요. 값은 항상 텍스트로 바인딩돼요. 지정된 SQL 매개변수가 존재하지 않으면 오류예요. 예를 들어:
CREATE VIRTUAL TABLE temp.x1 USING swarmvtab (
"SELECT :dir || local_filename, tbl, min, max FROM components",
:dir = '/home/user/app/databases/'
);
위 CREATE VIRTUAL TABLE 문이 실행되면, swarmvtab은 텍스트 값 "/home/user/app/databases/"를 실행 전에 SQL 문의 :dir 매개변수에 바인딩해요.
단일 CREATE VIRTUAL TABLE 문은 원하는 만큼 많은 SQL 매개변수를 포함할 수 있어요.
3.2. "maxopen" 매개변수
기본적으로 swarmvtab은 동시에 열린 데이터베이스의 수를 9개로 제한하려 해요. 이 매개변수로 그 한도를 변경할 수 있어요. 예를 들어 최대 30개의 데이터베이스를 동시에 열 수 있는 swarmvtab 테이블을 만들려면:
CREATE VIRTUAL TABLE temp.x1 USING swarmvtab (
"SELECT ...",
maxopen=30
);
열린 데이터베이스 수를 늘리면 일부 시나리오에서 성능이 향상될 수 있어요.
3.3. "openclose" 콜백
"openclose" 매개변수는 사용자가 애플리케이션 정의 SQL 함수의 이름을 지정할 수 있게 해요. 이 함수는 swarmvtab이 데이터베이스를 열기 직전과 닫은 직후에 호출돼요. open close 함수에 전달되는 첫 번째 인자는 열리거나 막 닫힌 데이터베이스를 식별하는 파일 이름 또는 URI예요 (CREATE VIRTUAL TABLE 명령에 제공된 SQL 문의 가장 왼쪽 컬럼에 반환된 것과 같은 값). 두 번째 인자는 데이터베이스를 열기 전에 함수가 호출되면 정수 0, 닫힌 후에 호출되면 1이에요. 예를 들어:
CREATE VIRTUAL TABLE temp.x1 USING swarmvtab (
"SELECT ...",
openclose = 'openclose_udf'
);
그러면 컴포넌트 테이블을 포함하는 각 데이터베이스를 열기 전에 swarmvtab은 사실상 다음을 실행해요:
SELECT openclose_udf(<database-name>, 0);
데이터베이스가 닫힌 후에는 swarmvtab이 다음에 해당하는 것을 실행해요:
SELECT openclose_udf(<database-name>, 1);
openclose 함수가 반환하는 값은 무시돼요. 데이터베이스를 열기 전에 실행된 호출이 오류를 반환하면, 데이터베이스 파일이 열리지 않고 오류가 사용자에게 반환돼요. 이것이 swarmvtab이 나중에 대응하는 "close" 호출 없이 "open" 호출을 발행하는 유일한 시나리오예요. 아직 데이터베이스가 열려 있다면, swarmvtab 테이블이 있는 temp 스키마를 삭제하는 애플리케이션의 데이터베이스에 대한 최종 sqlite3_close() 호출 안에서 "close" 호출이 발행될 수 있어요.
"close" 호출이 반환한 오류는 항상 무시돼요.
3.4. "missing" 콜백
"missing" 매개변수는 사용자가 애플리케이션 정의 SQL 함수의 이름을 지정할 수 있게 해요. swarmvtab이 데이터베이스를 열기 전에 필요한 데이터베이스 파일이 디스크에 없다는 것을 발견하면 이 함수가 호출돼요. 이는 swarmvtab이 열기를 시도하기 전에 애플리케이션이 원격 소스에서 필요한 데이터베이스를 가져올 기회를 제공해요. "missing" 함수에 전달되는 유일한 인자는 열리고 있는 데이터베이스를 식별하는 이름 또는 URI예요. 다음처럼 가정해요:
CREATE VIRTUAL TABLE temp.x1 USING swarmvtab (
"SELECT ...",
openclose = 'openclose_udf',
missing='missing_udf'
);
그러면 missing 함수는 다음과 같이 호출돼요:
SELECT missing_udf(<database-name>);
missing 함수가 오류를 반환하면 데이터베이스가 열리지 않고 오류가 사용자에게 반환돼요. openclose 함수가 구성되어 있으면, 이 시점에서 이전 "open"에 대응하는 "close" 호출이 발행돼요. 다음 의사 코드는 컴포넌트 데이터베이스가 열릴 때 missing과 openclose 함수가 모두 구성된 swarmvtab 인스턴스가 사용하는 절차를 보여줘요.
SELECT openclose_udf(<database-name>, 0);
if( error ) return error;
if( db does not exist ){
SELECT missing_udf(<database-name>);
if( error ){
SELECT openclose_udf(<database-name>, 1);
return error;
}
}
sqlite3_open_v2(<database-name>);
if( error ){
SELECT openclose_udf(<database-name>, 1);
return error;
}
// db successfully opened!
3.5. 컴포넌트 테이블 "context" 값
CREATE VIRTUAL TABLE 명령의 일부로 지정된 SELECT 문이 다섯 개의 컬럼을 반환하면, 마지막 컬럼은 애플리케이션 컨텍스트 전용으로 사용돼요. Swarmvtab은 이 값을 전혀 사용하지 않아요. 단, 지정된 경우
SELECT missing_udf(<database-name>, <context>);
SELECT openclose_udf(<database-name>, <context>, 0);
SELECT openclose_udf(<database-name>, <context>, 1);
필요에 따라 말이죠.
더 알아보기 (Learn more)
- The UNION Virtual Table — 함께 번들되는 unionvtab 가상 테이블
- Virtual Tables — 가상 테이블 일반 문서
- CREATE VIRTUAL TABLE — 가상 테이블 생성 구문
- Rowid Tables — rowid 테이블 개념