Виртуальная таблица Swarmvtab
Содержание
1.Обзор
Виртуальная таблица "swarmvtab" позволяет пользователю выполнять запросы к большому количеству таблиц (в дальнейшем "таблицы компонентов") с похожими схемами, но различными диапазонами значений rowid, как если бы они были одной таблицей базы данных. Таблицы могут (и обычно находятся) в разных базах данных. Таблицы Swarmvtab являются только для чтения.
Таблицы компонентов не должны объявляться БЕЗ ROWID и должны иметь одинаковую схему, но могут иметь разные имена внутри своих баз данных. В этом контексте "одинаковая схема" означает, что:
- Все таблицы компонентов должны иметь одинаковый набор столбцов в том же порядке.
- Типы и стандартные последовательности сортировки, прикрепленные к каждому столбцу, должны быть одинаковыми для всех таблиц компонентов.
- Все таблицы компонентов должны иметь одинаковое объявление PRIMARY KEY (если таковое имеется).
Таблица swarmvtab имеет такую же схему, как и каждая из её таблиц компонентов.
Виртуальная таблица swarmvtab создается следующим образом:
CREATE VIRTUAL TABLE temp.<name> USING swarmvtab(<sql-statement>);
Виртуальные таблицы Swarmvtab должны создаваться в схеме temp. Попытка создания swarmvtab в основной или подключённой базе данных является ошибкой.
SQL-запрос, переданный в качестве аргумента оператору CREATE VIRTUAL TABLE, выполняется при создании таблицы. Он должен возвращать четыре или пять столбцов. Каждая строка, возвращённая запросом, описывает одну из таблиц компонентов. Первые четыре столбца интерпретируются от первого к последнему как:
- URI базы данных. Имя файла или URI, который можно использовать для открытия базы данных, содержащей таблицу компонентов.
- Имя таблицы. Имя таблицы компонентов внутри её базы данных.
- Минимальный rowid. Наименьшее значение rowid, которое может содержать таблица компонентов.
- Максимальный rowid. Наибольшее значение rowid, которое может содержать таблица компонентов.
Интерпретация последнего столбца, если он присутствует, описана здесь.
Например, предположим, что SQL-запрос возвращает следующие данные при выполнении:
| URI базы данных | Имя таблицы | Минимальный rowid | Максимальный rowid |
|---|---|---|---|
| test.db1 | t1 | 0 | 10 |
| test.db2 | t2 | 11 | 20 |
| test.db3 | t1 | 21 | 30 |
| test.db4 | t1 | 31 | 40 |
и пользователь запрашивает таблицу swarmvtab для строки со значением rowid 25. Таблица swarmvtab откроет файл базы данных "test.db3" и прочитает данные для возвращения из таблицы "t1" (поскольку 25 находится в диапазоне rowid, назначенных таблице "t1" в "test.db3").
Swarmvtab эффективно обрабатывает ограничения диапазона и равенства на поле rowid (или другом поле INTEGER PRIMARY KEY) только. Если запрос не содержит такого ограничения, то swarmvtab находит результаты, открывая каждую базу данных по очереди и линейно сканируя таблицу компонентов. Это генерирует правильный результат, но часто медленно.
Диапазоны rowid в строках, возвращаемых SQL-запросом, не должны перекрываться. Если перекрытие существует, это ошибка.
Реализация swarmvtab может открывать или закрывать базы данных в любой момент. По умолчанию она пытается ограничить максимальное количество одновременно открытых файлов базы данных девятью. Это не жёсткий лимит — возможно, построить сценарий, который заставит swarmvtab превысить его.
2.Компиляция и использование Swarmvtab
Код виртуальной таблицы swarmvtab находится в файле ext/misc/unionvtab.c основного исходного кода SQLite. Его можно скомпилировать в загружаемый модуль SQLite с помощью команды, подобной:
gcc -g -fPIC -shared unionvtab.c -o unionvtab.so
В качестве альтернативы, файл unionvtab.c можно скомпилировать в приложение. В этом случае для регистрации расширения с каждой новой базой данных следует вызвать следующую функцию:
int sqlite3_unionvtab_init(sqlite3 *db, void*, void*);
В качестве первого аргумента следует передать дескриптор базы данных, с которым необходимо зарегистрировать расширение. Второй и третий аргументы должны быть равны 0.
Файл исходного кода и точка входа называются "unionvtab", а не "swarmvtab". Unionvtab — отдельно документированная виртуальная таблица, которая поставляется вместе с swarmvtab.
3.Расширенное использование
Большинство пользователей swarmvtab будут использовать только описанные выше функции. Этот раздел описывает функции, предназначенные для более экзотических случаев использования. Все эти функции предполагают указание дополнительных необязательных параметров после SQL-запроса в качестве части команды CREATE VIRTUAL TABLE. Необязательный параметр задаётся с помощью его имени, за которым следует знак равенства (=), за которым следует, необязательно, заключённое в кавычки значение. Пробелы могут отделять имя, знак равенства и значение. Например:
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/" к параметру :dir SQL-запроса перед его выполнением.
Один оператор CREATE VIRTUAL TABLE может содержать любое количество SQL-параметров.
3.2.Параметр "maxopen"
По умолчанию swarmvtab пытается ограничить количество одновременно открытых баз данных девятью. Этот параметр позволяет изменить это ограничение. Например, чтобы создать таблицу swarmvtab, которая может содержать до 30 одновременно открытых баз данных:
CREATE VIRTUAL TABLE temp.x1 USING swarmvtab ( "SELECT ...", maxopen=30 );
Увеличение числа открытых баз данных может улучшить производительность в некоторых сценариях.
3.3.Обратный вызов "openclose"
Параметр "openclose" позволяет пользователю указать имя определяемой приложением SQL-функции, которая будет вызываться непосредственно перед тем, как swarmvtab откроет базу данных, и снова сразу после закрытия. Первый аргумент, переданный функции openclose, — это имя файла или URI, идентифицирующий базу данных, которая должна быть открыта или только что закрыта (то же значение, возвращаемое в левом столбце SQL-запроса, переданного команде CREATE VIRTUAL TABLE). Второй аргумент — целое значение 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 будет делать вызов "open" без последующего вызова "close". Если базы данных всё ещё открыты, вызовы "close" могут выполняться из вызова sqlite3_close() в приложении базы данных, который удаляет схему temp, в которой находится таблица swarmvtab.
Ошибки, возвращаемые вызовами "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 настроена, то в этот момент будет выполнен вызов "close" для соответствия ранее выполненному "open". Следующий псевдокод иллюстрирует процедуру, используемую экземпляром swarmvtab с настроенными функциями missing и openclose при открытии базы данных компонента.
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" таблицы компонентов
Если SELECT-запрос, указанный в качестве части команды CREATE VIRTUAL TABLE, возвращает пять столбцов, то последний столбец используется только для контекста приложения. Swarmvtab вообще не использует это значение, за исключением того, что оно передаётся после <имя-базы-данных> как обоим функциям openclose, так и missing, если они указаны. Другими словами, вместо вызова функций, как описано выше, если столбец "context" присутствует, swarmvtab вместо этого вызывает:
SELECT missing_udf(<database-name>, <context>); SELECT openclose_udf(<database-name>, <context>, 0); SELECT openclose_udf(<database-name>, <context>, 1);
как требуется.
Последнее изменение этой страницы: 2022-01-08 05:02:57 UTC
SQLite is in the Public Domain.
https://sqlite.org/swarmvtab.html