Этот интерфейс представляет дескриптор, обеспеченный оперативной библиотекой SQLite.
Для списка всех членов этого типа посмотрите Члены ISQLiteNativeHandle.
Тип | Описание |
---|---|
SQLiteVirtualTableCursorEnumerator(T) | Этот класс представляет виртуальный курсор таблицы, который будет использоваться с классом SQLiteModuleEnumerable. Это не sealed и может использоваться в качестве базового класса для любого определенного пользователями виртуального класса курсора таблицы, который обертывает экземпляр объекта IEnumerator`1. |
SQLiteContext | Этот класс представляет контекст от оперативной библиотеки SQLite, которая может быть передана sqlite3_result_*() и присоединенным функциям. |
SQLiteValue | Этот класс представляет значение от оперативной библиотеки SQLite, которое может быть передано sqlite3_value_*() и присоединенным функциям. |
SQLiteVirtualTable | Этот класс представляет управляемое виртуальное внедрение таблицы. Это не sealed и должно использоваться в качестве базового класса для любых определенных пользователями виртуальных классов таблицы, осуществленных в управляемом коде. |
SQLiteVirtualTableCursor | Этот класс представляет управляемое виртуальное внедрение курсора таблицы. Это не sealed и должно использоваться в качестве базового класса для любых определенных пользователями виртуальных классов курсора, осуществленных в управляемом коде. |
SQLiteVirtualTableCursorEnumerator | Этот класс представляет виртуальный курсор таблицы, который будет использоваться с классом SQLiteModuleEnumerable. Это не sealed и может использоваться в качестве базового класса для любого определенного пользователями виртуального класса курсора таблицы, который обертывает экземпляр объекта IEnumerator. |
Namespace: System.Data.SQLite
Assembly: System.Data.SQLite (в System.Data.SQLite.dll)
Члены ISQLiteNativeHandle | Пространство имен System.Data.SQLite
Значение нативного дескриптора.
Интерфейс ISQLiteNativeHandle | Пространство имен System.Data.SQLite
![]() |
Значение нативного дескриптора. |
Интерфейс ISQLiteNativeHandle | Пространство имен System.Data.SQLite
Свойства интерфейса ISQLiteNativeHandle упоминаются ниже. Для полного списка участников интерфейса ISQLiteNativeHandle посмотрите Члены ISQLiteNativeHandle.
![]() |
Значение нативного дескриптора. |
Интерфейс ISQLiteNativeHandle | Пространство имен System.Data.SQLite
Этот интерфейс представляет виртуальное внедрение таблицы, написанное в собственном коде.
Для списка всех членов этого типа посмотрите Члены ISQLiteNativeModule.
Namespace: System.Data.SQLite
Assembly: System.Data.SQLite (в System.Data.SQLite.dll)
Члены ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xBegin)(sqlite3_vtab *pVTab);
Этот метод начинает транзакцию на виртуальной таблице. Этот метод опционален. Указатель xBegin в sqlite3_module может быть NULL.
Этот метод всегда сопровождается одним обращением к xCommit или xRollback. Виртуальные транзакции таблицы не вкладываются, таким образом, метод xBegin не будет вызван несколько раз на единственной виртуальной таблице без xCommit или xRollback. Множественные вызовы других методов могут и вероятно будут вызывать промежуточные xBegin и соответствующий xCommit или xRollback.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
SQLite использует метод xBestIndex виртуального модуля таблицы, чтобы определить лучший способ получить доступ к виртуальной таблице. У xBestIndex метода есть прототип:
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
Ядро SQLite общается с методом xBestIndex, заполняя определенные области структуры sqlite3_index_info и передавая указатель на ту структуру в xBestIndex как второй параметр. xBestIndex заполняет другие области этой структуры, которая формирует ответ. Структура sqlite3_index_info structure похожа на это:
struct sqlite3_index_info { /* Inputs */ const int nConstraint; /* Number of entries in aConstraint */ const 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 */ } *const aConstraint; /* Table of WHERE clause constraints */ const int nOrderBy; /* Number of terms in the ORDER BY clause */ const struct sqlite3_index_orderby { int iColumn; /* Column number */ unsigned char desc; /* True for DESC.False for ASC. */ } *const 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 */ } *const 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 */ };
Отметьте предупреждения на поля "estimatedRows", "idxFlags" и colUsed. Эти поля были добавлены с версиями 3.8.2, 3.9.0 SQLite и 3.10.0, соответственно. Любое расширение, которое читает или пишет эти поля, должно сначала проверить, что версия библиотеки SQLite в больше или равна соответствующей версии, возможно, сравнение значения, возвращенного sqlite3_libversion_number() с 3008002, 3009000 и/или 3010000. Результат попытки получить доступ к этим областям в структуре sqlite3_index_info, созданной более старой версией SQLite, не определен.
Кроме того, есть некоторые определенные константы:
#define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT16 #define SQLITE_INDEX_CONSTRAINT_GE32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 #define SQLITE_INDEX_CONSTRAINT_LIKE65/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_GLOB66/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_REGEXP67/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_NE68/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOT 69/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNULL71/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_IS72/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_LIMIT 73/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_OFFSET74/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150/* 3.25.0 and later */ #define SQLITE_INDEX_SCAN_UNIQUE 1/* Scan visits at most 1 row */
Используйте интерфейс sqlite3_vtab_collation(), чтобы найти имя последовательности сопоставления, которая должна использоваться, оценивая i-ое ограничение:
const char *sqlite3_vtab_collation(sqlite3_index_info*, int i);
Ядро SQLite вызывает xBestIndex, когда это собирает запрос, который включает виртуальную таблицу. Другими словами, SQLite вызывает этот метод, когда это управляет sqlite3_prepare() или эквивалент. Вызывая этот метод, ядро SQLite говорит виртуальной таблице, что должно получить доступ к некоторому подмножеству строк в виртуальной таблице, и это хочет знать самый эффективный способ сделать это. xBestIndex отвечает информацией, которую ядро SQLite может тогда использовать, чтобы провести эффективный поиск виртуальной таблицы.
Собирая единственный SQL-запрос, ядро SQLite могло бы вызвать xBestIndex многократно с различными параметрами настройки в sqlite3_index_info. Ядро SQLite тогда выберет комбинацию, которая, кажется, дает лучшую производительность.
Прежде, чем вызвать этот метод, ядро SQLite инициализирует экземпляр структуры sqlite3_index_info с информацией о запросе, который в настоящее время пытается обработать. Эта информация происходит, главным образом, из оператора Where или пунктов GROUP BY и ORDER BY запроса, но также и от любого ON или пунктов USING, если запрос это соединение. Информация, которую ядро SQLite предоставляет xBestIndex, содержится в части структуры, которая отмечена как "Inputs". Секция "Outputs" инициализируется к нолю.
Информация в структуре sqlite3_index_info эфемерна и может быть переписана или освобождена, как только xBestIndex возвращается. Если xBestIndex должен помнить какую-либо часть sqlite3_index_info, это должно сделать копию.
Заметьте, что xBestIndex будут всегда вызван до xFilter, так как idxNum и idxStr следуют из xBestIndex и нужны для xFilter. Однако, нет никакой гарантии, что xFilter вызовут после успешного xBestIndex.
xBestIndex нужен для каждого виртуального внедрения таблицы.
Главным, что ядро SQLite пытается сообщить виртуальной таблице, являются ограничения, которые доступны, чтобы ограничить количество строк, которые должны быть просмотрены. Массив aConstraint[] содержит один вход для каждого ограничения. Будет точно nConstraint записей в том множестве.
Каждое ограничение будет обычно соответствовать термину в операторе Where или в пункте USING или ON, который имеет форму
column OP EXPR
Здесь "column" колонка в виртуальной таблице, OP оператор вроде "=" или "<", а EXPR это произвольное выражение. Так, например, если оператор Where содержал термин:
a = 5
Тогда одно из ограничений было бы на колонке "a" с оператором "=" и выражением "5". У ограничений не должно быть буквального представления оператора Where. Оптимизатор запросов мог бы сделать преобразования к оператору Where, чтобы извлечь столько ограничений, сколько это может. Так, например, если оператор Where содержал что-то вроде этого:
x BETWEEN 10 AND 100 AND 999>y
Оптимизатор запросов мог бы перевести это на три отдельных ограничения:
x >= 10 x <= 100 y < 999
Для каждого такого ограничения поле aConstraint[].iColumn указывает, какая колонка появляется на левой стороне ограничения. Первая колонка виртуальной таблицы это колонка 0. rowid виртуальной таблицы это колонка -1. Поле aConstraint[].op указывает, какой оператор используется. Константы SQLITE_INDEX_CONSTRAINT_* отображают константы целого числа в значениях operator. Колонки происходят в том порядке, в каком они были определены обращением к sqlite3_declare_vtab() в xCreate или xConnect. Скрытые столбцы посчитаны, определяя индекс столбца.
Если метод xFindFunction() для виртуальной таблицы определяется, и если xFindFunction() вернет SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, то ограничения могли бы также иметь форму:
FUNCTION(column, EXPR)
В этом случае значение aConstraint[].op совпадает со значением, возвращенным xFindFunction() для FUNCTION.
Массив aConstraint[] содержит информацию обо всех ограничениях, которые относятся к виртуальной таблице. Но некоторые ограничения не могли бы быть применимыми из-за способа, которым таблицы упорядочены в соединении. xBestIndex должен поэтому только рассмотреть ограничения, у которых есть флаг aConstraint[].usable = true.
В дополнение к ограничениям оператора Where ядро SQLite также говорит xBestIndex о пункте ORDER BY. В агрегатном запросе ядро SQLite могло бы вставить информацию о пункте GROUP BY вместо информации о пункте ORDER BY, но этот факт не должен иметь никакого отношения к xBestIndex. Если все условия пункта ORDER BY будут колонками в виртуальной таблице, то nOrderBy будет количеством условий в пункте ORDER BY и массив aOrderBy[] определит колонку для каждого термина в порядке order и является ли та колонка ASC или DESC.
В SQLite version 3.10.0 (2016-01-06) и позже поле colUsed доступно, чтобы указать, какие поля виртуальной таблицы на самом деле используются подготовленным запросом. Если самая низкая часть colUsed установлена, это означает, что первая колонка используется. Второй самый низкий бит соответствует второй колонке и т. д. Если старшая значащая часть colUsed установлена, это означает, что используются одна или более колонок кроме первых 63 колонок. Если информация об использовании колонки необходима xFilter, то необходимые биты должны быть закодированы в вывод idxNum или idxStr.
Для LIKE, GLOB, REGEXP и MATCH значение aConstraint[].iColumn является столбцом виртуальной таблицы, который является левым операндом оператора. Однако, если эти операторы выражаются как вызовы функции вместо операторов, то значение aConstraint[].iColumn ссылается на столбец виртуальной таблицы, который является вторым аргументом той функции:
LIKE(EXPR, column)
GLOB(EXPR, column)
REGEXP(EXPR, column)
MATCH(EXPR, column)
Следовательно, до вызова xBestIndex() следующие две формы эквивалентны:
column LIKE EXPR
LIKE(EXPR,column)
Это специальное поведение рассмотрения второго аргумента функции происходит только для LIKE, GLOB, REGEXP и MATCH. Для всех других функций aConstraint[].iColumn ссылается на первый аргумент функции.
Эта специальная функция LIKE, GLOB, REGEXP и MATCH не относится к xFindFunction(). Он выключает левый операнд оператора LIKE, GLOB, REGEXP или MATCH, но исключение первого аргумента эквивалентно вызову функции тех операторов.
Когда aConstraint[].op это SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, это указывает, что есть пункт LIMIT или OFFSET в запросе SQL, который использует виртуальную таблицу. У операторов LIMIT и OFFSET нет левого операнда, поэтому когда aConstraint[].op = SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, aConstraint[].iColumn бессмыслено и не должно использоваться.
Интерфейс sqlite3_vtab_rhs_value() может использоваться, чтобы попытаться получить доступ к правому операнду ограничения. Однако, значение правого оператора не могло быть известно в то время, когда работает xBestIndex. Значит вызов sqlite3_vtab_rhs_value() успешным быть не может. Обычно правильный операнд ограничения доступен только xBestIndex, если это закодировано как литеральное значение во входе SQL. Если правый операнд будет закодирован как выражение или параметр host, это, вероятно, не будет доступно для xBestIndex. У некоторых операторов, таких как SQLITE_INDEX_CONSTRAINT_ISNULL и SQLITE_INDEX_CONSTRAINT_ISNOTNULL нет правого операнда. Интерфейс sqlite3_vtab_rhs_value() всегда возвращает SQLITE_NOTFOUND для таких операторов.
Учитывая всю информацию выше, работа метода xBestIndex это выяснение лучшего способа искать виртуальную таблицу.
xBestIndex передает стратегию индексации xFilter методу через поля idxNum и idxStr. Значение idxNum и содержание последовательности idxStr произвольны, насколько ядро SQLite затронуто и могут иметь любое значение, в зависимости от xBestIndex и xFilter. Ядро SQLite просто копирует информацию от xBestIndex к xFilter предполагая только, что последовательность, на которую ссылаются через idxStr, закончена NUL.
idxStr может быть последовательностью, полученной из функции выделения памяти SQLite, такой как sqlite3_mprintf(). Если это верно, тогда флаг needToFreeIdxStr должен быть установлен в true так, чтобы ядро SQLite знало, что надо вызвать sqlite3_free() на той последовательности, когда это закончит работу с ней, и таким образом избегать утечки памяти. Значение idxStr может также быть статической постоянной строкой, в этом случае needToFreeIdxStr needToFreeIdxStr=false.
Поле estimatedCost должно быть установлено в предполагаемое количество операций по доступу к диску, требуемых, чтобы выполнить этот запрос для виртуальной таблицы. Ядро SQLite будет часто вызывать xBestIndex многократно с различными ограничениями, получать многократные сметы, затем выбирать план запросов, который дает самую низкую оценку. Ядро SQLite инициализирует estimatedCost к очень большому значению до xBestIndex, так что если xBestIndex решает, что текущая комбинация параметров нежелательна, это может оставить поле estimatedCost без изменений, чтобы препятствовать ее использованию.
Если текущая версия SQLite 3.8.2 или выше, поле estimatedRows может быть установлено в оценку количества строк, возвращенных предложенным планом запросов. Если это значение явно не установлено, используется оценка по умолчанию в 25 строк.
Если текущая версия SQLite 3.9.0 или выше, поле idxFlags может быть установлено в SQLITE_INDEX_SCAN_UNIQUE, чтобы указать, что виртуальная таблица возвратит только ноль или одну строк, заданные входными ограничениями. Опциональные биты поля idxFlags могли бы быть поняты в более поздних версиях SQLite.
Массив aConstraintUsage[] содержит один элемент для каждого из ограничений nConstraint во входном разделе структуры sqlite3_index_info. Множество aConstraintUsage[] используется xBestIndex, чтобы сказать ядру, как это использует ограничения.
xBestIndex может установить aConstraintUsage[].argvIndex записи в значения больше 0. Точно один вход должен быть установлен в 1, другой к 2, другой в 3 и т. д. EXPR соответствующих ограничений будет тогда передан как параметр argv[] для xFilter.
Например, если aConstraint[3].argvIndex = 1, xFilter вызван с argv[0] длч xFilter со значением EXPR ограничения aConstraint[3].
По умолчанию SQLite производит bytecode, который будет проверять все ограничения дважды на каждую строку виртуальной таблицы, чтобы проверить, что они удовлетворены. Если виртуальная таблица может гарантировать, что ограничение будет всегда удовлетворяться, это может попытаться подавить ту перепроверку, установив aConstraintUsage[].omit. Однако, за некоторыми исключениями, это только намек и нет никакой гарантии, что избыточная проверка ограничения будет подавлена. Ключевые пункты:
Если виртуальная таблица произведет строки в порядке, определенном пунктом ORDER BY, то флаг orderByConsumed может быть установлен в true. Если вывод не автоматически в правильном порядке, тогда orderByConsumed должен быть оставлен в его умолчании false. Это укажет ядру SQLite, что должна быть сделана отдельная сортировка данных после того, как они выходят из виртуальной таблицы. Урегулирование orderByConsumed является оптимизацией. Запрос будет всегда получать правильный ответ, если orderByConsumed оставят в его значении по умолчанию (0). Ненужных операций по сортировке можно было бы избежать, придя к более быстрому запросу, если orderByConsumed установлен, но установка orderByConsumed неправильно может привести к неправильному ответу. Предложено, чтобы новые виртуальные внедрения таблицы оставили сброс значения orderByConsumed первоначально, а затем после того, как все остальное, как известно, работает правильно, вернулись и попытались оптимизировать, установив orderByConsumed в соответствующих случаях.
Иногда флаг orderByConsumed может быть безопасно установлен, даже если вывод виртуальной таблицы не находится строго в порядке, определенном nOrderBy и aOrderBy. Если интерфейс sqlite3_vtab_distinct() вернет 1 или 2, это указывает, что порядок может быть смягчен. См. документацию относительно sqlite3_vtab_distinct().
xBestIndex должен возвратить SQLITE_OK при успехе. Если какой-либо вид фатальной ошибки происходит, соответствующий код ошибки (например, SQLITE_NOMEM) должен быть возвращен вместо этого.
Если xBestIndex вернет SQLITE_CONSTRAINT, это не указывает на ошибку. SQLITE_CONSTRAINT указывает, что конкретная комбинация входных определенных параметров недостаточна для виртуальной таблицы, чтобы сделать ее работу. Это логически то же самое, как урегулирование estimatedCost к бесконечности. Если каждое обращение к xBestIndex для конкретного плана запросов возвратит SQLITE_CONSTRAINT, это означает, что нет никакого пути к виртуальной таблице, который будет безопасно использоваться, и вызов sqlite3_prepare() потерпит неудачу с ошибкой "no query solution".
Возвращение SQLITE_CONSTRAINT из xBestIndex полезно для табличных функций, у которых есть обязательные параметры. Если aConstraint[].usable = false для одного из обязательного параметра, то xBestIndex должен возвратить SQLITE_CONSTRAINT. Если обязательное поле не появляется в множестве aConstraint[] вообще, это означает, что соответствующий параметр опущен во входе SQL. В этом случае xBestIndex должен установить сообщение об ошибке в pVTab->zErrMsg и вернуть SQLITE_ERROR. Итак:
Следующий пример лучше иллюстрирует использование SQLITE_CONSTRAINT как возвращаемое значение из xBestIndex:
SELECT * FROM realtab, tablevaluedfunc(realtab.x);
Предполагая, что первый скрытый столбец "tablevaluedfunc" = "param1", запрос выше семантически эквивалентен этому:
SELECT * FROM realtab, tablevaluedfunc WHERE tablevaluedfunc.param1 = realtab.x;
Планировщик запроса должен решить между многими возможными внедрениями этого запроса, но два плана в особенности интересны:
xBestIndex будет вызван однажды для каждого из потенциальных планов выше. Для плана 1 флаг aConstraint[].usable для ограничения SQLITE_CONSTRAINT_EQ на колонку param1 будет верен потому, что значение правой стороны для ограничения "param1 = ?" будет известно, так как оно определяется внешним циклом realtab. Но для плана 2 флаг aConstraint[].usable для "param1 = ?" будет false потому, что значение правой стороны определяется внутренним циклом и является таким образом неизвестным. Поскольку param1 это необходимый вход к табличным функциям, xBestIndex вернет SQLITE_CONSTRAINT, когда смотрит план 2, указав, что необходимый вход отсутствует. Это вынуждает планировщик запроса выбрать план 1.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xClose)(sqlite3_vtab_cursor*);
xClose закрывает курсор, ранее открытый xOpen. Ядро SQLite будет всегда вызывать xClose однажды для каждого курсора, открытого, используя xOpen.
Этот метод должен высвободить все ресурсы, ассигнованные соответствующим обращением xOpen. Процедуру не вызовут снова, даже если она возвратит ошибку. Ядро SQLite не будет использовать sqlite3_vtab_cursor снова после того, как это будет закрыто.
xClose требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int N);
Ядро SQLite вызывает этот метод, чтобы найти значение для N-й колонки текущей строки. N основан на ноле, таким образом, первая колонка пронумерована 0. xColumn может возвратить свой результат назад SQLite использованием одного из следующих интерфейсов:
Если реализация метода xColumn не вызывает ни одну из функций выше, значение колонки по умолчанию SQL NULL.
Чтобы поднять ошибку, xColumn должен использовать один из методов result_text(), чтобы установить текст сообщения об ошибке, затем возвратить соответствующий код ошибки. xColumn должен возвратить SQLITE_OK при успехе.
xColumn требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xCommit) (sqlite3_vtab *pVTab);
Этот метод заставляет транзакцию виртуальной таблицы передавать. Это опциональный метод. Указатель xCommit в sqlite3_module может быть NULL.
Обращение к этому методу всегда следует за предшествующим обращением к xBegin и xSync.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xConnect) (sqlite3*, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr);
Метод xConnect очень похож на xCreate. Это имеет те же самые параметры и строит новую структуру sqlite3_vtab точно так же, как xCreate. И это должно также вызвать sqlite3_declare_vtab() подобно xCreate. Это должно также сделать все те же самые вызовы sqlite3_vtab_config(), как xCreate.
Различие в том, что xConnect вызывают, чтобы установить новую связь с существующей виртуальной таблицей, тогда как xCreate вызывают, чтобы составить новую виртуальную таблицу с нуля.
xCreate и xConnect отличаются только когда у виртуальной таблицы есть некоторое запоминающее устройство, которое должно быть инициализировано в первый раз, когда виртуальная таблица составлена. xCreate создает и инициализирует запоминающее устройство. xConnect просто соединяется с существующим запоминающим устройством. Когда xCreate и xConnect то же самое, таблица это виртуальная таблица.
Как пример, рассмотрите виртуальное внедрение таблицы, которое обеспечивает доступ только для чтения к существующим файлам comma-separated-value (CSV) на диске. Нет никакого запоминающего устройства, которое должно быть создано или инициализировано для такого виртуальной таблицы (так как файлы CSV уже существуют на диске), так что методы xCreate и xConnect будут идентичны для того модуля.
Другой пример это виртуальная таблица, которая осуществляет полнотекстовый индекс. xCreate должен создать и инициализировать структуры данных, чтобы хранить словарь и управляющие списки для этого индекса. xConnect с другой стороны должен определить только местонахождение и использовать существующий словарь и списки, которые были созданы предшествующим обращением xCreate.
xConnect должен вернуть SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если не успешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если что-то пошло не так. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить пространство, используя sqlite3_free(), после того, как об ошибке сообщили приложению.
xConnect требуется для каждого виртуального внедрения таблицы, хотя указатели xCreate и xConnect объекта sqlite3_module могут указать на ту же самую функцию, если виртуальная таблица не должна инициализировать запоминающее устройство.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xCreate) (sqlite3 *db, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr);
Метод xCreate вызывают, чтобы создать новый экземпляр виртуальной таблицы в ответ на CREATE VIRTUAL TABLE. Если метод xCreate пропущен (указатель NULL), виртуальная таблица это одноименно-единственная виртуальная таблица.
Параметр db это указатель на соединение с базой данных SQLite, которое выполняет CREATE VIRTUAL TABLE. pAux это копия указателя данных клиента, который был четвертым аргументом вызова sqlite3_create_module() или sqlite3_create_module_v2(), который зарегистрировал виртуальный модуль таблицы. Параметр argv это массив указателей на законченные null последовательности. Первая последовательность, argv[0], является именем вызываемого модуля. Имя модуля это имя, обеспеченное как второй аргумент sqlite3_create_module() и как аргумент пункта USING в CREATE VIRTUAL TABLE. Вторым, argv[1], является название базы данных, в которой составляется новая виртуальная таблица. Имя базы данных "main" для основной базы данных, "temp" для базы данных TEMP или имя, данное в конце запроса ATTACH для приложенных баз данных. Третий элемент множества, argv[2], является названием новой виртуальной таблицы, как определено после ключевого слова TABLE в CREATE VIRTUAL TABLE. Если существуют, четвертая и последующие последовательности в массиве argv[] сообщают об аргументах имени модуля в CREATE VIRTUAL TABLE.
Работа по этому методу состоит в том, чтобы построить новый виртуальный объект таблицы (объект sqlite3_vtab) и возвратить указатель на него в *ppVTab.
Как часть задачи создания новой структуры sqlite3_vtab, этот метод должен вызвать sqlite3_declare_vtab(), чтобы сказать ядру SQLite о колонках и типах данных в виртуальной таблице. sqlite3_declare_vtab() API имеет следующий прототип:
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable)
Первым аргументом sqlite3_declare_vtab() должен быть тот же самый указатель соединения с базой данных, как первый параметр этого метода. Второй аргумент sqlite3_declare_vtab() должен быть законченной нолем строкой UTF-8, которая содержит правильно построенный запрос CREATE TABLE, который определяет колонки в виртуальной таблице и их типы данных. Имя таблицы в этом CREATE TABLE проигнорировано, как все ограничения. Только запрос имен столбцов и типов данных. Последовательность CREATE TABLE не должна быть проведена в постоянной памяти. Последовательность может быть освобождена и/или снова использована, как только завершится sqlite3_declare_vtab().
xConnect может также произвольно просить специальные функции для виртуальной таблицы, сделав один или несколько вызовов интерфейса sqlite3_vtab_config():
int sqlite3_vtab_config(sqlite3 *db, int op, ...);
Вызов sqlite3_vtab_config() опционален. Но для максимальной безопасности рекомендуется, чтобы виртуальные внедрения таблицы вызвали "sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY)", если виртуальную таблицу не будет использовать изнутри триггеров или обзоров.
xCreate не должен инициализировать поля pModule, nRef и zErrMsg объекта sqlite3_vtab. Ядро SQLite будет заботиться об этой работе.
xCreate должен возвратить SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если неуспешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если есть проблема. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить место, используя sqlite3_free() после того, как об ошибке сообщили приложению.
Если опущен xCreate (оставленный как NULL), виртуальная таблица это одноименно-единственная виртуальная таблица. Новые экземпляры виртуальной таблицы не могут быть созданы, используя CREATE VIRTUAL TABLE, а виртуальная таблица может использоваться только через имя модуля. Обратите внимание на то, что версии SQLite до 3.9.0 (2015-10-14) не понимают одноименно-единственные виртуальные таблицы и будет segfault, если предпринята попытка CREATE VIRTUAL TABLE на одноименно-единственной виртуальной таблице, потому что метод xCreate не был проверен на пустой указатель.
Если метод xCreate тот же самый указатель, как xConnect, это указывает, что виртуальная таблица не должна инициализировать запоминающее устройство. Такая виртуальная таблица может использоваться в качестве одноименной виртуальной таблицы, в качестве названной виртуальной таблицы, используя CREATE VIRTUAL TABLE, или обоими способами.
Если тип данных колонки содержит специальное ключевое слово "HIDDEN" (в какой-либо комбинации прописных и строчных букв), ключевое слово опущено от имени типа данных колонки, а колонка отмечена как скрытый столбец внутренне. Скрытый столбец отличается от нормальной колонки в трех отношениях:
Например, если следующий SQL передается sqlite3_declare_vtab():
CREATE TABLE x(a HIDDEN VARCHAR(12), b INTEGER, c INTEGER Hidden);
Тогда виртуальная таблица была бы составлена с двумя скрытыми столбцами с типами данных "VARCHAR(12)" и "INTEGER".
Использование в качестве примера скрытых столбцов может быть замечено в виртуальном внедрении таблицы FTS3, где каждая виртуальная таблица FTS содержит скрытый столбец FTS, который используется, чтобы передать информацию от виртуальной таблицы во вспомогательные функции FTS и оператору MATCH FTS.
Виртуальная таблица, которая содержит скрытые столбцы, может использоваться как табличная функция в пункте FROM оператора SELECT. Аргументы табличной функции становятся ограничениями на столбцах HIDDEN виртуальной таблицы.
Например, расширение "generate_series" (файл ext/misc/series.c дерева исходных текстов) осуществляет одноименную виртуальную таблицу со следующей схемой:
CREATE TABLE generate_series(value, start HIDDEN, stop HIDDEN, step HIDDEN);
Метод sqlite3_module.xBestIndex во внедрении этой таблицы проверяет на ограничения равенства столбцы HIDDEN и использует их как входные параметры, чтобы определить диапазон вывода integer "value", чтобы произвести. Разумные значения по умолчанию используются для любых неограниченных колонок. Например, чтобы перечислить все целые числа между 5 и 50:
SELECT value FROM generate_series(5,50);
Предыдущий запрос эквивалентен следующему:
SELECT value FROM generate_series WHERE start=5 AND stop=50;
Аргументы на виртуальном имени таблицы соответствуют скрытым столбцам в порядке. Количество аргументов может быть меньше, чем количество скрытых столбцов, в этом случае последние скрытые столбцы не ограничены. Однако, будет ошибка, если есть больше аргументов, чем в виртуальной таблице есть скрытых столбцов.
Начиная с SQLite version 3.14.0 (2016-08-08), CREATE TABLE, который передается в sqlite3_declare_vtab(), может содержать WITHOUT ROWID. Это полезно для случаев, где виртуальные строки таблицы не могут быть легко отображены в уникальные целые числа. Запрос CREATE TABLE, который включает WITHOUT ROWID, должен определить одну или более колонок как PRIMARY KEY. Каждая колонка PRIMARY KEY должна индивидуально быть NOT NULL, а все колонки для каждой строки должны быть коллективно уникальными.
Обратите внимание на то, что SQLite не проводит в жизнь PRIMARY KEY для виртуальной таблицы WITHOUT ROWID. Осуществление это ответственность основного виртуального внедрения таблицы. Но SQLite действительно предполагает, что ограничение PRIMARY KEY действительно, что определенные колонки UNIQUE и NOT NULL, и использует это предположение, чтобы оптимизировать запросы для виртуальной таблицы.
Столбец rowid недоступен в виртуальной таблице (конечно) WITHOUT ROWID.
Метод xUpdate был первоначально разработан вокруг наличия ROWID как единственного значения. xUpdate был расширен, чтобы приспособить произвольный PRIMARY KEY вместо ROWID, но PRIMARY KEY все еще должен быть только одной колонкой. Поэтому SQLite отклонит любую виртуальную таблицу WITHOUT ROWID, у которой есть больше, чем одна колонка PRIMARY KEY и не-NULL метод xUpdate.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xDestroy)(sqlite3_vtab *pVTab);
Этот метод закрывает связь с виртуальной таблицей, точно так же, как xDisconnect, и это также разрушает внедрение базовой таблицы. Этот метод отменяет работу xCreate.
xDisconnect вызывают каждый раз, когда соединение с базой данных, которое использует виртуальную таблицу, закрывается. Метод xDestroy вызывают только когда запрос DROP TABLE выполняется для виртуальной таблицы.
Метод xDestroy требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xDisconnect)(sqlite3_vtab *pVTab);
Этот метод освобождает связь с виртуальной таблицей. Только объект sqlite3_vtab разрушен. Виртуальную таблицу не разрушают, любое запоминающее устройство, связанное с виртуальной таблицей, сохраняется. Этот метод отменяет работу xConnect.
Этот метод деструктор для связи с виртуальной таблицей. Противопоставьте этот метод xDestroy. xDestroy это деструктор для всей виртуальной таблицы.
Метод xDisconnect требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xEof)(sqlite3_vtab_cursor*);
Метод xEof должен возвратить false (0), если указанный курсор в настоящее время указывает на действительную строку данных, иначе true (не 0). Этот метод немедленно вызывает движок SQL после каждого xFilter и xNext.
Метод xEof требуется для каждого виртуального внедрения таблицы.
Не 0, если больше строк недоступно, ноль иначе.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xFilter) (sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv);
Этот метод начинает поиск виртуальной таблицы. Первый аргумент задает курсор, открытый xOpen. Следующие два аргумента определяют конкретный индекс поиска, ранее выбранный xBestIndex. Определенные значения idxNum и idxStr неважны, xFilter и xBestIndex договариваются, каково то значение.
Функция xBestIndex, возможно, запросит значения определенных выражений, используя aConstraintUsage[].argvIndex в структуре sqlite3_index_info. Эти значения передаются xFilter через использование argc и argv.
Если виртуальная таблица содержит одну или несколько строк, которые соответствуют критериям поиска, то курсор должен быть левой точкой в первой строке. Последующие обращения к xEof должны вернуть false (0). Если нет никакого соответствия строк, курсор нужно оставить в состоянии, которое заставит xEof возвращать true (не 0). Движок SQLite будет использовать методы xColumn и xRowid, чтобы получить доступ к тому содержанию строки. Метод xNext будет использоваться, чтобы продвинуться к следующей строке.
Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит.
Метод xFilter требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xFindFunction) (sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg);
Этот метод вызывают во время sqlite3_prepare(), чтобы дать виртуальному внедрению таблицы возможность перегрузить функции. Этот метод может быть установлен в NULL, в этом случае, никакая перегрузка не происходит.
Когда функция использует колонку от виртуальной таблицы как первый аргумент, этот метод вызывают, чтобы видеть, хотела ли виртуальная таблица перегрузить функцию. Первые три параметра это входы: виртуальная таблица, количество аргументов функции и имя функции. Если никакая перегрузка не желаема, этот метод возвращает 0. Чтобы перегрузить функцию, этот метод вписывает в новую реализацию функции *pxFunc, вписывает в пользовательские данные *ppArg и возвращает 1 или число между SQLITE_INDEX_CONSTRAINT_FUNCTION и 255.
Исторически возвращаемое значение xFindFunction() было нолем или единицей. Ноль означает, что функция не перегружена, единица подразумевает, что это перегрузка. Способность к возвращаемым значениям SQLITE_INDEX_CONSTRAINT_FUNCTION или больше была добавлена в версии 3.25.0 (2018-09-15). Если xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, это значит, что функция берет два аргумента, функция может использоваться в качестве булева значения в операторе Where запроса и что виртуальная таблица в состоянии эксплуатировать ту функцию, чтобы ускорить результат запроса. Когда xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, возвращенное значение становится значением sqlite3_index_info.aConstraint.op для одного из ограничений, переданных в xBestIndex(). Первый аргумент функции это колонка, определенная полем aConstraint[].iColumn ограничения. Второй аргумент функции это значение, которое будет передано в xFilter() (если задано aConstraintUsage[].argvIndex) или значение, возвращенное из sqlite3_vtab_rhs_value().
Модуль Geopoly это пример виртуальной таблицы, который использует SQLITE_INDEX_CONSTRAINT_FUNCTION, чтобы улучшить работу. Метод xFindFunction() для Geopoly вернет SQLITE_INDEX_CONSTRAINT_FUNCTION для функции geopoly_overlap() SQL и SQLITE_INDEX_CONSTRAINT_FUNCTION+1 SQL-функции geopoly_within(). Это разрешает оптимизации поиска для таких запросов, как:
SELECT * FROM geopolytab WHERE geopoly_overlap(_shape, $query_polygon); SELECT * FROM geopolytab WHERE geopoly_within(_shape, $query_polygon);
Обратите внимание на то, что infix-функции (LIKE, GLOB, REGEXP и MATCH) полностью изменяют порядок их аргументов. Так "like(A,B)" обычно работала бы как "B like A". Однако, xFindFunction() всегда смотрит крайний левый аргумент, но не первый логический аргумент. Следовательно, для формы "B like A" SQLite смотрит на левый операнд "B" и если тот операнд столбец виртуальной таблицы, он вызывает метод xFindFunction() на той виртуальной таблице. Но если форма "like(A,B)" используется вместо этого, то SQLite проверяет термин, чтобы видеть, является ли это колонкой виртуальной таблицы, и если так это вызывает метод xFindFunction() для колонки A виртуальной таблицы.
Указатель функции, возвращенный этим установленным порядком, должен быть действительным для целой жизни объекта sqlite3_vtab, данного в первом параметре.
Не 0, если указанная функция была найдена, иначе 0.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xNext)(sqlite3_vtab_cursor*);
Метод xNext переводит виртуальный курсор таблицы к следующей строке набора результатов, инициированного xFilter. Если курсор уже указывает на последнюю строку, когда это вызывают, то курсор больше не указывает на действительные данные, последующее обращение к методу xEof должно возвратить true (не 0). Если курсор успешно продвинут к другой строке содержания, то последующие обращения к xEof должны вернуть false (0).
Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит.
Метод xNext требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
Метод xOpen создает новый курсор, используемый для доступа (чтение и/или запись) к виртуальной таблице. Успешный вызов этого метода ассигнует память для sqlite3_vtab_cursor (или подкласс), инициализирует новый объект и сделает *ppCursor указателем на новый объект. Успешный вызов тогда возвращает SQLITE_OK.
Для каждого успешного вызова этого метода ядро SQLite позже вызовет xClose, чтобы разрушить ассигнованный курсор.
xOpen не должен инициализировать поле pVtab структуры sqlite3_vtab_cursor. Ядро SQLite будет заботиться об этой работе автоматически.
Виртуальное внедрение таблицы должно быть в состоянии поддержать произвольное число одновременно открытых курсоров.
Когда первоначально открыт, курсор находится в неопределенном состоянии. Ядро SQLite вызовет метод xFilter на курсоре до любой попытки поместить его куда-то или читать из курсора.
Метод xOpen требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);
Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже.
При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M.
Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback().
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
Этот метод предоставляет уведомление, что виртуальной таблице дадут новое имя. Если этот метод возвращает SQLITE_OK, SQLite переименовывает таблицу. Если этот метод возвращает код ошибки, переименование предотвращено.
Метод xRename опционален. Если опущен, то виртуальная таблица не может быть переименована, используя ALTER TABLE RENAME.
PRAGMA legacy_alter_table позволен до вызова этого метода, значение для legacy_alter_table восстановлено после того, как этот метод заканчивается. Это необходимо для правильной работы таблиц, которые используют теневые таблицы, где теневые таблицы должны быть переименованы, чтобы соответствовать новому виртуальному имени таблицы. Если legacy_alter_format будет выключен, то метод xConnect будет вызван для виртуальной таблицы каждый раз, когда xRename пытается изменить название теневой таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xRollback)(sqlite3_vtab *pVTab);
Этот метод вызывает отмену транзакции виртуальной таблицы. Этот метод опционален. Указатель xRollback в sqlite3_module может быть NULL.
Обращение к этому методу всегда следует за предшествующим обращением к xBegin.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);
Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии SQLite version 3.7.7 (2011-06-23) и позже.
При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что это должно сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда в последний раз вызывали xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена без повторной инициализации вызовом xSavepoint(). Обращение к xRelease(X,M) лишает законной силы все точки сохранения, где N>=M.
Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями к xBegin() и xCommit() или xRollback().
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xRowid)(sqlite3_vtab_cursor *pCur, sqlite_int64 *pRowid);
Успешный вызов этого метода заставит *pRowid быть заполненным rowid строки, на которую в настоящее время указывает виртуальный курсор таблицы pCur. Этот метод возвращает SQLITE_OK при успехе. Это возвращает соответствующий код ошибки при неудаче.
Метод xRowid требуется для каждого виртуального внедрения таблицы.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);
Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии SQLite version 3.7.7 (2011-06-23) и позже.
При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точку сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, каким это было, когда в последний раз вызвали xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;. Обращение к xRelease(X,M) лишает законной силы все точки сохранения где N>=M.
Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызваны между xBegin() и xCommit() или xRollback().
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xSync)(sqlite3_vtab *pVTab);
Этот метод сигнализирует о начале двухфазной фиксации на виртуальной таблице. Этот метод дополнительный. Указатель xSync в sqlite3_module может быть NULL.
Этот метод вызван только после xBegin и до xCommit или xRollback. Чтобы осуществить двухфазную фиксацию, метод xSync на всех виртуальных таблицах вызван до xCommit на любой виртуальной таблице. Если какой-либо из xSync терпит неудачу, вся транзакция отменяется.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
int (*xUpdate) (sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid);
Все изменения виртуальной таблицы внесены, используя метод xUpdate. Этот метод может использоваться, чтобы вставить, удалить или обновить.
Параметр argc определяет количество записей во множестве argv. Значение argc 1 для чистого удаления или N+2 для вставки или замены, где N это количество колонок в таблице. В предыдущем предложении N включает любые скрытые столбцы.
Каждая запись argv будет иметь значение не NULL в C, но может содержать значение SQL NULL. Другими словами, всегда верно что argv[i]!=0 для i от 0 до argc-1. Однако, могло бы иметь место sqlite3_value_type(argv[i])==SQLITE_NULL.
Параметр argv[0] это rowid строки, которая будет удалена. Если argv[0] это SQL NULL, никакое удаление не происходит.
Параметр argv[1] это rowid новой строки, которая будет вставлена в виртуальную таблицу. Если argv[1] это SQL NULL, внедрение должно выбрать rowid для недавно вставленной строки. Последующие записи argv[] содержат значения колонок виртуальной таблицы в порядке, в котором были объявлены колонки. Количество колонок будет соответствовать декларации таблицы, которую метод xConnect или xCreate сделал использованием sqlite3_declare_vtab(). Все скрытые столбцы включены.
Делая вставку без rowid (argc>1, argv[1] = SQL NULL), на виртуальной таблице, которая использует ROWID (но не на WITHOUT ROWID), внедрение должно установить *pRowid в rowid недавно вставленной строки, это станет значением, возвращенным функцией sqlite3_last_insert_rowid(). Устанавливание этого значения во всех других случаях является безопасным, движок SQLite игнорирует *pRowid возвращаемое значение, если argc == 1 или argv[1] не является NULL SQL.
Каждое обращение к xUpdate попадет в один из случаев, показанных ниже. Ссылки на argv[i] обозначают SQL-значение в объекте argv[i], но не сам объект argv[i].
UPDATE table SET rowid=rowid+1 WHERE ...;
Метод xUpdate должен возвратить SQLITE_OK если и только если это успешно. Если неудача происходит, xUpdate должен возвратить соответствующий код ошибки. При неудаче элемент pVTab->zErrMsg может произвольно быть заменен текстом сообщения об ошибке, сохраненным в памяти, ассигнованной от SQLite через функции вроде sqlite3_mprintf() или sqlite3_malloc().
Если xUpdate нарушает некоторое ограничение виртуальной таблицы (включая, но не ограничиваясь попытку сохранить значение неверного типа данных, сохранить значение, которое является слишком большим или слишком маленьким, или изменить значение только для чтения), xUpdate должен потерпеть неудачу с соответствующим кодом ошибки.
Если xUpdate выполняет UPDATE, то sqlite3_value_nochange(X) может использоваться, чтобы обнаружить, какие колонки виртуальной таблицы были на самом деле изменены запросом UPDATE. Интерфейс sqlite3_value_nochange(X) вернет true для колонок, которые не изменяются. На каждом UPDATE SQLite сначала вызовет xColumn отдельно для каждой неизменной колонки в таблице, чтобы получить значение для той колонки. xColumn может проверить, неизменна ли колонка на уровне SQL через sqlite3_vtab_nochange(). Если xColumn видит, что колонка не изменяется, это должно возвратиться, не устанавливая результат, используя один из интерфейсов sqlite3_result_xxxxx(). Только в этом случае sqlite3_value_nochange() будет true в методе xUpdate. Если xColumn действительно вызывает один или несколько и ннтерфейсов sqlite3_result_xxxxx(), SQLite понимает это как изменение значения столбца, а вызов sqlite3_value_nochange() к той колонке в xUpdate в xUpdate вернет false.
Могли бы быть один или несколько открытых объектов sqlite3_vtab_cursor в использовании на экземпляре таблицы и возможно даже на строке виртуальной таблицы, когда xUpdate вызван. Внедрение xUpdate должно быть подготовлено к попыткам удалить или изменить строки таблицы из других существующих курсоров. Если виртуальная таблица не может приспособить такие изменения, xUpdate должен возвратить код ошибки.
Метод xUpdate опционален. Если указатель xUpdate в sqlite3_module для виртуальной таблицы NULL, то виртуальная таблица только для чтения.
Стандартный код возврата SQLite.
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
![]() |
int (*xBegin)(sqlite3_vtab *pVTab); Этот метод начинает транзакцию на виртуальной таблице. Этот метод опционален. Указатель xBegin в sqlite3_module может быть NULL. Этот метод всегда сопровождается одним обращением к xCommit или xRollback. Виртуальные транзакции таблицы не вкладываются, таким образом, метод xBegin не будет вызван несколько раз на единственной виртуальной таблице без xCommit или xRollback. Множественные вызовы других методов могут и вероятно будут вызывать промежуточные xBegin и соответствующий xCommit или xRollback. |
![]() |
SQLite использует xBestIndex метод виртуального модуля
таблицы, чтобы определить лучший способ получить доступ к виртуальной
таблице. У xBestIndex метода есть прототип:
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); Ядро SQLite общается с методом xBestIndex, заполняя определенные области структуры sqlite3_index_info и передавая указатель на ту структуру в xBestIndex как второй параметр. xBestIndex заполняет другие области этой структуры, которая формирует ответ. Структура sqlite3_index_info structure похожа на это: struct sqlite3_index_info { /* Inputs */ const int nConstraint; /* Number of entries in aConstraint */ const 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 */ } *const aConstraint; /* Table of WHERE clause constraints */ const int nOrderBy; /* Number of terms in the ORDER BY clause */ const struct sqlite3_index_orderby { int iColumn; /* Column number */ unsigned char desc; /* True for DESC.False for ASC. */ } *const 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 */ } *const 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 */ }; Отметьте предупреждения на поля "estimatedRows", "idxFlags" и colUsed. Эти поля были добавлены с версиями 3.8.2, 3.9.0 SQLite и 3.10.0, соответственно. Любое расширение, которое читает или пишет эти поля, должно сначала проверить, что версия библиотеки SQLite в больше или равна соответствующей версии, возможно, сравнение значения, возвращенного sqlite3_libversion_number() с 3008002, 3009000 и/или 3010000. Результат попытки получить доступ к этим областям в структуре sqlite3_index_info, созданной более старой версией SQLite, не определен. Кроме того, есть некоторые определенные константы: #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT16 #define SQLITE_INDEX_CONSTRAINT_GE32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 #define SQLITE_INDEX_CONSTRAINT_LIKE65/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_GLOB66/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_REGEXP67/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_NE68/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOT 69/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNULL71/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_IS72/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_LIMIT 73/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_OFFSET74/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150/* 3.25.0 and later */ #define SQLITE_INDEX_SCAN_UNIQUE 1/* Scan visits at most 1 row */ Используйте интерфейс sqlite3_vtab_collation(), чтобы найти имя последовательности сопоставления, которая должна использоваться, оценивая i-ое ограничение: const char *sqlite3_vtab_collation(sqlite3_index_info*, int i); Ядро SQLite вызывает xBestIndex, когда это собирает запрос, который включает виртуальную таблицу. Другими словами, SQLite вызывает этот метод, когда это управляет sqlite3_prepare() или эквивалент. Вызывая этот метод, ядро SQLite говорит виртуальной таблице, что должно получить доступ к некоторому подмножеству строк в виртуальной таблице, и это хочет знать самый эффективный способ сделать это. xBestIndex отвечает информацией, которую ядро SQLite может тогда использовать, чтобы провести эффективный поиск виртуальной таблицы. Собирая единственный SQL-запрос, ядро SQLite могло бы вызвать xBestIndex многократно с различными параметрами настройки в sqlite3_index_info. Ядро SQLite тогда выберет комбинацию, которая, кажется, дает лучшую производительность. Прежде, чем вызвать этот метод, ядро SQLite инициализирует экземпляр структуры sqlite3_index_info с информацией о запросе, который в настоящее время пытается обработать. Эта информация происходит, главным образом, из оператора Where или пунктов GROUP BY и ORDER BY запроса, но также и от любого ON или пунктов USING, если запрос это соединение. Информация, которую ядро SQLite предоставляет xBestIndex, содержится в части структуры, которая отмечена как "Inputs". Секция "Outputs" инициализируется к нолю. Информация в структуре sqlite3_index_info эфемерна и может быть переписана или освобождена, как только xBestIndex возвращается. Если xBestIndex должен помнить какую-либо часть sqlite3_index_info, это должно сделать копию. Заметьте, что xBestIndex будут всегда вызван до xFilter, так как idxNum и idxStr следуют из xBestIndex и нужны для xFilter. Однако, нет никакой гарантии, что xFilter вызовут после успешного xBestIndex. xBestIndex нужен для каждого виртуального внедрения таблицы. Главным, что ядро SQLite пытается сообщить виртуальной таблице, являются ограничения, которые доступны, чтобы ограничить количество строк, которые должны быть просмотрены. Массив aConstraint[] содержит один вход для каждого ограничения. Будет точно nConstraint записей в том множестве. Каждое ограничение будет обычно соответствовать термину в операторе Where или в пункте USING или ON, который имеет форму column OP EXPR Здесь "column" колонка в виртуальной таблице, OP оператор вроде "=" или "<", а EXPR это произвольное выражение. Так, например, если оператор Where содержал термин: a = 5 Тогда одно из ограничений было бы на колонке "a" с оператором "=" и выражением "5". У ограничений не должно быть буквального представления оператора Where. Оптимизатор запросов мог бы сделать преобразования к оператору Where, чтобы извлечь столько ограничений, сколько это может. Так, например, если оператор Where содержал что-то вроде этого: x BETWEEN 10 AND 100 AND 999>y Оптимизатор запросов мог бы перевести это на три отдельных ограничения: x >= 10 x <= 100 y < 999 Для каждого такого ограничения поле aConstraint[].iColumn указывает, какая колонка появляется на левой стороне ограничения. Первая колонка виртуальной таблицы это колонка 0. rowid виртуальной таблицы это колонка -1. Поле aConstraint[].op указывает, какой оператор используется. Константы SQLITE_INDEX_CONSTRAINT_* отображают константы целого числа в значениях operator. Колонки происходят в том порядке, в каком они были определены обращением к sqlite3_declare_vtab() в xCreate или xConnect. Скрытые столбцы посчитаны, определяя индекс столбца. Если метод xFindFunction() для виртуальной таблицы определяется, и если xFindFunction() вернет SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, то ограничения могли бы также иметь форму: FUNCTION(column, EXPR) В этом случае значение aConstraint[].op совпадает со значением, возвращенным xFindFunction() для FUNCTION. Массив aConstraint[] содержит информацию обо всех ограничениях, которые относятся к виртуальной таблице. Но некоторые ограничения не могли бы быть применимыми из-за способа, которым таблицы упорядочены в соединении. xBestIndex должен поэтому только рассмотреть ограничения, у которых есть флаг aConstraint[].usable = true. В дополнение к ограничениям оператора Where ядро SQLite также говорит xBestIndex о пункте ORDER BY. В агрегатном запросе ядро SQLite могло бы вставить информацию о пункте GROUP BY вместо информации о пункте ORDER BY, но этот факт не должен иметь никакого отношения к xBestIndex. Если все условия пункта ORDER BY будут колонками в виртуальной таблице, то nOrderBy будет количеством условий в пункте ORDER BY и массив aOrderBy[] определит колонку для каждого термина в порядке order и является ли та колонка ASC или DESC. В SQLite version 3.10.0 (2016-01-06) и позже поле colUsed доступно, чтобы указать, какие поля виртуальной таблицы на самом деле используются подготовленным запросом. Если самая низкая часть colUsed установлена, это означает, что первая колонка используется. Второй самый низкий бит соответствует второй колонке и т. д. Если старшая значащая часть colUsed установлена, это означает, что используются одна или более колонок кроме первых 63 колонок. Если информация об использовании колонки необходима xFilter, то необходимые биты должны быть закодированы в вывод idxNum или idxStr. Для LIKE, GLOB, REGEXP и MATCH значение aConstraint[].iColumn является столбцом виртуальной таблицы, который является левым операндом оператора. Однако, если эти операторы выражаются как вызовы функции вместо операторов, то значение aConstraint[].iColumn ссылается на столбец виртуальной таблицы, который является вторым аргументом той функции: LIKE(EXPR, column) Следовательно, до вызова xBestIndex() следующие две формы эквивалентны: column LIKE EXPR Это специальное поведение рассмотрения второго аргумента функции происходит только для LIKE, GLOB, REGEXP и MATCH. Для всех других функций aConstraint[].iColumn ссылается на первый аргумент функции. Эта специальная функция LIKE, GLOB, REGEXP и MATCH не относится к xFindFunction(). Он выключает левый операнд оператора LIKE, GLOB, REGEXP или MATCH, но исключение первого аргумента эквивалентно вызову функции тех операторов. Когда aConstraint[].op это SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, это указывает, что есть пункт LIMIT или OFFSET в запросе SQL, который использует виртуальную таблицу. У операторов LIMIT и OFFSET нет левого операнда, поэтому когда aConstraint[].op = SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, aConstraint[].iColumn бессмыслено и не должно использоваться. Интерфейс sqlite3_vtab_rhs_value() может использоваться, чтобы попытаться получить доступ к правому операнду ограничения. Однако, значение правого оператора не могло быть известно в то время, когда работает xBestIndex. Значит вызов sqlite3_vtab_rhs_value() успешным быть не может. Обычно правильный операнд ограничения доступен только xBestIndex, если это закодировано как литеральное значение во входе SQL. Если правый операнд будет закодирован как выражение или параметр host, это, вероятно, не будет доступно для xBestIndex. У некоторых операторов, таких как SQLITE_INDEX_CONSTRAINT_ISNULL и SQLITE_INDEX_CONSTRAINT_ISNOTNULL нет правого операнда. Интерфейс sqlite3_vtab_rhs_value() всегда возвращает SQLITE_NOTFOUND для таких операторов. Учитывая всю информацию выше, работа метода xBestIndex это выяснение лучшего способа искать виртуальную таблицу. xBestIndex передает стратегию индексации xFilter методу через поля idxNum и idxStr. Значение idxNum и содержание последовательности idxStr произвольны, насколько ядро SQLite затронуто и могут иметь любое значение, в зависимости от xBestIndex и xFilter. Ядро SQLite просто копирует информацию от xBestIndex к xFilter предполагая только, что последовательность, на которую ссылаются через idxStr, закончена NUL. idxStr может быть последовательностью, полученной из функции выделения памяти SQLite, такой как sqlite3_mprintf(). Если это верно, тогда флаг needToFreeIdxStr должен быть установлен в true так, чтобы ядро SQLite знало, что надо вызвать sqlite3_free() на той последовательности, когда это закончит работу с ней, и таким образом избегать утечки памяти. Значение idxStr может также быть статической постоянной строкой, в этом случае needToFreeIdxStr needToFreeIdxStr=false. Поле estimatedCost должно быть установлено в предполагаемое количество операций по доступу к диску, требуемых, чтобы выполнить этот запрос для виртуальной таблицы. Ядро SQLite будет часто вызывать xBestIndex многократно с различными ограничениями, получать многократные сметы, затем выбирать план запросов, который дает самую низкую оценку. Ядро SQLite инициализирует estimatedCost к очень большому значению до xBestIndex, так что если xBestIndex решает, что текущая комбинация параметров нежелательна, это может оставить поле estimatedCost без изменений, чтобы препятствовать ее использованию. Если текущая версия SQLite 3.8.2 или выше, поле estimatedRows может быть установлено в оценку количества строк, возвращенных предложенным планом запросов. Если это значение явно не установлено, используется оценка по умолчанию в 25 строк. Если текущая версия SQLite 3.9.0 или выше, поле idxFlags может быть установлено в SQLITE_INDEX_SCAN_UNIQUE, чтобы указать, что виртуальная таблица возвратит только ноль или одну строк, заданные входными ограничениями. Опциональные биты поля idxFlags могли бы быть поняты в более поздних версиях SQLite. Массив aConstraintUsage[] содержит один элемент для каждого из ограничений nConstraint во входном разделе структуры sqlite3_index_info. Множество aConstraintUsage[] используется xBestIndex, чтобы сказать ядру, как это использует ограничения. xBestIndex может установить aConstraintUsage[].argvIndex записи в значения больше 0. Точно один вход должен быть установлен в 1, другой к 2, другой в 3 и т. д. EXPR соответствующих ограничений будет тогда передан как параметр argv[] для xFilter. Например, если aConstraint[3].argvIndex = 1, xFilter вызван с argv[0] длч xFilter со значением EXPR ограничения aConstraint[3]. По умолчанию SQLite производит bytecode, который будет проверять все ограничения дважды на каждую строку виртуальной таблицы, чтобы проверить, что они удовлетворены. Если виртуальная таблица может гарантировать, что ограничение будет всегда удовлетворяться, это может попытаться подавить ту перепроверку, установив aConstraintUsage[].omit. Однако, за некоторыми исключениями, это только намек и нет никакой гарантии, что избыточная проверка ограничения будет подавлена. Ключевые пункты:
Если виртуальная таблица произведет строки в порядке, определенном пунктом ORDER BY, то флаг orderByConsumed может быть установлен в true. Если вывод не автоматически в правильном порядке, тогда orderByConsumed должен быть оставлен в его умолчании false. Это укажет ядру SQLite, что должна быть сделана отдельная сортировка данных после того, как они выходят из виртуальной таблицы. Урегулирование orderByConsumed является оптимизацией. Запрос будет всегда получать правильный ответ, если orderByConsumed оставят в его значении по умолчанию (0). Ненужных операций по сортировке можно было бы избежать, придя к более быстрому запросу, если orderByConsumed установлен, но установка orderByConsumed неправильно может привести к неправильному ответу. Предложено, чтобы новые виртуальные внедрения таблицы оставили сброс значения orderByConsumed первоначально, а затем после того, как все остальное, как известно, работает правильно, вернулись и попытались оптимизировать, установив orderByConsumed в соответствующих случаях. Иногда флаг orderByConsumed может быть безопасно установлен, даже если вывод виртуальной таблицы не находится строго в порядке, определенном nOrderBy и aOrderBy. Если интерфейс sqlite3_vtab_distinct() вернет 1 или 2, это указывает, что порядок может быть смягчен. См. документацию относительно sqlite3_vtab_distinct(). xBestIndex должен возвратить SQLITE_OK при успехе. Если какой-либо вид фатальной ошибки происходит, соответствующий код ошибки (например, SQLITE_NOMEM) должен быть возвращен вместо этого. Если xBestIndex вернет SQLITE_CONSTRAINT, это не указывает на ошибку. SQLITE_CONSTRAINT указывает, что конкретная комбинация входных определенных параметров недостаточна для виртуальной таблицы, чтобы сделать ее работу. Это логически то же самое, как урегулирование estimatedCost к бесконечности. Если каждое обращение к xBestIndex для конкретного плана запросов возвратит SQLITE_CONSTRAINT, это означает, что нет никакого пути к виртуальной таблице, который будет безопасно использоваться, и вызов sqlite3_prepare() потерпит неудачу с ошибкой "no query solution". Возвращение SQLITE_CONSTRAINT из xBestIndex полезно для табличных функций, у которых есть обязательные параметры. Если aConstraint[].usable = false для одного из обязательного параметра, то xBestIndex должен возвратить SQLITE_CONSTRAINT. Если обязательное поле не появляется в множестве aConstraint[] вообще, это означает, что соответствующий параметр опущен во входе SQL. В этом случае xBestIndex должен установить сообщение об ошибке в pVTab->zErrMsg и вернуть SQLITE_ERROR. Итак:
Следующий пример лучше иллюстрирует использование SQLITE_CONSTRAINT как возвращаемое значение из xBestIndex: SELECT * FROM realtab, tablevaluedfunc(realtab.x); Предполагая, что первый скрытый столбец "tablevaluedfunc" = "param1", запрос выше семантически эквивалентен этому: SELECT * FROM realtab, tablevaluedfunc WHERE tablevaluedfunc.param1 = realtab.x; Планировщик запроса должен решить между многими возможными внедрениями этого запроса, но два плана в особенности интересны:
xBestIndex будет вызван однажды для каждого из потенциальных планов выше. Для плана 1 флаг aConstraint[].usable для ограничения SQLITE_CONSTRAINT_EQ на колонку param1 будет верен потому, что значение правой стороны для ограничения "param1 = ?" будет известно, так как оно определяется внешним циклом realtab. Но для плана 2 флаг aConstraint[].usable для "param1 = ?" будет false потому, что значение правой стороны определяется внутренним циклом и является таким образом неизвестным. Поскольку param1 это необходимый вход к табличным функциям, xBestIndex вернет SQLITE_CONSTRAINT, когда смотрит план 2, указав, что необходимый вход отсутствует. Это вынуждает планировщик запроса выбрать план 1. |
![]() |
int (*xClose)(sqlite3_vtab_cursor*);xClose закрывает курсор, ранее открытый xOpen. Ядро SQLite будет всегда вызывать xClose однажды для каждого курсора, открытого, используя xOpen. Этот метод должен высвободить все ресурсы, ассигнованные соответствующим обращением xOpen. Процедуру не вызовут снова, даже если она возвратит ошибку. Ядро SQLite не будет использовать sqlite3_vtab_cursor снова после того, как это будет закрыто. |
![]() |
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int N);Ядро SQLite вызывает этот метод, чтобы найти значение для N-й колонки текущей строки. N основан на ноле, таким образом, первая колонка пронумерована 0. xColumn может возвратить свой результат назад SQLite использованием одного из следующих интерфейсов:
Если реализация метода xColumn не вызывает ни одну из функций выше, значение колонки по умолчанию SQL NULL. Чтобы поднять ошибку, xColumn должен использовать один из методов result_text(), чтобы установить текст сообщения об ошибке, затем возвратить соответствующий код ошибки. xColumn должен возвратить SQLITE_OK при успехе. xColumn требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xCommit)(sqlite3_vtab *pVTab); Этот метод заставляет транзакцию виртуальной таблицы передавать. Это опциональный метод. Указатель xCommit в sqlite3_module может быть NULL. Обращение к этому методу всегда следует за предшествующим обращением к xBegin и xSync. |
![]() |
int (*xConnect) (sqlite3*, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr);Метод xConnect очень похож на xCreate. Это имеет те же самые параметры и строит новую структуру sqlite3_vtab точно так же, как xCreate. И это должно также вызвать sqlite3_declare_vtab() подобно xCreate. Это должно также сделать все те же самые вызовы sqlite3_vtab_config(), как xCreate. Различие в том, что xConnect вызывают, чтобы установить новую связь с существующей виртуальной таблицей, тогда как xCreate вызывают, чтобы составить новую виртуальную таблицу с нуля. xCreate и xConnect отличаются только когда у виртуальной таблицы есть некоторое запоминающее устройство, которое должно быть инициализировано в первый раз, когда виртуальная таблица составлена. xCreate создает и инициализирует запоминающее устройство. xConnect просто соединяется с существующим запоминающим устройством. Когда xCreate и xConnect то же самое, таблица это виртуальная таблица. Как пример, рассмотрите виртуальное внедрение таблицы, которое обеспечивает доступ только для чтения к существующим файлам comma-separated-value (CSV) на диске. Нет никакого запоминающего устройства, которое должно быть создано или инициализировано для такого виртуальной таблицы (так как файлы CSV уже существуют на диске), так что методы xCreate и xConnect будут идентичны для того модуля. Другой пример это виртуальная таблица, которая осуществляет полнотекстовый индекс. xCreate должен создать и инициализировать структуры данных, чтобы хранить словарь и управляющие списки для этого индекса. xConnect с другой стороны должен определить только местонахождение и использовать существующий словарь и списки, которые были созданы предшествующим обращением xCreate. xConnect должен вернуть SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если не успешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если что-то пошло не так. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить пространство, используя sqlite3_free(), после того, как об ошибке сообщили приложению. xConnect требуется для каждого виртуального внедрения таблицы, хотя указатели xCreate и xConnect объекта sqlite3_module могут указать на ту же самую функцию, если виртуальная таблица не должна инициализировать запоминающее устройство. |
![]() |
int (*xCreate) (sqlite3 *db, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr); Метод xCreate вызывают, чтобы создать новый экземпляр виртуальной таблицы в ответ на CREATE VIRTUAL TABLE. Если метод xCreate пропущен (указатель NULL), виртуальная таблица это одноименно-единственная виртуальная таблица. Параметр db это указатель на соединение с базой данных SQLite, которое выполняет CREATE VIRTUAL TABLE. pAux это копия указателя данных клиента, который был четвертым аргументом вызова sqlite3_create_module() или sqlite3_create_module_v2(), который зарегистрировал виртуальный модуль таблицы. Параметр argv это массив указателей на законченные null последовательности. Первая последовательность, argv[0], является именем вызываемого модуля. Имя модуля это имя, обеспеченное как второй аргумент sqlite3_create_module() и как аргумент пункта USING в CREATE VIRTUAL TABLE. Вторым, argv[1], является название базы данных, в которой составляется новая виртуальная таблица. Имя базы данных "main" для основной базы данных, "temp" для базы данных TEMP или имя, данное в конце запроса ATTACH для приложенных баз данных. Третий элемент множества, argv[2], является названием новой виртуальной таблицы, как определено после ключевого слова TABLE в CREATE VIRTUAL TABLE. Если существуют, четвертая и последующие последовательности в массиве argv[] сообщают об аргументах имени модуля в CREATE VIRTUAL TABLE. Работа по этому методу состоит в том, чтобы построить новый виртуальный объект таблицы (объект sqlite3_vtab) и возвратить указатель на него в *ppVTab. Как часть задачи создания новой структуры sqlite3_vtab, этот метод должен вызвать sqlite3_declare_vtab(), чтобы сказать ядру SQLite о колонках и типах данных в виртуальной таблице. sqlite3_declare_vtab() API имеет следующий прототип: int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable) Первым аргументом sqlite3_declare_vtab() должен быть тот же самый указатель соединения с базой данных, как первый параметр этого метода. Второй аргумент sqlite3_declare_vtab() должен быть законченной нолем строкой UTF-8, которая содержит правильно построенный запрос CREATE TABLE, который определяет колонки в виртуальной таблице и их типы данных. Имя таблицы в этом CREATE TABLE проигнорировано, как все ограничения. Только запрос имен столбцов и типов данных. Последовательность CREATE TABLE не должна быть проведена в постоянной памяти. Последовательность может быть освобождена и/или снова использована, как только завершится sqlite3_declare_vtab(). xConnect может также произвольно просить специальные функции для виртуальной таблицы, сделав один или несколько вызовов интерфейса sqlite3_vtab_config(): int sqlite3_vtab_config(sqlite3 *db, int op, ...); Вызов sqlite3_vtab_config() опционален. Но для максимальной безопасности рекомендуется, чтобы виртуальные внедрения таблицы вызвали "sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY)", если виртуальную таблицу не будет использовать изнутри триггеров или обзоров. xCreate не должен инициализировать поля pModule, nRef и zErrMsg объекта sqlite3_vtab. Ядро SQLite будет заботиться об этой работе. xCreate должен возвратить SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если неуспешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если есть проблема. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить место, используя sqlite3_free() после того, как об ошибке сообщили приложению. Если опущен xCreate (оставленный как NULL), виртуальная таблица это одноименно-единственная виртуальная таблица. Новые экземпляры виртуальной таблицы не могут быть созданы, используя CREATE VIRTUAL TABLE, а виртуальная таблица может использоваться только через имя модуля. Обратите внимание на то, что версии SQLite до 3.9.0 (2015-10-14) не понимают одноименно-единственные виртуальные таблицы и будет segfault, если предпринята попытка CREATE VIRTUAL TABLE на одноименно-единственной виртуальной таблице, потому что метод xCreate не был проверен на пустой указатель. Если метод xCreate тот же самый указатель, как xConnect, это указывает, что виртуальная таблица не должна инициализировать запоминающее устройство. Такая виртуальная таблица может использоваться в качестве одноименной виртуальной таблицы, в качестве названной виртуальной таблицы, используя CREATE VIRTUAL TABLE, или обоими способами. Если тип данных колонки содержит специальное ключевое слово "HIDDEN" (в какой-либо комбинации прописных и строчных букв), ключевое слово опущено от имени типа данных колонки, а колонка отмечена как скрытый столбец внутренне. Скрытый столбец отличается от нормальной колонки в трех отношениях:
Например, если следующий SQL передается sqlite3_declare_vtab(): CREATE TABLE x(a HIDDEN VARCHAR(12), b INTEGER, c INTEGER Hidden); Тогда виртуальная таблица была бы составлена с двумя скрытыми столбцами с типами данных "VARCHAR(12)" и "INTEGER". Использование в качестве примера скрытых столбцов может быть замечено в виртуальном внедрении таблицы FTS3, где каждая виртуальная таблица FTS содержит скрытый столбец FTS, который используется, чтобы передать информацию от виртуальной таблицы во вспомогательные функции FTS и оператору MATCH FTS. Виртуальная таблица, которая содержит скрытые столбцы, может использоваться как табличная функция в пункте FROM оператора SELECT. Аргументы табличной функции становятся ограничениями на столбцах HIDDEN виртуальной таблицы. Например, расширение "generate_series" (файл ext/misc/series.c дерева исходных текстов) осуществляет одноименную виртуальную таблицу со следующей схемой: CREATE TABLE generate_series(value, start HIDDEN, stop HIDDEN, step HIDDEN); Метод sqlite3_module.xBestIndex во внедрении этой таблицы проверяет на ограничения равенства столбцы HIDDEN и использует их как входные параметры, чтобы определить диапазон вывода integer "value", чтобы произвести. Разумные значения по умолчанию используются для любых неограниченных колонок. Например, чтобы перечислить все целые числа между 5 и 50: SELECT value FROM generate_series(5,50); Предыдущий запрос эквивалентен следующему: SELECT value FROM generate_series WHERE start=5 AND stop=50; Аргументы на виртуальном имени таблицы соответствуют скрытым столбцам в порядке. Количество аргументов может быть меньше, чем количество скрытых столбцов, в этом случае последние скрытые столбцы не ограничены. Однако, будет ошибка, если есть больше аргументов, чем в виртуальной таблице есть скрытых столбцов. Начиная с SQLite version 3.14.0 (2016-08-08), CREATE TABLE, который передается в sqlite3_declare_vtab(), может содержать WITHOUT ROWID. Это полезно для случаев, где виртуальные строки таблицы не могут быть легко отображены в уникальные целые числа. Запрос CREATE TABLE, который включает WITHOUT ROWID, должен определить одну или более колонок как PRIMARY KEY. Каждая колонка PRIMARY KEY должна индивидуально быть NOT NULL, а все колонки для каждой строки должны быть коллективно уникальными. Обратите внимание на то, что SQLite не проводит в жизнь PRIMARY KEY для виртуальной таблицы WITHOUT ROWID. Осуществление это ответственность основного виртуального внедрения таблицы. Но SQLite действительно предполагает, что ограничение PRIMARY KEY действительно, что определенные колонки UNIQUE и NOT NULL, и использует это предположение, чтобы оптимизировать запросы для виртуальной таблицы. Столбец rowid недоступен в виртуальной таблице (конечно) WITHOUT ROWID. Метод xUpdate был первоначально разработан вокруг наличия ROWID как единственного значения. xUpdate был расширен, чтобы приспособить произвольный PRIMARY KEY вместо ROWID, но PRIMARY KEY все еще должен быть только одной колонкой. Поэтому SQLite отклонит любую виртуальную таблицу WITHOUT ROWID, у которой есть больше, чем одна колонка PRIMARY KEY и не-NULL метод xUpdate. |
![]() |
int (*xDestroy)(sqlite3_vtab *pVTab);Этот метод закрывает связь с виртуальной таблицей, точно так же, как xDisconnect, и это также разрушает внедрение базовой таблицы. Этот метод отменяет работу xCreate. xDisconnect вызывают каждый раз, когда соединение с базой данных, которое использует виртуальную таблицу, закрывается. Метод xDestroy вызывают только когда запрос DROP TABLE выполняется для виртуальной таблицы. Метод xDestroy требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы. |
![]() |
int (*xDisconnect)(sqlite3_vtab *pVTab);Этот метод освобождает связь с виртуальной таблицей. Только объект sqlite3_vtab разрушен. Виртуальную таблицу не разрушают, любое запоминающее устройство, связанное с виртуальной таблицей, сохраняется. Этот метод отменяет работу xConnect. Этот метод деструктор для связи с виртуальной таблицей. Противопоставьте этот метод xDestroy. xDestroy это деструктор для всей виртуальной таблицы. Метод xDisconnect требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы. |
![]() |
int (*xEof)(sqlite3_vtab_cursor*);Метод xEof должен возвратить false (0), если указанный курсор в настоящее время указывает на действительную строку данных, иначе true (не 0). Этот метод немедленно вызывает движок SQL после каждого xFilter и xNext. Метод xEof требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xFilter) (sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv);Этот метод начинает поиск виртуальной таблицы. Первый аргумент задает курсор, открытый xOpen. Следующие два аргумента определяют конкретный индекс поиска, ранее выбранный xBestIndex. Определенные значения idxNum и idxStr неважны, xFilter и xBestIndex договариваются, каково то значение. Функция xBestIndex, возможно, запросит значения определенных выражений, используя aConstraintUsage[].argvIndex в структуре sqlite3_index_info. Эти значения передаются xFilter через использование argc и argv. Если виртуальная таблица содержит одну или несколько строк, которые соответствуют критериям поиска, то курсор должен быть левой точкой в первой строке. Последующие обращения к xEof должны вернуть false (0). Если нет никакого соответствия строк, курсор нужно оставить в состоянии, которое заставит xEof возвращать true (не 0). Движок SQLite будет использовать методы xColumn и xRowid, чтобы получить доступ к тому содержанию строки. Метод xNext будет использоваться, чтобы продвинуться к следующей строке. Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит. Метод xFilter требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xFindFunction) (sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg);Этот метод вызывают во время sqlite3_prepare(), чтобы дать виртуальному внедрению таблицы возможность перегрузить функции. Этот метод может быть установлен в NULL, в этом случае, никакая перегрузка не происходит. Когда функция использует колонку от виртуальной таблицы как первый аргумент, этот метод вызывают, чтобы видеть, хотела ли виртуальная таблица перегрузить функцию. Первые три параметра это входы: виртуальная таблица, количество аргументов функции и имя функции. Если никакая перегрузка не желаема, этот метод возвращает 0. Чтобы перегрузить функцию, этот метод вписывает в новую реализацию функции *pxFunc, вписывает в пользовательские данные *ppArg и возвращает 1 или число между SQLITE_INDEX_CONSTRAINT_FUNCTION и 255. Исторически возвращаемое значение xFindFunction() было нолем или единицей. Ноль означает, что функция не перегружена, единица подразумевает, что это перегрузка. Способность к возвращаемым значениям SQLITE_INDEX_CONSTRAINT_FUNCTION или больше была добавлена в версии 3.25.0 (2018-09-15). Если xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, это значит, что функция берет два аргумента, функция может использоваться в качестве булева значения в операторе Where запроса и что виртуальная таблица в состоянии эксплуатировать ту функцию, чтобы ускорить результат запроса. Когда xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, возвращенное значение становится значением sqlite3_index_info.aConstraint.op для одного из ограничений, переданных в xBestIndex(). Первый аргумент функции это колонка, определенная полем aConstraint[].iColumn ограничения. Второй аргумент функции это значение, которое будет передано в xFilter() (если задано aConstraintUsage[].argvIndex) или значение, возвращенное из sqlite3_vtab_rhs_value(). Модуль Geopoly это пример виртуальной таблицы, который использует SQLITE_INDEX_CONSTRAINT_FUNCTION, чтобы улучшить работу. Метод xFindFunction() для Geopoly вернет SQLITE_INDEX_CONSTRAINT_FUNCTION для функции geopoly_overlap() SQL и SQLITE_INDEX_CONSTRAINT_FUNCTION+1 SQL-функции geopoly_within(). Это разрешает оптимизации поиска для таких запросов, как: SELECT * FROM geopolytab WHERE geopoly_overlap(_shape, $query_polygon); SELECT * FROM geopolytab WHERE geopoly_within(_shape, $query_polygon); Обратите внимание на то, что infix-функции (LIKE, GLOB, REGEXP и MATCH) полностью изменяют порядок их аргументов. Так "like(A,B)" обычно работала бы как "B like A". Однако, xFindFunction() всегда смотрит крайний левый аргумент, но не первый логический аргумент. Следовательно, для формы "B like A" SQLite смотрит на левый операнд "B" и если тот операнд столбец виртуальной таблицы, он вызывает метод xFindFunction() на той виртуальной таблице. Но если форма "like(A,B)" используется вместо этого, то SQLite проверяет термин, чтобы видеть, является ли это колонкой виртуальной таблицы, и если так это вызывает метод xFindFunction() для колонки A виртуальной таблицы. Указатель функции, возвращенный этим установленным порядком, должен быть действительным для целой жизни объекта sqlite3_vtab, данного в первом параметре. |
![]() |
int (*xNext) (sqlite3_vtab_cursor*);Метод xNext переводит виртуальный курсор таблицы к следующей строке набора результатов, инициированного xFilter. Если курсор уже указывает на последнюю строку, когда это вызывают, то курсор больше не указывает на действительные данные, последующее обращение к методу xEof должно возвратить true (не 0). Если курсор успешно продвинут к другой строке содержания, то последующие обращения к xEof должны вернуть false (0). Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит. Метод xNext требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);Метод xOpen создает новый курсор, используемый для доступа (чтение и/или запись) к виртуальной таблице. Успешный вызов этого метода ассигнует память для sqlite3_vtab_cursor (или подкласс), инициализирует новый объект и сделает *ppCursor указателем на новый объект. Успешный вызов тогда возвращает SQLITE_OK. Для каждого успешного вызова этого метода ядро SQLite позже вызовет xClose, чтобы разрушить ассигнованный курсор. xOpen не должен инициализировать поле pVtab структуры sqlite3_vtab_cursor. Ядро SQLite будет заботиться об этой работе автоматически. Виртуальное внедрение таблицы должно быть в состоянии поддержать произвольное число одновременно открытых курсоров. Когда первоначально открыт, курсор находится в неопределенном состоянии. Ядро SQLite вызовет метод xFilter на курсоре до любой попытки поместить его куда-то или читать из курсора. Метод xOpen требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);Этот метод предоставляет уведомление, что виртуальной таблице дадут новое имя. Если этот метод возвращает SQLITE_OK, SQLite переименовывает таблицу. Если этот метод возвращает код ошибки, переименование предотвращено. Метод xRename опционален. Если опущен, то виртуальная таблица не может быть переименована, используя ALTER TABLE RENAME. PRAGMA legacy_alter_table позволен до вызова этого метода, значение для legacy_alter_table восстановлено после того, как этот метод заканчивается. Это необходимо для правильной работы таблиц, которые используют теневые таблицы, где теневые таблицы должны быть переименованы, чтобы соответствовать новому виртуальному имени таблицы. Если legacy_alter_format будет выключен, то метод xConnect будет вызван для виртуальной таблицы каждый раз, когда xRename пытается изменить название теневой таблицы. |
![]() |
int (*xRollback)(sqlite3_vtab *pVTab);Этот метод вызывает отмену транзакции виртуальной таблицы. Этот метод опционален. Указатель xRollback в sqlite3_module может быть NULL. Обращение к этому методу всегда следует за предшествующим обращением к xBegin. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xRowid) (sqlite3_vtab_cursor *pCur, sqlite_int64 *pRowid);Успешный вызов этого метода заставит *pRowid быть заполненным rowid строки, на которую в настоящее время указывает виртуальный курсор таблицы pCur. Этот метод возвращает SQLITE_OK при успехе. Это возвращает соответствующий код ошибки при неудаче. Метод xRowid требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xSync) (sqlite3_vtab *pVTab);Этот метод сигнализирует о начале двухфазной фиксации на виртуальной таблице. Этот метод дополнительный. Указатель xSync в sqlite3_module может быть NULL. Этот метод вызван только после xBegin и до xCommit или xRollback. Чтобы осуществить двухфазную фиксацию, метод xSync на всех виртуальных таблицах вызван до xCommit на любой виртуальной таблице. Если какой-либо из xSync терпит неудачу, вся транзакция отменяется. |
![]() |
int (*xUpdate) (sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid);Все изменения виртуальной таблицы внесены, используя метод xUpdate. Этот метод может использоваться, чтобы вставить, удалить или обновить. Параметр argc определяет количество записей во множестве argv. Значение argc 1 для чистого удаления или N+2 для вставки или замены, где N это количество колонок в таблице. В предыдущем предложении N включает любые скрытые столбцы. Каждая запись argv будет иметь значение не NULL в C, но может содержать значение SQL NULL. Другими словами, всегда верно что argv[i]!=0 для i от 0 до argc-1. Однако, могло бы иметь место sqlite3_value_type(argv[i])==SQLITE_NULL. Параметр argv[0] это rowid строки, которая будет удалена. Если argv[0] это SQL NULL, никакое удаление не происходит. Параметр argv[1] это rowid новой строки, которая будет вставлена в виртуальную таблицу. Если argv[1] это SQL NULL, внедрение должно выбрать rowid для недавно вставленной строки. Последующие записи argv[] содержат значения колонок виртуальной таблицы в порядке, в котором были объявлены колонки. Количество колонок будет соответствовать декларации таблицы, которую метод xConnect или xCreate сделал использованием sqlite3_declare_vtab(). Все скрытые столбцы включены. Делая вставку без rowid (argc>1, argv[1] = SQL NULL), на виртуальной таблице, которая использует ROWID (но не на WITHOUT ROWID), внедрение должно установить *pRowid в rowid недавно вставленной строки, это станет значением, возвращенным функцией sqlite3_last_insert_rowid(). Устанавливание этого значения во всех других случаях является безопасным, движок SQLite игнорирует *pRowid возвращаемое значение, если argc == 1 или argv[1] не является NULL SQL. Каждое обращение к xUpdate попадет в один из случаев, показанных ниже. Ссылки на argv[i] обозначают SQL-значение в объекте argv[i], но не сам объект argv[i].
Метод xUpdate должен возвратить SQLITE_OK если и только если это успешно. Если неудача происходит, xUpdate должен возвратить соответствующий код ошибки. При неудаче элемент pVTab->zErrMsg может произвольно быть заменен текстом сообщения об ошибке, сохраненным в памяти, ассигнованной от SQLite через функции вроде sqlite3_mprintf() или sqlite3_malloc(). Если xUpdate нарушает некоторое ограничение виртуальной таблицы (включая, но не ограничиваясь попытку сохранить значение неверного типа данных, сохранить значение, которое является слишком большим или слишком маленьким, или изменить значение только для чтения), xUpdate должен потерпеть неудачу с соответствующим кодом ошибки. Если xUpdate выполняет UPDATE, то sqlite3_value_nochange(X) может использоваться, чтобы обнаружить, какие колонки виртуальной таблицы были на самом деле изменены запросом UPDATE. Интерфейс sqlite3_value_nochange(X) вернет true для колонок, которые не изменяются. На каждом UPDATE SQLite сначала вызовет xColumn отдельно для каждой неизменной колонки в таблице, чтобы получить значение для той колонки. xColumn может проверить, неизменна ли колонка на уровне SQL через sqlite3_vtab_nochange(). Если xColumn видит, что колонка не изменяется, это должно возвратиться, не устанавливая результат, используя один из интерфейсов sqlite3_result_xxxxx(). Только в этом случае sqlite3_value_nochange() будет true в методе xUpdate. Если xColumn действительно вызывает один или несколько и ннтерфейсов sqlite3_result_xxxxx(), SQLite понимает это как изменение значения столбца, а вызов sqlite3_value_nochange() к той колонке в xUpdate в xUpdate вернет false. Могли бы быть один или несколько открытых объектов sqlite3_vtab_cursor в использовании на экземпляре таблицы и возможно даже на строке виртуальной таблицы, когда xUpdate вызван. Внедрение xUpdate должно быть подготовлено к попыткам удалить или изменить строки таблицы из других существующих курсоров. Если виртуальная таблица не может приспособить такие изменения, xUpdate должен возвратить код ошибки. Метод xUpdate опционален. Если указатель xUpdate в sqlite3_module для виртуальной таблицы NULL, то виртуальная таблица только для чтения. |
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite
Методы интерфейса ISQLiteNativeModule упоминаются ниже. Для полного списка участников интерфейса ISQLiteNativeModule посмотрите Члены ISQLiteNativeModule.
![]() |
int (*xBegin) (sqlite3_vtab *pVTab);Этот метод начинает транзакцию на виртуальной таблице. Этот метод опционален. Указатель xBegin в sqlite3_module может быть NULL. Этот метод всегда сопровождается одним обращением к xCommit или xRollback. Виртуальные транзакции таблицы не вкладываются, таким образом, метод xBegin не будет вызван несколько раз на единственной виртуальной таблице без xCommit или xRollback. Множественные вызовы других методов могут и вероятно будут вызывать промежуточные xBegin и соответствующий xCommit или xRollback. |
![]() |
SQLite использует метод xBestIndex виртуального модуля
таблицы, чтобы определить лучший способ получить доступ к виртуальной
таблице. У xBestIndex метода есть прототип:
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);Ядро SQLite общается с методом xBestIndex, заполняя определенные области структуры sqlite3_index_info и передавая указатель на ту структуру в xBestIndex как второй параметр. xBestIndex заполняет другие области этой структуры, которая формирует ответ. Структура sqlite3_index_info structure похожа на это: struct sqlite3_index_info { /* Inputs */ const int nConstraint; /* Number of entries in aConstraint */ const 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 */ } *const aConstraint; /* Table of WHERE clause constraints */ const int nOrderBy; /* Number of terms in the ORDER BY clause */ const struct sqlite3_index_orderby { int iColumn; /* Column number */ unsigned char desc; /* True for DESC.False for ASC. */ } *const 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 */ } *const 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 */ }; Отметьте предупреждения на поля "estimatedRows", "idxFlags" и colUsed. Эти поля были добавлены с версиями 3.8.2, 3.9.0 SQLite и 3.10.0, соответственно. Любое расширение, которое читает или пишет эти поля, должно сначала проверить, что версия библиотеки SQLite в больше или равна соответствующей версии, возможно, сравнение значения, возвращенного sqlite3_libversion_number() с 3008002, 3009000 и/или 3010000. Результат попытки получить доступ к этим областям в структуре sqlite3_index_info, созданной более старой версией SQLite, не определен. Кроме того, есть некоторые определенные константы: #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT16 #define SQLITE_INDEX_CONSTRAINT_GE32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 #define SQLITE_INDEX_CONSTRAINT_LIKE65/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_GLOB66/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_REGEXP67/* 3.10.0 and later */ #define SQLITE_INDEX_CONSTRAINT_NE68/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOT 69/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_ISNULL71/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_IS72/* 3.21.0 and later */ #define SQLITE_INDEX_CONSTRAINT_LIMIT 73/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_OFFSET74/* 3.38.0 and later */ #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150/* 3.25.0 and later */ #define SQLITE_INDEX_SCAN_UNIQUE 1/* Scan visits at most 1 row */ Используйте интерфейс sqlite3_vtab_collation(), чтобы найти имя последовательности сопоставления, которая должна использоваться, оценивая i-ое ограничение: const char *sqlite3_vtab_collation(sqlite3_index_info*, int i); Ядро SQLite вызывает xBestIndex, когда это собирает запрос, который включает виртуальную таблицу. Другими словами, SQLite вызывает этот метод, когда это управляет sqlite3_prepare() или эквивалент. Вызывая этот метод, ядро SQLite говорит виртуальной таблице, что должно получить доступ к некоторому подмножеству строк в виртуальной таблице, и это хочет знать самый эффективный способ сделать это. xBestIndex отвечает информацией, которую ядро SQLite может тогда использовать, чтобы провести эффективный поиск виртуальной таблицы. Собирая единственный SQL-запрос, ядро SQLite могло бы вызвать xBestIndex многократно с различными параметрами настройки в sqlite3_index_info. Ядро SQLite тогда выберет комбинацию, которая, кажется, дает лучшую производительность. Прежде, чем вызвать этот метод, ядро SQLite инициализирует экземпляр структуры sqlite3_index_info с информацией о запросе, который в настоящее время пытается обработать. Эта информация происходит, главным образом, из оператора Where или пунктов GROUP BY и ORDER BY запроса, но также и от любого ON или пунктов USING, если запрос это соединение. Информация, которую ядро SQLite предоставляет xBestIndex, содержится в части структуры, которая отмечена как "Inputs". Секция "Outputs" инициализируется к нолю. Информация в структуре sqlite3_index_info эфемерна и может быть переписана или освобождена, как только xBestIndex возвращается. Если xBestIndex должен помнить какую-либо часть sqlite3_index_info, это должно сделать копию. Заметьте, что xBestIndex будут всегда вызван до xFilter, так как idxNum и idxStr следуют из xBestIndex и нужны для xFilter. Однако, нет никакой гарантии, что xFilter вызовут после успешного xBestIndex. xBestIndex нужен для каждого виртуального внедрения таблицы. Главным, что ядро SQLite пытается сообщить виртуальной таблице, являются ограничения, которые доступны, чтобы ограничить количество строк, которые должны быть просмотрены. Массив aConstraint[] содержит один вход для каждого ограничения. Будет точно nConstraint записей в том множестве. Каждое ограничение будет обычно соответствовать термину в операторе Where или в пункте USING или ON, который имеет форму column OP EXPR Здесь "column" колонка в виртуальной таблице, OP оператор вроде "=" или "<", а EXPR это произвольное выражение. Так, например, если оператор Where содержал термин: a = 5 Тогда одно из ограничений было бы на колонке "a" с оператором "=" и выражением "5". У ограничений не должно быть буквального представления оператора Where. Оптимизатор запросов мог бы сделать преобразования к оператору Where, чтобы извлечь столько ограничений, сколько это может. Так, например, если оператор Where содержал что-то вроде этого: x BETWEEN 10 AND 100 AND 999>y Оптимизатор запросов мог бы перевести это на три отдельных ограничения: x >= 10 x <= 100 y < 999 Для каждого такого ограничения поле aConstraint[].iColumn указывает, какая колонка появляется на левой стороне ограничения. Первая колонка виртуальной таблицы это колонка 0. rowid виртуальной таблицы это колонка -1. Поле aConstraint[].op указывает, какой оператор используется. Константы SQLITE_INDEX_CONSTRAINT_* отображают константы целого числа в значениях operator. Колонки происходят в том порядке, в каком они были определены обращением к sqlite3_declare_vtab() в xCreate или xConnect. Скрытые столбцы посчитаны, определяя индекс столбца. Если метод xFindFunction() для виртуальной таблицы определяется, и если xFindFunction() вернет SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, то ограничения могли бы также иметь форму: FUNCTION(column, EXPR) В этом случае значение aConstraint[].op совпадает со значением, возвращенным xFindFunction() для FUNCTION. Массив aConstraint[] содержит информацию обо всех ограничениях, которые относятся к виртуальной таблице. Но некоторые ограничения не могли бы быть применимыми из-за способа, которым таблицы упорядочены в соединении. xBestIndex должен поэтому только рассмотреть ограничения, у которых есть флаг aConstraint[].usable = true. В дополнение к ограничениям оператора Where ядро SQLite также говорит xBestIndex о пункте ORDER BY. В агрегатном запросе ядро SQLite могло бы вставить информацию о пункте GROUP BY вместо информации о пункте ORDER BY, но этот факт не должен иметь никакого отношения к xBestIndex. Если все условия пункта ORDER BY будут колонками в виртуальной таблице, то nOrderBy будет количеством условий в пункте ORDER BY и массив aOrderBy[] определит колонку для каждого термина в порядке order и является ли та колонка ASC или DESC. В SQLite version 3.10.0 (2016-01-06) и позже поле colUsed доступно, чтобы указать, какие поля виртуальной таблицы на самом деле используются подготовленным запросом. Если самая низкая часть colUsed установлена, это означает, что первая колонка используется. Второй самый низкий бит соответствует второй колонке и т. д. Если старшая значащая часть colUsed установлена, это означает, что используются одна или более колонок кроме первых 63 колонок. Если информация об использовании колонки необходима xFilter, то необходимые биты должны быть закодированы в вывод idxNum или idxStr. Для LIKE, GLOB, REGEXP и MATCH значение aConstraint[].iColumn является столбцом виртуальной таблицы, который является левым операндом оператора. Однако, если эти операторы выражаются как вызовы функции вместо операторов, то значение aConstraint[].iColumn ссылается на столбец виртуальной таблицы, который является вторым аргументом той функции: LIKE(EXPR, column) Следовательно, до вызова xBestIndex() следующие две формы эквивалентны: column LIKE EXPR Это специальное поведение рассмотрения второго аргумента функции происходит только для LIKE, GLOB, REGEXP и MATCH. Для всех других функций aConstraint[].iColumn ссылается на первый аргумент функции. Эта специальная функция LIKE, GLOB, REGEXP и MATCH не относится к xFindFunction(). Он выключает левый операнд оператора LIKE, GLOB, REGEXP или MATCH, но исключение первого аргумента эквивалентно вызову функции тех операторов. Когда aConstraint[].op это SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, это указывает, что есть пункт LIMIT или OFFSET в запросе SQL, который использует виртуальную таблицу. У операторов LIMIT и OFFSET нет левого операнда, поэтому когда aConstraint[].op = SQLITE_INDEX_CONSTRAINT_LIMIT или SQLITE_INDEX_CONSTRAINT_OFFSET, aConstraint[].iColumn бессмыслено и не должно использоваться. Интерфейс sqlite3_vtab_rhs_value() может использоваться, чтобы попытаться получить доступ к правому операнду ограничения. Однако, значение правого оператора не могло быть известно в то время, когда работает xBestIndex. Значит вызов sqlite3_vtab_rhs_value() успешным быть не может. Обычно правильный операнд ограничения доступен только xBestIndex, если это закодировано как литеральное значение во входе SQL. Если правый операнд будет закодирован как выражение или параметр host, это, вероятно, не будет доступно для xBestIndex. У некоторых операторов, таких как SQLITE_INDEX_CONSTRAINT_ISNULL и SQLITE_INDEX_CONSTRAINT_ISNOTNULL нет правого операнда. Интерфейс sqlite3_vtab_rhs_value() всегда возвращает SQLITE_NOTFOUND для таких операторов. Учитывая всю информацию выше, работа метода xBestIndex это выяснение лучшего способа искать виртуальную таблицу. xBestIndex передает стратегию индексации xFilter методу через поля idxNum и idxStr. Значение idxNum и содержание последовательности idxStr произвольны, насколько ядро SQLite затронуто и могут иметь любое значение, в зависимости от xBestIndex и xFilter. Ядро SQLite просто копирует информацию от xBestIndex к xFilter предполагая только, что последовательность, на которую ссылаются через idxStr, закончена NUL. idxStr может быть последовательностью, полученной из функции выделения памяти SQLite, такой как sqlite3_mprintf(). Если это верно, тогда флаг needToFreeIdxStr должен быть установлен в true так, чтобы ядро SQLite знало, что надо вызвать sqlite3_free() на той последовательности, когда это закончит работу с ней, и таким образом избегать утечки памяти. Значение idxStr может также быть статической постоянной строкой, в этом случае needToFreeIdxStr needToFreeIdxStr=false. Поле estimatedCost должно быть установлено в предполагаемое количество операций по доступу к диску, требуемых, чтобы выполнить этот запрос для виртуальной таблицы. Ядро SQLite будет часто вызывать xBestIndex многократно с различными ограничениями, получать многократные сметы, затем выбирать план запросов, который дает самую низкую оценку. Ядро SQLite инициализирует estimatedCost к очень большому значению до xBestIndex, так что если xBestIndex решает, что текущая комбинация параметров нежелательна, это может оставить поле estimatedCost без изменений, чтобы препятствовать ее использованию. Если текущая версия SQLite 3.8.2 или выше, поле estimatedRows может быть установлено в оценку количества строк, возвращенных предложенным планом запросов. Если это значение явно не установлено, используется оценка по умолчанию в 25 строк. Если текущая версия SQLite 3.9.0 или выше, поле idxFlags может быть установлено в SQLITE_INDEX_SCAN_UNIQUE, чтобы указать, что виртуальная таблица возвратит только ноль или одну строк, заданные входными ограничениями. Опциональные биты поля idxFlags могли бы быть поняты в более поздних версиях SQLite. Массив aConstraintUsage[] содержит один элемент для каждого из ограничений nConstraint во входном разделе структуры sqlite3_index_info. Множество aConstraintUsage[] используется xBestIndex, чтобы сказать ядру, как это использует ограничения. xBestIndex может установить aConstraintUsage[].argvIndex записи в значения больше 0. Точно один вход должен быть установлен в 1, другой к 2, другой в 3 и т. д. EXPR соответствующих ограничений будет тогда передан как параметр argv[] для xFilter. Например, если aConstraint[3].argvIndex = 1, xFilter вызван с argv[0] длч xFilter со значением EXPR ограничения aConstraint[3]. По умолчанию SQLite производит bytecode, который будет проверять все ограничения дважды на каждую строку виртуальной таблицы, чтобы проверить, что они удовлетворены. Если виртуальная таблица может гарантировать, что ограничение будет всегда удовлетворяться, это может попытаться подавить ту перепроверку, установив aConstraintUsage[].omit. Однако, за некоторыми исключениями, это только намек и нет никакой гарантии, что избыточная проверка ограничения будет подавлена. Ключевые пункты:
Если виртуальная таблица произведет строки в порядке, определенном пунктом ORDER BY, то флаг orderByConsumed может быть установлен в true. Если вывод не автоматически в правильном порядке, тогда orderByConsumed должен быть оставлен в его умолчании false. Это укажет ядру SQLite, что должна быть сделана отдельная сортировка данных после того, как они выходят из виртуальной таблицы. Урегулирование orderByConsumed является оптимизацией. Запрос будет всегда получать правильный ответ, если orderByConsumed оставят в его значении по умолчанию (0). Ненужных операций по сортировке можно было бы избежать, придя к более быстрому запросу, если orderByConsumed установлен, но установка orderByConsumed неправильно может привести к неправильному ответу. Предложено, чтобы новые виртуальные внедрения таблицы оставили сброс значения orderByConsumed первоначально, а затем после того, как все остальное, как известно, работает правильно, вернулись и попытались оптимизировать, установив orderByConsumed в соответствующих случаях. Иногда флаг orderByConsumed может быть безопасно установлен, даже если вывод виртуальной таблицы не находится строго в порядке, определенном nOrderBy и aOrderBy. Если интерфейс sqlite3_vtab_distinct() вернет 1 или 2, это указывает, что порядок может быть смягчен. См. документацию относительно sqlite3_vtab_distinct(). xBestIndex должен возвратить SQLITE_OK при успехе. Если какой-либо вид фатальной ошибки происходит, соответствующий код ошибки (например, SQLITE_NOMEM) должен быть возвращен вместо этого. Если xBestIndex вернет SQLITE_CONSTRAINT, это не указывает на ошибку. SQLITE_CONSTRAINT указывает, что конкретная комбинация входных определенных параметров недостаточна для виртуальной таблицы, чтобы сделать ее работу. Это логически то же самое, как урегулирование estimatedCost к бесконечности. Если каждое обращение к xBestIndex для конкретного плана запросов возвратит SQLITE_CONSTRAINT, это означает, что нет никакого пути к виртуальной таблице, который будет безопасно использоваться, и вызов sqlite3_prepare() потерпит неудачу с ошибкой "no query solution". Возвращение SQLITE_CONSTRAINT из xBestIndex полезно для табличных функций, у которых есть обязательные параметры. Если aConstraint[].usable = false для одного из обязательного параметра, то xBestIndex должен возвратить SQLITE_CONSTRAINT. Если обязательное поле не появляется в множестве aConstraint[] вообще, это означает, что соответствующий параметр опущен во входе SQL. В этом случае xBestIndex должен установить сообщение об ошибке в pVTab->zErrMsg и вернуть SQLITE_ERROR. Итак:
Следующий пример лучше иллюстрирует использование SQLITE_CONSTRAINT как возвращаемое значение из xBestIndex: SELECT * FROM realtab, tablevaluedfunc(realtab.x); Предполагая, что первый скрытый столбец "tablevaluedfunc" = "param1", запрос выше семантически эквивалентен этому: SELECT * FROM realtab, tablevaluedfunc WHERE tablevaluedfunc.param1 = realtab.x; Планировщик запроса должен решить между многими возможными внедрениями этого запроса, но два плана в особенности интересны:
xBestIndex будет вызван однажды для каждого из потенциальных планов выше. Для плана 1 флаг aConstraint[].usable для ограничения SQLITE_CONSTRAINT_EQ на колонку param1 будет верен потому, что значение правой стороны для ограничения "param1 = ?" будет известно, так как оно определяется внешним циклом realtab. Но для плана 2 флаг aConstraint[].usable для "param1 = ?" будет false потому, что значение правой стороны определяется внутренним циклом и является таким образом неизвестным. Поскольку param1 это необходимый вход к табличным функциям, xBestIndex вернет SQLITE_CONSTRAINT, когда смотрит план 2, указав, что необходимый вход отсутствует. Это вынуждает планировщик запроса выбрать план 1. |
![]() |
int (*xClose) (sqlite3_vtab_cursor*);xClose закрывает курсор, ранее открытый xOpen. Ядро SQLite будет всегда вызывать xClose однажды для каждого курсора, открытого, используя xOpen. Этот метод должен высвободить все ресурсы, ассигнованные соответствующим обращением xOpen. Процедуру не вызовут снова, даже если она возвратит ошибку. Ядро SQLite не будет использовать sqlite3_vtab_cursor снова после того, как это будет закрыто. xClose требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xColumn) (sqlite3_vtab_cursor*, sqlite3_context*, int N);Ядро SQLite вызывает этот метод, чтобы найти значение для N-й колонки текущей строки. N основан на ноле, таким образом, первая колонка пронумерована 0. xColumn может возвратить свой результат назад SQLite использованием одного из следующих интерфейсов:
Если реализация метода xColumn не вызывает ни одну из функций выше, значение колонки по умолчанию SQL NULL. Чтобы поднять ошибку, xColumn должен использовать один из методов result_text(), чтобы установить текст сообщения об ошибке, затем возвратить соответствующий код ошибки. xColumn должен возвратить SQLITE_OK при успехе. xColumn требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xCommit) (sqlite3_vtab *pVTab);Этот метод заставляет транзакцию виртуальной таблицы передавать. Это опциональный метод. Указатель xCommit в sqlite3_module может быть NULL. Обращение к этому методу всегда следует за предшествующим обращением к xBegin и xSync. |
![]() |
int (*xConnect) (sqlite3*, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr);Метод xConnect очень похож на xCreate. Это имеет те же самые параметры и строит новую структуру sqlite3_vtab точно так же, как xCreate. И это должно также вызвать sqlite3_declare_vtab() подобно xCreate. Это должно также сделать все те же самые вызовы sqlite3_vtab_config(), как xCreate. Различие в том, что xConnect вызывают, чтобы установить новую связь с существующей виртуальной таблицей, тогда как xCreate вызывают, чтобы составить новую виртуальную таблицу с нуля. xCreate и xConnect отличаются только когда у виртуальной таблицы есть некоторое запоминающее устройство, которое должно быть инициализировано в первый раз, когда виртуальная таблица составлена. xCreate создает и инициализирует запоминающее устройство. xConnect просто соединяется с существующим запоминающим устройством. Когда xCreate и xConnect то же самое, таблица это виртуальная таблица. Как пример, рассмотрите виртуальное внедрение таблицы, которое обеспечивает доступ только для чтения к существующим файлам comma-separated-value (CSV) на диске. Нет никакого запоминающего устройства, которое должно быть создано или инициализировано для такого виртуальной таблицы (так как файлы CSV уже существуют на диске), так что методы xCreate и xConnect будут идентичны для того модуля. Другой пример это виртуальная таблица, которая осуществляет полнотекстовый индекс. xCreate должен создать и инициализировать структуры данных, чтобы хранить словарь и управляющие списки для этого индекса. xConnect с другой стороны должен определить только местонахождение и использовать существующий словарь и списки, которые были созданы предшествующим обращением xCreate. xConnect должен вернуть SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если не успешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если что-то пошло не так. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить пространство, используя sqlite3_free(), после того, как об ошибке сообщили приложению. xConnect требуется для каждого виртуального внедрения таблицы, хотя указатели xCreate и xConnect объекта sqlite3_module могут указать на ту же самую функцию, если виртуальная таблица не должна инициализировать запоминающее устройство. |
![]() |
int (*xCreate) (sqlite3 *db, void *pAux, int argc, char *const*argv, sqlite3_vtab **ppVTab, char **pzErr);Метод xCreate вызывают, чтобы создать новый экземпляр виртуальной таблицы в ответ на CREATE VIRTUAL TABLE. Если метод xCreate пропущен (указатель NULL), виртуальная таблица это одноименно-единственная виртуальная таблица. Параметр db это указатель на соединение с базой данных SQLite, которое выполняет CREATE VIRTUAL TABLE. pAux это копия указателя данных клиента, который был четвертым аргументом вызова sqlite3_create_module() или sqlite3_create_module_v2(), который зарегистрировал виртуальный модуль таблицы. Параметр argv это массив указателей на законченные null последовательности. Первая последовательность, argv[0], является именем вызываемого модуля. Имя модуля это имя, обеспеченное как второй аргумент sqlite3_create_module() и как аргумент пункта USING в CREATE VIRTUAL TABLE. Вторым, argv[1], является название базы данных, в которой составляется новая виртуальная таблица. Имя базы данных "main" для основной базы данных, "temp" для базы данных TEMP или имя, данное в конце запроса ATTACH для приложенных баз данных. Третий элемент множества, argv[2], является названием новой виртуальной таблицы, как определено после ключевого слова TABLE в CREATE VIRTUAL TABLE. Если существуют, четвертая и последующие последовательности в массиве argv[] сообщают об аргументах имени модуля в CREATE VIRTUAL TABLE. Работа по этому методу состоит в том, чтобы построить новый виртуальный объект таблицы (объект sqlite3_vtab) и возвратить указатель на него в *ppVTab. Как часть задачи создания новой структуры sqlite3_vtab, этот метод должен вызвать sqlite3_declare_vtab(), чтобы сказать ядру SQLite о колонках и типах данных в виртуальной таблице. sqlite3_declare_vtab() API имеет следующий прототип: int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable) Первым аргументом sqlite3_declare_vtab() должен быть тот же самый указатель соединения с базой данных, как первый параметр этого метода. Второй аргумент sqlite3_declare_vtab() должен быть законченной нолем строкой UTF-8, которая содержит правильно построенный запрос CREATE TABLE, который определяет колонки в виртуальной таблице и их типы данных. Имя таблицы в этом CREATE TABLE проигнорировано, как все ограничения. Только запрос имен столбцов и типов данных. Последовательность CREATE TABLE не должна быть проведена в постоянной памяти. Последовательность может быть освобождена и/или снова использована, как только завершится sqlite3_declare_vtab(). xConnect может также произвольно просить специальные функции для виртуальной таблицы, сделав один или несколько вызовов интерфейса sqlite3_vtab_config(): int sqlite3_vtab_config(sqlite3 *db, int op, ...); Вызов sqlite3_vtab_config() опционален. Но для максимальной безопасности рекомендуется, чтобы виртуальные внедрения таблицы вызвали "sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY)", если виртуальную таблицу не будет использовать изнутри триггеров или обзоров. xCreate не должен инициализировать поля pModule, nRef и zErrMsg объекта sqlite3_vtab. Ядро SQLite будет заботиться об этой работе. xCreate должен возвратить SQLITE_OK, если это успешно в составлении новой виртуальной таблицы или SQLITE_ERROR, если это не успешно. Если неуспешно, структура sqlite3_vtab не должна быть ассигнована. Сообщение об ошибке может произвольно быть возвращено в *pzErr, если есть проблема. Место, чтобы хранить последовательность сообщения об ошибке должно быть выделено, используя функцию выделения памяти SQLite, например, sqlite3_malloc() или sqlite3_mprintf(), поскольку ядро SQLite попытается освободить место, используя sqlite3_free() после того, как об ошибке сообщили приложению. Если опущен xCreate (оставленный как NULL), виртуальная таблица это одноименно-единственная виртуальная таблица. Новые экземпляры виртуальной таблицы не могут быть созданы, используя CREATE VIRTUAL TABLE, а виртуальная таблица может использоваться только через имя модуля. Обратите внимание на то, что версии SQLite до 3.9.0 (2015-10-14) не понимают одноименно-единственные виртуальные таблицы и будет segfault, если предпринята попытка CREATE VIRTUAL TABLE на одноименно-единственной виртуальной таблице, потому что метод xCreate не был проверен на пустой указатель. Если метод xCreate тот же самый указатель, как xConnect, это указывает, что виртуальная таблица не должна инициализировать запоминающее устройство. Такая виртуальная таблица может использоваться в качестве одноименной виртуальной таблицы, в качестве названной виртуальной таблицы, используя CREATE VIRTUAL TABLE, или обоими способами. Если тип данных колонки содержит специальное ключевое слово "HIDDEN" (в какой-либо комбинации прописных и строчных букв), ключевое слово опущено от имени типа данных колонки, а колонка отмечена как скрытый столбец внутренне. Скрытый столбец отличается от нормальной колонки в трех отношениях:
Например, если следующий SQL передается sqlite3_declare_vtab(): CREATE TABLE x(a HIDDEN VARCHAR(12), b INTEGER, c INTEGER Hidden); Тогда виртуальная таблица была бы составлена с двумя скрытыми столбцами с типами данных "VARCHAR(12)" и "INTEGER". Использование в качестве примера скрытых столбцов может быть замечено в виртуальном внедрении таблицы FTS3, где каждая виртуальная таблица FTS содержит скрытый столбец FTS, который используется, чтобы передать информацию от виртуальной таблицы во вспомогательные функции FTS и оператору MATCH FTS. Виртуальная таблица, которая содержит скрытые столбцы, может использоваться как табличная функция в пункте FROM оператора SELECT. Аргументы табличной функции становятся ограничениями на столбцах HIDDEN виртуальной таблицы. Например, расширение "generate_series" (файл ext/misc/series.c дерева исходных текстов) осуществляет одноименную виртуальную таблицу со следующей схемой: CREATE TABLE generate_series(value, start HIDDEN, stop HIDDEN, step HIDDEN); Метод sqlite3_module.xBestIndex во внедрении этой таблицы проверяет на ограничения равенства столбцы HIDDEN и использует их как входные параметры, чтобы определить диапазон вывода integer "value", чтобы произвести. Разумные значения по умолчанию используются для любых неограниченных колонок. Например, чтобы перечислить все целые числа между 5 и 50: SELECT value FROM generate_series(5,50); Предыдущий запрос эквивалентен следующему: SELECT value FROM generate_series WHERE start=5 AND stop=50; Аргументы на виртуальном имени таблицы соответствуют скрытым столбцам в порядке. Количество аргументов может быть меньше, чем количество скрытых столбцов, в этом случае последние скрытые столбцы не ограничены. Однако, будет ошибка, если есть больше аргументов, чем в виртуальной таблице есть скрытых столбцов. Начиная с SQLite version 3.14.0 (2016-08-08), CREATE TABLE, который передается в sqlite3_declare_vtab(), может содержать WITHOUT ROWID. Это полезно для случаев, где виртуальные строки таблицы не могут быть легко отображены в уникальные целые числа. Запрос CREATE TABLE, который включает WITHOUT ROWID, должен определить одну или более колонок как PRIMARY KEY. Каждая колонка PRIMARY KEY должна индивидуально быть NOT NULL, а все колонки для каждой строки должны быть коллективно уникальными. Обратите внимание на то, что SQLite не проводит в жизнь PRIMARY KEY для виртуальной таблицы WITHOUT ROWID. Осуществление это ответственность основного виртуального внедрения таблицы. Но SQLite действительно предполагает, что ограничение PRIMARY KEY действительно, что определенные колонки UNIQUE и NOT NULL, и использует это предположение, чтобы оптимизировать запросы для виртуальной таблицы. Столбец rowid недоступен в виртуальной таблице (конечно) WITHOUT ROWID. Метод xUpdate был первоначально разработан вокруг наличия ROWID как единственного значения. xUpdate был расширен, чтобы приспособить произвольный PRIMARY KEY вместо ROWID, но PRIMARY KEY все еще должен быть только одной колонкой. Поэтому SQLite отклонит любую виртуальную таблицу WITHOUT ROWID, у которой есть больше, чем одна колонка PRIMARY KEY и не-NULL метод xUpdate. |
![]() |
int (*xDestroy) (sqlite3_vtab *pVTab);Этот метод закрывает связь с виртуальной таблицей, точно так же, как xDisconnect, и это также разрушает внедрение базовой таблицы. Этот метод отменяет работу xCreate. xDisconnect вызывают каждый раз, когда соединение с базой данных, которое использует виртуальную таблицу, закрывается. Метод xDestroy вызывают только когда запрос DROP TABLE выполняется для виртуальной таблицы. Метод xDestroy требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы. |
![]() |
int (*xDisconnect) (sqlite3_vtab *pVTab);Этот метод освобождает связь с виртуальной таблицей. Только объект sqlite3_vtab разрушен. Виртуальную таблицу не разрушают, любое запоминающее устройство, связанное с виртуальной таблицей, сохраняется. Этот метод отменяет работу xConnect. Этот метод деструктор для связи с виртуальной таблицей. Противопоставьте этот метод xDestroy. xDestroy это деструктор для всей виртуальной таблицы. Метод xDisconnect требуется для каждого виртуального внедрения таблицы, хотя приемлемо для методов xDisconnect и xDestroy быть той же самой функцией, если это имеет смысл для конкретной виртуальной таблицы. |
![]() |
int (*xEof) (sqlite3_vtab_cursor*);Метод xEof должен возвратить false (0), если указанный курсор в настоящее время указывает на действительную строку данных, иначе true (не 0). Этот метод немедленно вызывает движок SQL после каждого xFilter и xNext. Метод xEof требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xFilter) (sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv);Этот метод начинает поиск виртуальной таблицы. Первый аргумент задает курсор, открытый xOpen. Следующие два аргумента определяют конкретный индекс поиска, ранее выбранный xBestIndex. Определенные значения idxNum и idxStr неважны, xFilter и xBestIndex договариваются, каково то значение. Функция xBestIndex, возможно, запросит значения определенных выражений, используя aConstraintUsage[].argvIndex в структуре sqlite3_index_info. Эти значения передаются xFilter через использование argc и argv. Если виртуальная таблица содержит одну или несколько строк, которые соответствуют критериям поиска, то курсор должен быть левой точкой в первой строке. Последующие обращения к xEof должны вернуть false (0). Если нет никакого соответствия строк, курсор нужно оставить в состоянии, которое заставит xEof возвращать true (не 0). Движок SQLite будет использовать методы xColumn и xRowid, чтобы получить доступ к тому содержанию строки. Метод xNext будет использоваться, чтобы продвинуться к следующей строке. Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит. Метод xFilter требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xFindFunction) (sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc) (sqlite3_context*,int,sqlite3_value**), void **ppArg);Этот метод вызывают во время sqlite3_prepare(), чтобы дать виртуальному внедрению таблицы возможность перегрузить функции. Этот метод может быть установлен в NULL, в этом случае, никакая перегрузка не происходит. Когда функция использует колонку от виртуальной таблицы как первый аргумент, этот метод вызывают, чтобы видеть, хотела ли виртуальная таблица перегрузить функцию. Первые три параметра это входы: виртуальная таблица, количество аргументов функции и имя функции. Если никакая перегрузка не желаема, этот метод возвращает 0. Чтобы перегрузить функцию, этот метод вписывает в новую реализацию функции *pxFunc, вписывает в пользовательские данные *ppArg и возвращает 1 или число между SQLITE_INDEX_CONSTRAINT_FUNCTION и 255. Исторически возвращаемое значение xFindFunction() было нолем или единицей. Ноль означает, что функция не перегружена, единица подразумевает, что это перегрузка. Способность к возвращаемым значениям SQLITE_INDEX_CONSTRAINT_FUNCTION или больше была добавлена в версии 3.25.0 (2018-09-15). Если xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, это значит, что функция берет два аргумента, функция может использоваться в качестве булева значения в операторе Where запроса и что виртуальная таблица в состоянии эксплуатировать ту функцию, чтобы ускорить результат запроса. Когда xFindFunction возвращает SQLITE_INDEX_CONSTRAINT_FUNCTION или больше, возвращенное значение становится значением sqlite3_index_info.aConstraint.op для одного из ограничений, переданных в xBestIndex(). Первый аргумент функции это колонка, определенная полем aConstraint[].iColumn ограничения. Второй аргумент функции это значение, которое будет передано в xFilter() (если задано aConstraintUsage[].argvIndex) или значение, возвращенное из sqlite3_vtab_rhs_value(). Модуль Geopoly это пример виртуальной таблицы, который использует SQLITE_INDEX_CONSTRAINT_FUNCTION, чтобы улучшить работу. Метод xFindFunction() для Geopoly вернет SQLITE_INDEX_CONSTRAINT_FUNCTION для функции geopoly_overlap() SQL и SQLITE_INDEX_CONSTRAINT_FUNCTION+1 SQL-функции geopoly_within(). Это разрешает оптимизации поиска для таких запросов, как: SELECT * FROM geopolytab WHERE geopoly_overlap(_shape, $query_polygon); SELECT * FROM geopolytab WHERE geopoly_within(_shape, $query_polygon); Обратите внимание на то, что infix-функции (LIKE, GLOB, REGEXP и MATCH) полностью изменяют порядок их аргументов. Так "like(A,B)" обычно работала бы как "B like A". Однако, xFindFunction() всегда смотрит крайний левый аргумент, но не первый логический аргумент. Следовательно, для формы "B like A" SQLite смотрит на левый операнд "B" и если тот операнд столбец виртуальной таблицы, он вызывает метод xFindFunction() на той виртуальной таблице. Но если форма "like(A,B)" используется вместо этого, то SQLite проверяет термин, чтобы видеть, является ли это колонкой виртуальной таблицы, и если так это вызывает метод xFindFunction() для колонки A виртуальной таблицы. Указатель функции, возвращенный этим установленным порядком, должен быть действительным для целой жизни объекта sqlite3_vtab, данного в первом параметре. |
![]() |
int (*xNext) (sqlite3_vtab_cursor*);Метод xNext переводит виртуальный курсор таблицы к следующей строке набора результатов, инициированного xFilter. Если курсор уже указывает на последнюю строку, когда это вызывают, то курсор больше не указывает на действительные данные, последующее обращение к методу xEof должно возвратить true (не 0). Если курсор успешно продвинут к другой строке содержания, то последующие обращения к xEof должны вернуть false (0). Этот метод должен возвратить SQLITE_OK в случае успеха или код ошибки sqlite, если ошибка происходит. Метод xNext требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xOpen) (sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);Метод xOpen создает новый курсор, используемый для доступа (чтение и/или запись) к виртуальной таблице. Успешный вызов этого метода ассигнует память для sqlite3_vtab_cursor (или подкласс), инициализирует новый объект и сделает *ppCursor указателем на новый объект. Успешный вызов тогда возвращает SQLITE_OK. Для каждого успешного вызова этого метода ядро SQLite позже вызовет xClose, чтобы разрушить ассигнованный курсор. xOpen не должен инициализировать поле pVtab структуры sqlite3_vtab_cursor. Ядро SQLite будет заботиться об этой работе автоматически. Виртуальное внедрение таблицы должно быть в состоянии поддержать произвольное число одновременно открытых курсоров. Когда первоначально открыт, курсор находится в неопределенном состоянии. Ядро SQLite вызовет метод xFilter на курсоре до любой попытки поместить его куда-то или читать из курсора. Метод xOpen требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xRename) (sqlite3_vtab *pVtab, const char *zNew);Этот метод предоставляет уведомление, что виртуальной таблице дадут новое имя. Если этот метод возвращает SQLITE_OK, SQLite переименовывает таблицу. Если этот метод возвращает код ошибки, переименование предотвращено. Метод xRename опционален. Если опущен, то виртуальная таблица не может быть переименована, используя ALTER TABLE RENAME. PRAGMA legacy_alter_table позволен до вызова этого метода, значение для legacy_alter_table восстановлено после того, как этот метод заканчивается. Это необходимо для правильной работы таблиц, которые используют теневые таблицы, где теневые таблицы должны быть переименованы, чтобы соответствовать новому виртуальному имени таблицы. Если legacy_alter_format будет выключен, то метод xConnect будет вызван для виртуальной таблицы каждый раз, когда xRename пытается изменить название теневой таблицы. |
![]() |
int (*xRollback) (sqlite3_vtab *pVTab);Этот метод вызывает отмену транзакции виртуальной таблицы. Этот метод опционален. Указатель xRollback в sqlite3_module может быть NULL. Обращение к этому методу всегда следует за предшествующим обращением к xBegin. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xRowid) (sqlite3_vtab_cursor *pCur, sqlite_int64 *pRowid);Успешный вызов этого метода заставит *pRowid быть заполненным rowid строки, на которую в настоящее время указывает виртуальный курсор таблицы pCur. Этот метод возвращает SQLITE_OK при успехе. Это возвращает соответствующий код ошибки при неудаче. Метод xRowid требуется для каждого виртуального внедрения таблицы. |
![]() |
int (*xSavepoint)(sqlite3_vtab *pVtab, int); int (*xRelease)(sqlite3_vtab *pVtab, int); int (*xRollbackTo)(sqlite3_vtab *pVtab, int);Эти методы предоставляют виртуальному внедрению таблицы возможность осуществить вложенные транзакции. Они всегда опциональные и будут вызваны только в версии 3.7.7 (2011-06-23) SQLite и позже. При вызове xSavepoint(X,N) это является сигналом виртуальной таблице X, что она должна сохранить свое текущее состояние как точка сохранения N. Последующее обращение к xRollbackTo(X,R) означает, что состояние виртуальной таблицы должно возвратиться к тому, чем это было, когда вызван xSavepoint(X,R). Вызов xRollbackTo(X,R) лишит законной силы все точки сохранения с N>R;, ни одна из них не будет отменена до прежнего уровня или освобождена, без повторной инициализации обращением к xSavepoint(). Вызов xRelease(X,M) лишает законной силы все точки сохранения, где N>=M. Методы xSavepoint(), xRelease() или xRollbackTo() никогда не будут вызывать между обращениями xBegin() и xCommit() или xRollback(). |
![]() |
int (*xSync) (sqlite3_vtab *pVTab);Этот метод сигнализирует о начале двухфазной фиксации на виртуальной таблице. Этот метод дополнительный. Указатель xSync в sqlite3_module может быть NULL. Этот метод вызван только после xBegin и до xCommit или xRollback. Чтобы осуществить двухфазную фиксацию, метод xSync на всех виртуальных таблицах вызван до xCommit на любой виртуальной таблице. Если какой-либо из xSync терпит неудачу, вся транзакция отменяется. |
![]() |
int (*xUpdate) (sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid);Все изменения виртуальной таблицы внесены, используя метод xUpdate. Этот метод может использоваться, чтобы вставить, удалить или обновить. Параметр argc определяет количество записей во множестве argv. Значение argc 1 для чистого удаления или N+2 для вставки или замены, где N это количество колонок в таблице. В предыдущем предложении N включает любые скрытые столбцы. Каждая запись argv будет иметь значение не NULL в C, но может содержать значение SQL NULL. Другими словами, всегда верно что argv[i]!=0 для i от 0 до argc-1. Однако, могло бы иметь место sqlite3_value_type(argv[i])==SQLITE_NULL. Параметр argv[0] это rowid строки, которая будет удалена. Если argv[0] это SQL NULL, никакое удаление не происходит. Параметр argv[1] это rowid новой строки, которая будет вставлена в виртуальную таблицу. Если argv[1] это SQL NULL, внедрение должно выбрать rowid для недавно вставленной строки. Последующие записи argv[] содержат значения колонок виртуальной таблицы в порядке, в котором были объявлены колонки. Количество колонок будет соответствовать декларации таблицы, которую метод xConnect или xCreate сделал использованием sqlite3_declare_vtab(). Все скрытые столбцы включены. Делая вставку без rowid (argc>1, argv[1] = SQL NULL), на виртуальной таблице, которая использует ROWID (но не на WITHOUT ROWID), внедрение должно установить *pRowid в rowid недавно вставленной строки, это станет значением, возвращенным функцией sqlite3_last_insert_rowid(). Устанавливание этого значения во всех других случаях является безопасным, движок SQLite игнорирует *pRowid возвращаемое значение, если argc == 1 или argv[1] не является NULL SQL. Каждое обращение к xUpdate попадет в один из случаев, показанных ниже. Ссылки на argv[i] обозначают SQL-значение в объекте argv[i], но не сам объект argv[i].
Метод xUpdate должен возвратить SQLITE_OK если и только если это успешно. Если неудача происходит, xUpdate должен возвратить соответствующий код ошибки. При неудаче элемент pVTab->zErrMsg может произвольно быть заменен текстом сообщения об ошибке, сохраненным в памяти, ассигнованной от SQLite через функции вроде sqlite3_mprintf() или sqlite3_malloc(). Если xUpdate нарушает некоторое ограничение виртуальной таблицы (включая, но не ограничиваясь попытку сохранить значение неверного типа данных, сохранить значение, которое является слишком большим или слишком маленьким, или изменить значение только для чтения), xUpdate должен потерпеть неудачу с соответствующим кодом ошибки. Если xUpdate выполняет UPDATE, то sqlite3_value_nochange(X) может использоваться, чтобы обнаружить, какие колонки виртуальной таблицы были на самом деле изменены запросом UPDATE. Интерфейс sqlite3_value_nochange(X) вернет true для колонок, которые не изменяются. На каждом UPDATE SQLite сначала вызовет xColumn отдельно для каждой неизменной колонки в таблице, чтобы получить значение для той колонки. xColumn может проверить, неизменна ли колонка на уровне SQL через sqlite3_vtab_nochange(). Если xColumn видит, что колонка не изменяется, это должно возвратиться, не устанавливая результат, используя один из интерфейсов sqlite3_result_xxxxx(). Только в этом случае sqlite3_value_nochange() будет true в методе xUpdate. Если xColumn действительно вызывает один или несколько и ннтерфейсов sqlite3_result_xxxxx(), SQLite понимает это как изменение значения столбца, а вызов sqlite3_value_nochange() к той колонке в xUpdate в xUpdate вернет false. Могли бы быть один или несколько открытых объектов sqlite3_vtab_cursor в использовании на экземпляре таблицы и возможно даже на строке виртуальной таблицы, когда xUpdate вызван. Внедрение xUpdate должно быть подготовлено к попыткам удалить или изменить строки таблицы из других существующих курсоров. Если виртуальная таблица не может приспособить такие изменения, xUpdate должен возвратить код ошибки. Метод xUpdate опционален. Если указатель xUpdate в sqlite3_module для виртуальной таблицы NULL, то виртуальная таблица только для чтения. |
Интерфейс ISQLiteNativeModule | Пространство имен System.Data.SQLite