struct sqlite3_index_info { /* Inputs */ int nConstraint; /* Number of entries in aConstraint */ struct sqlite3_index_constraint { int iColumn; /* Column constrained. -1 for ROWID */ unsigned char op; /* Constraint operator */ unsigned char usable; /* True if this constraint is usable */ int iTermOffset; /* Used internally - xBestIndex should ignore */ } *aConstraint; /* Table of WHERE clause constraints */ int nOrderBy; /* Number of terms in the ORDER BY clause */ struct sqlite3_index_orderby { int iColumn; /* Column number */ unsigned char desc; /* True for DESC. False for ASC. */ } *aOrderBy; /* The ORDER BY clause */ /* Outputs */ struct sqlite3_index_constraint_usage { int argvIndex; /* if >0, constraint is part of argv to xFilter */ unsigned char omit; /* Do not code a test for this constraint */ } *aConstraintUsage; int idxNum; /* Number used to identify the index */ char *idxStr; /* String, possibly obtained from sqlite3_malloc */ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ int orderByConsumed; /* True if output is already ordered */ double estimatedCost; /* Estimated cost of using this index */ /* Fields below are only available in SQLite 3.8.2 and later */ sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ /* Fields below are only available in SQLite 3.9.0 and later */ int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ /* Fields below are only available in SQLite 3.10.0 and later */ sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ };
Структура sqlite3_index_info и ее подструктуры используются в качестве части интерфейса виртуальной таблицы, чтобы передать информацию и получить ответ от метода xBestIndex модуля виртуальной таблицы. Области под **Inputs** это ввод для xBestIndex, они read-only. xBestIndex вставляет свои результаты в поля **Outputs**.
Массив aConstraint[] делает запись ограничений оператора WHERE:
column OP expr
здесь OP это =, <, <=, > или >=. Конкретный оператор сохранен в aConstraint[].op с использованием одного из значений SQLITE_INDEX_CONSTRAINT_. Индекс колонки сохранен в aConstraint[].iColumn. aConstraint[].usable = TRUE, если expr на правой стороне может быть оценен (и таким образом ограничение применимое) и false, если это не так.
Оптимизатор автоматически инвертирует условия формы "expr OP column" и делает другие упрощения в операторе WHERE в попытке получить как можно больше условий оператора WHERE в форму, показанную выше. Массив aConstraint[] выстраивают только условия оператора WHERE, которые относятся к конкретной запрашиваемой виртуальной таблице.
Информация о пункте ORDER BY хранится в aOrderBy []. Каждый термин aOrderBy делает запись колонки пункта ORDER BY.
Поле colUsed указывает, какие колонки виртуальной таблицы могут требоваться текущим просмотром. Виртуальные столбцы таблицы пронумерованы с нуля в порядке в котором они появляются в рамках CREATE TABLE, переданным в sqlite3_declare_vtab(). Для первых 63 колонок (колонки 0-62) соответствующий бит установлен в маске colUsed, если колонка может требоваться SQLite. Если у таблицы есть по крайней мере 64 колонки, и любая колонка направо от первых 63 требуется, то бит 63 в colUsed также установлен. Другими словами, колонка iCol может требоваться, если выражение (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) оценивается к значению, отличному от нуля.
Метод xBestIndex должен заполнять aConstraintUsage[] информацией о том, какие параметры передать xFilter. Если argvIndex>0, тогда правая сторона соответствующего aConstraint[] оценена и становится записью argvIndex в argv. Если aConstraintUsage[].omit = true, то ограничение, как предполагается, полностью обработано виртуальной таблицей и не могло бы быть проверено снова байт-кодом. Флаг aConstraintUsage[].omit является намеком оптимизации. Когда флаг omit в его настройке по умолчанию false, ограничение будет всегда проверяться отдельно в байт-коде. Если флаг omit = true, то ограничение может или не может быть проверено в байт-коде. Другими словами, когда omit = true, нет никакой гарантии, что ограничение не будет проверено снова, используя байт-код.
idxNum и idxStr зарегистрированы и переданы в метод xFilter. sqlite3_free() используется, чтобы освободить idxStr если и только если needToFreeIdxStr = true.
orderByConsumed означает, что вывод от xFilter/xNext произойдет в правильном порядке, чтобы удовлетворить пункт ORDER BY так, чтобы никакой отдельный шаг сортировки не требовался.
Значение estimatedCost это оценка стоимости конкретной стратегии. Стоимость N указывает, что стоимость стратегии подобна линейному просмотру таблицы SQLite с N строками. Стоимость log(N) указывает, что расход операции подобен двоичному поиску на уникальной индексируемой области таблицы SQLite с N строками.
Значение estimatedRows это оценка количества строк, которые будут возвращены стратегией.
Метод xBestIndex может произвольно наполнить поле idxFlags маской флагов SQLITE_INDEX_SCAN_*. В настоящее время есть только один такой флаг SQLITE_INDEX_SCAN_UNIQUE. Если метод xBestIndex его установит, SQLite предполагает, что стратегия может посетить самое большее одну строку.
Кроме того, если xBestIndex устанавливает флаг SQLITE_INDEX_SCAN_UNIQUE, то SQLite также предполагает, что, если вызов метода xUpdate() сделан как часть того же самого запроса, чтобы удалить или обновить виртуальную строку таблицы и внедрение возвращает SQLITE_CONSTRAINT, то нет никакой потребности к обратной перемотке никаких изменений базы данных. Другими словами, если xUpdate() вернет SQLITE_CONSTRAINT, содержание базы данных должно быть точно таким, каким было прежде, чем вызвали xUpdate. В отличие от этого, если SQLITE_INDEX_SCAN_UNIQUE не установлен, и xUpdate вернет SQLITE_CONSTRAINT, любые изменения базы данных, внесенные методом xUpdate, автоматически отменены SQLite.
ВАЖНО: поле estimatedRows было добавлено к структуре sqlite3_index_info в SQLite version 3.8.2 (2013-12-06). Если виртуальное расширение таблицы используется с версией SQLite ранее, чем 3.8.2, результаты попытки прочитать или написать поле estimatedRows не определены (но, вероятно, будут включать сбой приложения). Поэтому estimatedRows можно использовать только если sqlite3_libversion_number() возвращает значение больше или равное 3008002. Точно так же поле idxFlags добавлено в version 3.9.0 (2015-10-14). Это может использоваться только, если sqlite3_libversion_number() возвращает значение больше или равное 3009000.
3 метода, использующих этот объект: sqlite3_vtab_collation(), sqlite3_vtab_distinct(), sqlite3_vtab_rhs_value()