![]() |
|
|||
WebMoney: WMZ Z294115950220 WMR R409981405661 WME E134003968233 |
Visa 4274 3200 2453 6495 |
SQLite работает, переводя SQL-операторы на bytecode и затем управляя этим
bytecode в виртуальной машине. Этот документ описывает,
как bytecode работает. Этот документ описывает внутренности SQLite. Информация, предоставленная
здесь, не необходима для обычной разработки приложений, используя SQLite.
Этот документ предназначается для людей, которые хотят копаться более глубоко
во внутренней структуре SQLite. bytecode не API SQLite. Детали о bytecode изменяются от одного
выпуска SQLite к следующему. Запросы, которые используют SQLite, не должны
зависеть ни от одной из деталей, найденных в этом документе. SQLite работает, переводя каждый SQL-оператор на bytecode и затем управляя
этим bytecode. A Подготовленный запрос в
SQLite главным образом просто bytecode, который должен был осуществить
соответствующий SQL. sqlite3_prepare_v2()
это компилятор, который переводит SQL на bytecode.
sqlite3_step() это
виртуальная машина, которая управляет bytecode в рамках
подготовленного запроса. Программисты, которые хотят понять, как SQLite работает
внутренне, должны быть знакомы с bytecode-движком. Исторически, bytecode-движок в SQLite известен как
"Virtual DataBase Engine" или "VDBE". Этот веб-сайт использует термины
"bytecode engine", "VDBE", "virtual machine" и "bytecode virtual machine"
попеременно, поскольку они все имеют в виду то же самое. Эта статья также использует термины "bytecode-программа" и
"подготовленный запрос" попеременно, поскольку они главным образом
то же самое. Исходный текст bytecode-движка находится в файле
vdbe.c.
Определения кода операции в этом документе
получены на основании комментариев в том исходном файле.
Комментарии исходного кода это канонический источник информации о bytecode.
Когда сомневаетесь, обратитесь к исходному коду. В дополнение к основному файлу исходного кода vdbe.c в исходном дереве
есть другие кодовые файлы-помощники, чьи имена начинаются с "vdbe",
сокращение от "Virtual DataBase Engine". Помните, что имена и значения кодов операции часто изменяются от одного
выпуска SQLite к следующему. Таким образом, если вы изучаете вывод
EXPLAIN в SQLite,
необходимо сослаться на версию этого документа (или исходный код vdbe.c),
который соответствует версии SQLite, который управлял
EXPLAIN.
Иначе описание кодов операции может не быть точным. Этот документ получен
из SQLite version 3.44.0
17129ba1ff7f0 dated 2023-11-01. bytecode в SQLite состоит из одной или более инструкций. У каждой
инструкции есть код операции и пять операндов по имени P1, P2 P3, P4 и P5.
P1, P2 и P3 это 32-битные целые числа со знаком.
Эти операнды часто обращаются к регистрам. Для инструкций, которые
воздействуют на курсоры b-дерева, операнд P1 обычно номер курсора.
Для команд перехода P2 обычно место назначения. P4 может быть 32-битным целым
числом со знаком, 64-битным целым числом со знаком, 64-битным значением с
плавающей точкой, строковым литералом, Blob, указателем на функцию сравнения
последовательности сопоставления, указателем на внедрение определенной
применением функции SQL или чем-то еще. P5 это 16-битное целое без знака,
обычно хранит флаги. Части флага P5 могут иногда затрагивать код операции
тонкими способами. Например, если SQLITE_NULLEQ (0x0080) часть операнда P5
установлен на коде операции Eq, NULL
выдерживают сравнение равенства друг другу. Иначе NULL считаются
отличающимися друг от друга.
Некоторые коды операции используют все пять операндов.
Некоторые коды операции используют один или два. Некоторые коды операции
не используют ни один из операндов. bytecode начинает выполнение на инструкции номер 0.
Выполнение продолжается, пока инструкция
Halt не замечена, пока счетчик команд не
становится больше, чем адрес последней инструкции или пока нет ошибки.
Когда bytecode останавливается, вся память, которую он ассигновал,
освобождена, закрываются все курсоры базы данных, которые он, возможно,
открыл. Если выполнение остановилось из-за ошибки, любые отложенные
транзакции закончены, и изменения, внесенные в базу данных, отменены. Код операции ResultRow
заставляет bytecode делать паузу, и соответствующие
sqlite3_step()
вернут SQLITE_ROW. Прежде, чем вызвать
ResultRow, bytecode
загрузит результаты для единственноой строки запроса в
ряд регистров. C API, такой как
sqlite3_column_int() или
sqlite3_column_text(),
извлекает результаты запроса из тех регистров. bytecode возобновляется со
следующей инструкцией после ResultRow
на следующем вызове sqlite3_step(). У каждой bytecode-программы есть фиксированное (но потенциально большое)
количество регистров. Единственный регистр может
содержать множество объектов:
Регистр может также быть "Undefined", что подразумевает, что он не
содержит значение вообще. Неопределенный отличается от NULL.
В зависимости от вариантов времени компиляции попытка прочитать
неопределенный регистр будет обычно вызывать ошибку периода выполнения.
Если генератор кода (sqlite3_prepare_v2())
когда-нибудь производит подготовленный запрос,
который читает неопределенный регистр, это является
ошибкой в генераторе кода. Регистры пронумерованы, начав с 0.
Большинство кодов операции обращается по крайней мере к одному регистру. Количество регистров в единственном подготовленном запросе
фиксируется во время компиляции. Содержание всех регистров очищено, когда
подготовленный запрос сбрасывается или
закрывается. Внутренняя объектно-ориентированная память Mem
хранит значение для единственного регистра. Абстрактный объект
sqlite3_value,
который выставляется в API, является действительно просто объектом
Mem или регистром. Подготовленный запрос может иметь нуль или более открытых курсоров.
Каждый курсор определяется маленьким целым числом, которое обычно является
параметром P1 к коду операции, который использует курсор.
Могут быть многократные курсоры, открытые на том же самом индексе или
таблице. Все курсоры работают независимо, даже курсоры, указывающие на
те же самые индексы или таблицы. Единственный путь к виртуальной машине,
чтобы взаимодействовать с файлом базы данных, это через курсор.
Инструкции в виртуальной машине могут создать новый курсор
(OpenRead или
OpenWrite), читать данные из курсора
(Column), сдвинуть курсор к другому
входу в таблице (Next или
Prev) и т.д.
Все курсоры автоматически закрываются, когда подготовленный запрос
сброшен или
закрыт.
bytecode не имеет стека, в котором можно сохранить обратный адрес
подпрограммы. Обратные адреса должны быть сохранены в регистрах.
Код операции Gosub
сохранит текущий счетчик команд в регистр P1, затем переходит на адрес в P2.
Return переходит на адрес в P1+1.
Следовательно, каждая подпрограмма связана с двумя целыми числами:
адрес точки входа в подпрограмму и номер регистра, который используется,
чтобы хранить обратный адрес.
Код операции Yield
меняет значение счетчика команд с целочисленным значением в регистре P1.
Этот код операции используется, чтобы осуществить подпрограммы, они
часто используются, чтобы осуществить подвопросы, из которых содержание
вынимают по мере необходимости. Триггеры должны быть
поточно-безопасны. Так так подпрограммы bytecode не поточно-безопасны,
различный механизм должен использоваться, чтобы осуществить триггеры.
Каждый триггер осуществляется, используя отдельную bytecode-программу
с ее собственными кодами операции, счетчиком команд и набором регистров.
Код операции Program
вызывает триггер. Program
ассигнует и инициализирует новый набор регистров для каждого вызова
подпрограммы, таким образом, подпрограммы могут быть поточно-безопасны
и рекурсивны. Код операции Param
используется подпрограммами, чтобы получить доступ к содержанию в
регистрах запроса bytecode-программы. Некоторые коды операции самоизменяются. Например, код операции
Init (который всегда является первым кодом
операции в каждой bytecode-программе) увеличивает свой операнд P1.
Последующий Once
сравнивают свои операнды P1 со значением P1 для
Init, чтобы определить, должен ли
одноразовый код инициализации, который следует, быть пропущен.
Другой пример это код операции String8,
который преобразовывает его операнд P4 из UTF-8 в правильное кодирование
последовательности базы данных, затем преобразовывает себя в
код операции String.
Каждый SQL-оператор SQLite интерпретирует
в программе для виртуальной машины. Но если SQL-оператор начнется с ключевого
слова EXPLAIN,
то виртуальная машина не выполнит программу. Вместо этого инструкции
программы будут возвращены, одна инструкция на строку, как результат запроса.
Эта особенность полезна для отладки и для изучения, как виртуальная
машина работает. Например: Любое применение может управлять EXPLAIN,
который выдаст подобное вышеупомянутому.
Оболочка командной строки
содержит дополнительную логику для того, чтобы определить циклы.
Кроме того, колонка "комментария" в выводе
EXPLAIN предоставлена только, если SQLite
собран с
-DSQLITE_ENABLE_EXPLAIN_COMMENTS. Когда SQLite собран с выбором времени компиляции
SQLITE_DEBUG,
команды PRAGMA
доступны, которые полезны для отладки и для исследования операции VDBE.
Например, vdbe_trace pragma
можно заставить выполнить разборку каждого кода операции VDBE с печатью
на стандартном выводе, поскольку код операции выполняется.
Отладочные pragma включают: В настоящее время есть 187 кодов операции, определенных виртуальной
машиной. Все в настоящее время определяемые коды операции описаны в
приведенной ниже таблице. Она была произведена автоматически, сканируя
исходный код из файла
vdbe.c. Помните: коды операции VDBE не часть интерфейсного определения для
SQLite. Количество кодов операции и их имен и значений изменяется от одного
выпуска SQLite к следующему. Коды операции, показанные в приведенной ниже
таблице, действительны для SQLite version 3.44.0
17129ba1ff7f0 dated 2023-11-01.
Abort безопасно если не было записей или если
есть активный журнал. Чтобы вынудить любой регистр быть целым
числом, просто добавьте 0. P4 это строка, которая имеет длину в P2 символов.
N-й символ указывает на близость колонки, которая должна использоваться для
N-го элемента памяти в диапазоне. P2 это количество аргументов, которое ступенчатая функция берет, а
P4 это указатель на FuncDef для этой функции. Аргумент P2 не используется
этим кодом операции. Это только чтобы снять неоднозначность функций, которые
могут взять переменное число аргументов.
Аргумент P4 необходим только для случая, где ступенчатую функцию
ранее не вызывали. Аргументы P5 взяты из регистра P2 и его преемников. Аргументы P5 взяты из регистра P2 и его преемников. Этот код операции первоначально закодирован как OP_AggStep0.
На первой оценке FuncDef, сохраненный в P4, преобразовывается в
sqlite3_context и код операции изменяется. Таким образом инициализация
sqlite3_context происходит только однажды, а не при каждом
обращении к ступенчатой функции. P2 это число аргументов, что ступенчатая функция берет, и P4
указатель на FuncDef для этой функции. Аргумент P2 не используется
этим кодом операции. Это только чтобы снять неоднозначность функций, которые
могут взять переменное число аргументов. Аргумент P4 необходим только для
случая, где ступенчатую функцию ранее не вызывали. Если P1 или P2 = 0 (false), результат 0, даже если другой вход NULL.
NULL и true или 2 NULL всегда дадут NULL. Эта инструкция заставляет VM останавливаться. Это работает, загружая NULL в регистр P2. Когда регистр обратного адреса
содержит NULL, инструкция Return
не делает ничего, просто проваливается к следующей инструкции (предполагая,
что у кода операции Return P3 = 1).
Таким образом, если подпрограмма будет введена напрямую,
Return
заставит действующее выполнение продолжаться. Но если подпрограмма будет
введена через Gosub,
Return вызовет возвращение к адресу после
Gosub. Этот код операции идентичен Null.
У этого есть другое имя только, чтобы заставить
легче прочитать и проверить. NULL не изменяется этим установленным порядком.
Это остается NULL. Очищаемая таблица находится в главном файле базы данных если P2 = 0.
Если P2 = 1, тогда таблица находится во вспомогательном файле базы
данных, который используется для хранения таблиц из
CREATE TEMPORARY TABLE. Если P3 не 0, количество изменения строки увеличено количеством строк
в очищаемой таблице. Если P3 больше, чем ноль, то значение, сохраненное в
регистре P3, также увеличено количеством строк в очищаемой таблице. См. также: Destroy Если P1 не 0, то это регистр, который последующую совокупность min() или
max() установит в 1, если текущая строка не будет минимумом или максимумом.
Регистр P1 инициализируется к 0 этой инструкцией. Интерфейс, используемый внедрением вышеупомянутых функций, чтобы
восстановить сортирующую последовательность, установленную этим кодом
операции, не доступен публично.
Только у встроенных функций есть доступ к этой особенности. Извлеченное значение сохранено в регистре P3. Если запись содержит меньше, чем P2 полей, верните NULL.
Ксли аргумент P4 это P4_MEM, примените
значение аргумента P4 как результат. Если бит OPFLAG_LENGTHARG установлен в P5,
результат, как гарантируют, будет использоваться только length()
или эквивалентом. Содержание больших blob
не загружается, таким образом экономя циклы CPU. Если бит OPFLAG_TYPEOFARG
установлен, результат будет использоваться только typeof(), операторами
IS NULL, IS NOT NULL или аналогами. В этом случае весь загруженный
контент может быть опущен. Если P5 имеет установленный бит OPFLAG_PERMUTE,
порядок сравнения определяется новым оператором
Permutation. Если бит OPFLAG_PERMUTE
очищен, регистры сравнены в последовательном порядке. P4 это структура KeyInfo, которая определяет последовательности
сопоставления и порядки сортировки для сравнения. Перестановка относится
только к регистрам. Элементы KeyInfo используются последовательно. Сравнение это сортированное сравнение, так что NULL считаются равными,
NULL меньше, чем числа, числа меньше, чем последовательности, а
последовательности меньше, чем blob. Этот код операции должен немедленно сопровождаться кодом операции
Jump. P3 = P2 || P1 Незаконно для P1 и P3 быть тем же самым регистром. Иногда, если P3
тот же самый регистр как P2, внедрение в состоянии обойти memcpy(). Если бит 0x0002 в P5 установлен, также очищают флаг MEM_Subtype в
месте назначения. Бит 0x0001 в P5 указывает, что этот код операции
Copy не может быть слит.
Бит 0x0001 используется планировщиком запроса и не играет роли во
время выполнения запросов. Эта инструкция делает глубокую копию из значения.
Дубликат сделан из любой последовательности или постоянного blob. См. также
SCopy. Если P3=0, точное количество получено, которое
включает посещение каждой btree-страницы таблицы. Но если P3 отличный от
нуля, оценка возвращена на основе текущей позиции курсора. Это отсроченный поиск. Ничего на самом деле не происходит, пока курсор не
используется, чтобы прочитать запись. Если не происходит чтение, никакого
ненужного I/O не происходит. P4 может быть массивом integers (тип P4_INTARRAY), содержащим один вход
для каждой колонки в таблице P3. Если запись массива a(i) отличная от нуля,
то чтение колонки a(i)-1 от курсора P3 эквивалентно выполнению отсроченного
поиска и затем чтение колонки i от P1. Эта информация хранится в P3 и
используется, чтобы перенаправить чтение из P3 в P1, таким образом возможно
избегая потребности искать и прочитать курсор P3. Если бит OPFLAG_SAVEPOSITION в P5 установлен, курсор будет указывающим
налево в следующей или в предыдущей записи в таблице. Если это будет
указывающим налево в следующей записи, то следующая инструкция
Next ничего не делает.
В результате в этом случае нормально удалять запись в цикле
Next. Если бит
OPFLAG_SAVEPOSITION = 0 в P5, курсор оставят в неопределенном статусе. Если OPFLAG_AUXDELETE = 1 в P5,
указывает, что это удаляет одну из нескольких связанных с удалением строки
таблицы строк и всех ее связанных элементов индекса. Точно одно из тех
удалений "primary". Все другие на курсорах OPFLAG_FORDELETE
или иначе отмечены флагом AUXDELETE. Если флаг OPFLAG_NCHANGE (0x01) в P2 (P2 НЕ P5) = 1,
тогда количество изменения строки увеличено (иначе нет). Если флаг OPFLAG_ISNOOP (0x40) в P2 (НЕ в P5!) = 1,
перехватчик pre-update для удалений выполняется,
но btree в других отношениях неизменен. Это происходит, когда
Delete должно вскоре сопровождаться
Insert
с тем же самым ключом, заставляя вход btree быть переписанным. P1 не должен быть псевдотаблицей. Это должна быть реальная
таблица с многократными строкими. Если P4 не NULL, это указывает на объект таблицы. В этом случае
перехватчик update, pre-update или оба может быть вызван.
Курсор P1 должен быть позиционирован, используя
NotFound до вызова
этого кода операции в этом случае. Определенно, если вы настраиваете
pre-update вызван, если P4 не NULL. update-hook вызван, если
P4 не NULL, и флаг OPFLAG_NCHANGE установлен в P2. Если флаг OPFLAG_ISUPDATE установлен в P2, P3
содержит адрес элемента памяти, который содержит значение, что rowid строки
будет установлен обновлением. Таблица находится в главном файле базы данных если P3 = 0.
Если P3 = 1, тогда эта таблица находится во вспомогательном файле базы
данных, который используется для хранения таблиц, созданных
CREATE TEMPORARY TABLE. Если AUTOVACUUM позволен, тогда возможно, что другая страница корня могла
бы быть перемещена в недавно удаленную страницу корня, чтобы сохранять все
страницы корня смежными в начале базы данных. Бывшее значение страницы корня,
которая переместилась (ее значение перед перемещением)
сохранено в регистре P2. Если никакое движение страницы не требовалось
(потому что удаляемая таблица уже была последней в базе данных),
ноль сохранен в регистре P2. Если AUTOVACUUM выключен,
ноль сохранен в регистре P2. Этот код операции бросает ошибку, если есть какой-либо активный читатель
VM, когда это вызвано. Это сделано, чтобы избежать трудности, связанной с
обновлением существующих курсоров, когда страница корня перемещена в базу
данных AUTOVACUUM. Эта ошибка брошена, даже если база данных не AUTOVACUUM
db, чтобы избежать вводить несовместимость между
неавтовакуумными режимами и автовакуумом. См. также: Clear Если результат сравнения Eq
на тех же самых двух операндах как предшествующий
Lt или Gt
был бы верен, то переходите к P2. Если результат сравнения
Eq на двух предыдущих операндах был бы
ложным или NULL, то проваливается. См. также: InitCoroutine Часть SQLITE_AFF_MASK в P5 должна быть символом близости:
SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER и т.д.
Попытка предпринята, чтобы привести оба входа согласно этой близости, прежде
чем сравнение будет сделано. Если SQLITE_AFF_MASK = 0x00,
то числовая близость используется. Обратите внимание на то, что
преобразования близости сохранены назад во входные регистры P1 и P3.
Таким образом, этот код операции может вызвать
постоянные изменения регистров P1 и P3. Как только любые преобразования произошли, и никакое значение не NULL,
значения сравнены. Если оба значения blob, используется memcmp(), чтобы
определить результаты сравнения. Если оба значения
текст, то соответствующая функция сопоставления, определенная в P4,
используется, чтобы сделать сравнение. Если P4 не определяется, тогда
используется memcmp(), чтобы сравнить текстовые строки. Если оба значения
числовые, то числовое сравнение используется. Если два значения имеют
различные типы, то числа считают меньше, чем последовательности, а
последовательности считают меньше, чем blob. Если установлен SQLITE_NULLEQ в P5,
результат сравнения всегда true или false, но не NULL.
Если оба операнда NULL, результат сравнения true.
Если любой операнд NULL, результат false.
Если никакой операнд не NULL, результат совпадает с тем, что было бы, если бы
флаг SQLITE_NULLEQ был опущен в P5. Этот код операции сохранит результат сравнения для использования новым
кодом операции Jump. Если P1 = 0, то все SQL-операторы становятся с истекшим сроком.
Если P1 отличный от нуля, то только в настоящее время
выполняющийся запрос истекает. Если P2 = 0, то SQL-операторы немедленно истекают. Если P2 = 1,
работающим SQL-операторам позволяют продолжить работу до завершения.
Случай P2 = 1 происходит, когда CREATE INDEX или подобное изменение схемы
происходят, которое могло бы помочь запросу, которым управляют быть быстрее,
но это не затрагивает правильность операции. Ложные отрицательные стороны безопасны. Всегда безопасно провалиться, даже
если значение находится в фильтре bloom.
Ложное отрицание заставляет больше циклов CPU использоваться, но оно должно
все еще привести к правильному ответу.
Однако, неправильный ответ может явиться результатом ложного положительного,
если переход сделан, когда это должно провалиться. Ограничительные нарушения FK также проверяются, когда подготовленный
запрос выходит. Этот код операции используется, чтобы поднять ограничительные
ошибки внешнего ключа до возвращения результатов, таких как количество
изменения строки или результат пункта RETURNING. Если P1 отличный от нуля, то переход сделан, если ограничительный счетчик
базы данных = 0 (тот, который считает отсроченные ограничительные нарушения).
Если P1 = 0, переход сделан, если ограничительный счетчик запроса = 0
(непосредственные ограничительные нарушения внешнего ключа). Курсор P1 находится на индексе btree. Если запись, определенная
P3 и P4, является префиксом какого-либо входа в P1, сделан переход
к P2, и P1 указывает налево при соответствующем входе. Эта операция оставляет курсор в состоянии, где это может быть
продвинуто в передовом направлении. Next
будет работать, но Prev нет. См. также: NotFound,
NoConflict,
NotExists. SeekGe P1 это 32-bit bitmask, указывающий, был ли каждый аргумент функции
постоянным во время компиляции. Если первый аргумент был постоянным, тогда
бит 0 в P1 установлен. Это используется, чтобы определить, могут ли
метаданные, связанные с аргументом функции пользователя, используя
sqlite3_set_auxdata() API быть безопасно сохранены до следующего вызова
этого кода операции. P1 на самом деле не используется этим кодом операции. Однако, это иногда
устанавливается в 1 вместо 0 как намек оболочке
командной строки, что этот Goto
основание цикла и что строки от P2 вниз к текущей строке
должны быть показаны для вывода EXPLAIN. P1 это код результата, возвращенный sqlite3_exec(), sqlite3_reset() или
sqlite3_finalize(). Для нормальной остановки это должно быть SQLITE_OK (0).
Для ошибок это может быть некоторое другое значение.
Если P1!=0, тогда P2 определит, действительно ли отменяется текущая
транзакция. Не делайте обратной перемотки, если P2 = OE_Fail.
Сделайте обратную перемотку, если P2 = OE_Rollback. Если P2 = OE_Abort, то
отмените все изменения, которые произошли во время этого выполнения VDBE,
но не делайте отмены транзакции. Если P4 не null, это последовательность сообщения об ошибке. P5 это значение от 0 до 4, включительно,
которое изменяет последовательность P4. 0: (без изменений)
1: ограничение NOT NULL потерпело неудачу: P4
2: Ограничение UNIQUE потерпело неудачу: P4
3: Ограничение CHECK потерпело неудачу: P4
4: ограничение FOREIGN KEY потерпело неудачу: P4 Если P5 не 0 и P4 = NULL, все после ":" пропустить. Есть подразумеваемая инструкция "Halt
0 0 0", вставленная в самом конце каждой программы. Таким образом, переход
мимо последней инструкции программы совпадает с
Halt. Если P5 не 0, поднимите ошибку SQLITE_CORRUPT_INDEX, если никакой элемент
индекса соответствия не найден. Это происходит, управляя UPDATE или
оператором удаления, и элемент индекса, который будет обновлен или удален,
не найден. Для некоторого использования
IdxDelete (например: оператор EXCEPT)
не имеет значения, что никакой вход соответствия не найден.
Для тех случаев P5 = 0. Кроме того, не поднимайте эту (самокорректирующаяся и
некритическая) ошибку, если в режиме writable_schema. Если элемент индекса P1 больше или равен значению ключа, тогда
перейдите на P2. Иначе провалитесь к следующей инструкции. Если элемент индекса P1 больше, чем значение ключа, тогда перейдите
на P2. Иначе провалитесь к следующей инструкции. Если P4 не 0, то это количество значений в распакованном ключе reg(P2).
В этом случае P3 это индекс первого регистра для распакованного ключа.
Доступность распакованного ключа может иногда быть оптимизацией. Если P5 имеет установленный бит OPFLAG_APPEND,
это является намеком к слою b-дерева, что эта вставка,
вероятно, будет приложением. Если P5 имеет установленный бит OPFLAG_NCHANGE,
то счетчик изменения увеличен этой инструкцией. Если бит OPFLAG_NCHANGE
очищен, то счетчик изменения не изменен. Если P5 имеет установленный бит OPFLAG_USESEEKRESULT,
внедрение могло бы работать быстрее, избегая ненужного поиска на курсоре P1.
Однако, флаг OPFLAG_USESEEKRESULT должен быть установлен только, если там
не было предшествующих поисков на курсоре или если новые поиски
используют ключевой эквивалент P2. Эта инструкция работает только на индексах.
Эквивалентная инструкция для таблиц
Insert. Если элемент индекса P1 меньше или равен значению ключа, тогда перейдите
к P2. Иначе провалитесь к следующей инструкции. Если элемент индекса P1 меньше, чем значение ключа тогда перейдите
к P2. Иначе провалитесь к следующей инструкции. См. также: Rowid,
MakeRecord. Этот код операции только попытка оптимизации. Если этот код операции
всегда проваливается, правильный ответ все еще получен, но
дополнительная работа выполняется. Значение N в seekHit флаге курсора P1 означает, что там существует
ключ P3:N, который будет соответствовать некоторой записи
в индексе. Мы хотим знать, возможно ли для записи P3:P4
соответствовать некоторой записи в индексе. Если это невозможно, мы можем
пропустить некоторую работу. Таким образом, если seekHit меньше P4, делается
попытка узнать, возможно ли соответствие, управляя
NotFound. Этот код операции используется в обработке пункта IN для многостолбцового
ключа. Если пункт IN присоединен к элементу ключа кроме крайнего левого
элемента, и при отсутствии совпадений на новом поиске по целому ключу, то
могло бы случиться так, что один из элементов ключа слева запрещает
совпадение и следовательно нет никакой надежды ни на какое соответствие
независимо от того, сколько элементов пункта IN проверяется.
В таком случае мы оставляем поиск пункта IN рано, используя этот код
операции. Название кода операции происходит от того, что переход сделан, если
нет никакой надежды на достижение соответствия. Если P1 не открытый курсор, то этот код операции
ничего не делает. Если начальное значение регистра P1 меньше 1,
значение неизменно, и контроль проходит к следующей инструкции. Если отслеживание позволено (через интерфейс sqlite3_trace()),
то последовательность UTF-8, содержавшаяся в P4, выдается на отзыве
трассировки. Или если P4 чист, используйте последовательность, возвращенную
sqlite3_sql(). Если P2 не ноль, выполните переход на инструкцию P2. Увеличьте значение P1 так, чтобы Once
перешел в первый раз, когда он оценен для этого. Если P3 не ноль, то это адрес, чтобы перейти, если с ошибкой
SQLITE_CORRUPT сталкиваются. Если P2!=0, внедрение немедленно следует этому коду операции.
Поэтому перепрыгните через внедрение, чтобы обратиться к P2. См. также: EndCoroutine Если флаг OPFLAG_NCHANGE в P5 = 1,
количество изменения строки увеличено (иначе нет). Если флаг OPFLAG_LASTROWID
в P5 = 1, rowid сохранен для последующего возвращения
sqlite3_last_insert_rowid() (иначе это не изменяется). Если флаг OPFLAG_USESEEKRESULT в P5 = 1,
внедрение могло бы работать быстрее, избегая ненужного поиска
на курсоре P1. Однако, флаг OPFLAG_USESEEKRESULT должен быть установлен
только, если там не было предшествующих поисков
на курсоре или если новые поиски использовали ключ, равный P3. Если установлен OPFLAG_ISUPDATE,
то этот код операции часть операции UPDATE. Иначе (если флаг не
установлен), этот код операции часть операции INSERT. Различие важно только
для перехватчика обновления. Параметр P4 может указать на структуру таблицы или может быть NULL.
Если это не NULL, то перехватчик обновления (sqlite3.xUpdateCallback)
вызван после успешной вставки. Если P1 псевдокурсор, и P2 динамично ассигнуется, то владелец
P2 передается псевдокурсору и регистр P2 становится эфемерным.
Если курсор будет изменен, значение регистра P2 изменится.
Удостоверьтесь, что это не вызывает проблем. Эта инструкция работает только с таблицами.
Эквивалентная инструкция для индексов
IdxInsert. Это оптимизированная версия SCopy,
которая работает только на целочисленных значениях. Регистр P3 содержит на единицу
меньше, чем максимальное количество позволенных ошибок. В большей части
reg(P3) ошибки будет сообщаться. Другими словами, анализ останавливается, как
только замечено reg(P1) ошибок.
Reg(P1) обновляется с количеством остающихся ошибок. Номера страниц корня всех столов в базе данных это
целые числа, сохраненные в аргументе P4_INTARRAY. Если P5 не ноль, проверка сделана на вспомогательном файле базы данных,
не на главном файле базы данных. Этот код операции используется, чтобы осуществить
integrity_check pragma. Интерпретируйте значение в регистре P1 как булево значение.
Сохраните boolean (0 или 1) в P2. Или если значение в регистре, P1 = NULL, то
P3 сохранен в регистре P2. Инвертируйте ответ, если P4 равняется 1. Логика в итоге как это: P1 обычно курсор на btree, для которого строка
расшифрованный кэш действителен через, по крайней мере, колонку P3.
Другими словами, должна была быть предшествующая
Column
для колонки P3 или больше. Если курсор не действителен, то этот код операции
мог бы дать поддельные результаты.
У btree-строки есть меньше, чем P3 колонок, затем используйте P4 в
качестве типа данных. Если P1 = -1, P3 это номер регистра, и тип данных взят от
значения в том регистре. P5 это битовая маска типов данных. SQLITE_INTEGER это
младший значащий бит (0x01). SQLITE_FLOAT бит 0x02. SQLITE_TEXT 0x04.
SQLITE_BLOB 0x08. SQLITE_NULL 0x10. Этот код операции достоверно не различает NULL и REAL, когда
P1>=0. Если база данных будет содержать значение NaN, этот код операции
будет думать, что тип данных REAL, когда это должен быть NULL.
Когда P1 <0 и значение уже сохранено
в регистре P3, тогда этот код операции действительно достоверно различает
NULL и REAL. Проблема возникает только когда P1> =0. Выполните переход на адрес в P2, если и только если тип данных значения,
определенного P1 и P3, соответствует одному из битов в битовой маске P5.
Изменяя режим WAL WAL процедура более сложна. Напишите последовательность, содержащую заключительный режим журнала, в
P2. Этот код операции должен немедленно следовать за
Compare. Этот код операции оставляет курсор настроенным, чтобы переместиться в
обратном порядке от конца к началу. Другими словами, курсор формируется,
чтобы использовать Prev, но не
Next. Если бит SQLITE_JUMPIFNULL в P5 = 1 и reg(P1) или reg(P3) = NULL,
выполните переход. Если бит SQLITE_JUMPIFNULL = 0,
тогда проваливаются, если любой операнд NULL. Часть SQLITE_AFF_MASK в P5 должна быть символом близости:
SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER и т.д.
Попытка предпринята, чтобы принудить оба входа согласно этой близости, прежде
чем сравнение будет сделано. Если SQLITE_AFF_MASK = 0x00,
то числовая близость используется. Обратите внимание на то, что
преобразования близости сохранены назад во входные регистры P1 и P3.
Таким образом, этот код операции может вызвать
постоянные изменения регистров P1 и P3. Как только любые преобразования произошли, и никакое
значение не NULL, значения сравнены. Если оба значения blob, memcmp()
используется, чтобы определить результаты сравнения. Если оба значения текст,
то соответствующая функция сопоставления, определенная в P4, используется,
чтобы сделать сравнение. Если P4 не определяется, тогда используется
memcmp(), чтобы сравнить текстовую строку. Если оба значения числовые, то
числовое сравнение используется. Если два значения имеют различные типы, то
числа считают меньше, чем последовательности, а последовательности считают
меньше, чем blob. Этот код операции сохранит результат сравнения для использования новым
кодом операции Jump. P4 может быть последовательностью, которая имеет длину P2 символов.
N-й символ строки указывает на близость колонки, которая должна
использоваться для N-го поля ключа индекса. Отображение от символа до близости дано макросом SQLITE_AFF_,
определенным в sqliteInt.h. Если P4 = NULL, у всех полей индекса есть близость BLOB. Значение P5 зависит от того, позволен ли выбор времени компиляции
SQLITE_ENABLE_NULL_TRIM: Если включен SQLITE_ENABLE_NULL_TRIM, P5 это индекс самой правой таблицы,
который может быть урезан пустым указателем. Если выключен SQLITE_ENABLE_NULL_TRIM, P5 имеет
значение OPFLAG_NOCHNG_MAGIC, если коду операции
MakeRecord
позволяют принять записи без изменений с serial_type 10.
Это значение используется только в assert()
и не затрагивает конечный результат. Сохраните максимальное количество страниц
после изменения в регистре P2. Эта инструкция бросает ошибку, если элемент памяти первоначально
не целое число. Если P3>0, P3 это регистр в структуре корня этой VDBE, который содержит
самое большое ранее произведенное рекордное число. Никаким новым рекордным
числам не позволяют быть меньше, чем это значение.
Когда это значение достигает своего максимума, ошибка SQLITE_FULL
произведена. Регистр P3 обновляется произведенным рекордным числом.
Этот механизм P3 используется, чтобы помочь
реализовать опцию AUTOINCREMENT. Next действителен только после
SeekGT,
SeekGE или Rewind,
который раньше помещал курсор.
Next не может следовать за
SeekLT,
SeekLE или
Last. Курсор P1 должен быть для реальной таблицы, не псевдотаблицы. P1 должен
быть открыт до этого кода операции, или программа будет segfault. Значение P3 это намек к btree-внедрению. Если P3=1, значит
P1 является индексом SQL, а эта инструкция, возможно, была опущена, если бы
тот индекс был уникален. P3 обычно 0. P3 всегда 0 или 1. Если P5 положительный, и переход сделан, то счетчик события
номер P5-1 в подготовленном запросе увеличен. См. также: Prev Курсор P1 находится на индексе btree. Если запись, определенная P3 и P4,
содержит какой-либо NULL, перейдите немедленно к P2. Если все термины записи
не NULL, проверка сделана, чтобы определить, есть ли у какой-либо строки в
индексе P1 btree соответствующий ключевой префикс.
Если нет никаких соответствий, немедленно перейдите к P2.
Если есть совпадение, провалитесь и оставьте курсор P1, указывающий
на соответствующую строку. Этот код операции подобен NotFound
за исключениями, что отделение всегда берется, если какая-либо часть
входного ключа поиска NULL. Эта операция оставляет курсор в статусе, где это не может быть продвинуто
ни в одном направлении. Другими словами,
Next и Prev
не работают после этой операции. SeekRowid
выполняет ту же самую операцию, но также позволяет регистру P3 содержать
значение нецелого числа, в этом случае переход всегда делается.
Этот код операции требует, чтобы P3 всегда содержал целое число. NotFound
выполняет ту же самую операцию на индексе btree (с произвольными ключами). Этот код операции оставляет курсор в состоянии, где это не может быть
продвинуто ни в одном направлении. Другими словами,
Next и
Prev
не будут работать после этого кода операции. См. также: Found,
NotFound,
NoConflict,
SeekRowid Курсор P1 находится на индексе btree. Если запись, определенная P3 и P4,
не является префиксом никакого входа в P1, переход сделан на P2.
Если P1 действительно содержит вход, префикс которого соответствует записи
P3/P4, управление проваливается к следующей инструкции, и P1 указывает
налево при соответствующем входе. Эта операция оставляет курсор в состоянии,
где это не может быть продвинуто ни в одном направлении. Другими словами,
Next и Prev
не работают после этой операции. См. также: Found,
NotExists,
NoConflict,
IfNoHope Если P1 не 0, то также установите флаг MEM_Cleared так, чтобы
NULL не сравнивались как равные, даже если SQLITE_NULLEQ будет установлен в
Ne или
Eq. Если курсор P1 ранее не открыт, откройте его теперь для специального
псевдокурсора, который всегда возвращает NULL для каждой колонки. P2 это номер столбца для аргумента sqlite_offset().
Этот код операции не использует сам P2, но значение P2 используется
генератором кода. P1, P2 и P3 к этому коду операции совпадают с
Column. Этот код операции доступен только, если SQLite собран с
-DSQLITE_ENABLE_OFFSET_SQL_FUNC. Если r[P3] ноль или меньше нуля, значит
нет никакого OFFSET, а r[P2] собирается быть значением LIMIT, r[P1]. Если r[P1] ноль или меньше нуля, значит
нет никакого LIMIT, и r[P2] установлен в -1. Иначе r[P2] это сумма r[P1] и
r[P3]. Программы верхнего уровня определяют первый вызов,
сравнивая операнд P1 с операндом P1 на коде операции
Init в начале программы. Если значения P1
отличаются, то проваливаются и делают P1 этого кода операции равным P1
из Init.
Если значения P1 то же самое, тогда выполняют переход. Для подпрограмм есть битовая маска в VdbeFrame, которая
определяет, должен ли переход быть сделан.
Битовая маска необходима, потому что самоизменяющаяся кодовая уловка
не работает на рекурсивные триггеры. Двойные эфемерные курсоры используются для
самосоединений осуществленных обзорами. Если курсор P1 уже открыт на эфемерной таблице, она
очищена (все содержание стерто). P2 это количество колонок в эфемерной таблице. Курсор указывает на
таблицу BTree, если P4=0 или на индекс BTree, если P4 не 0. Если P4 не NULL,
он указывает на структуру KeyInfo, которая определяет
формат ключей в индексе. P5 может быть маской флагов BTREE_*, определенных в btree.h.
Эти флаги управляют аспектами операции btree. Флаги BTREE_OMIT_JOURNAL и
BTREE_SINGLE добавляются автоматически. Если P3 положительный, reg[P3] изменяется немного так, чтобы это
могло использоваться в качестве данных нулевой длины для
Insert.
Это оптимизация, которая избегает дополнительного кода операции
Blob, чтобы
инициализировать тот регистр. Псевдотаблица, созданная этим кодом операции, используется, чтобы
поддержать единственный вывод строки от сортировщика так, чтобы строка
могла разделиться на отдельные столбцы, используя код операции
Column.
Код операции Column это
единственный код операции курсора, который работает с псевдотаблицей. P3 это количество областей в записях, которые
будут сохранены псевдотаблицей. Биты P5:
P4 может быть целым числом (P4_INT32) или указателем на структуру KeyInfo
(P4_KEYINFO). Если это указатель на объект KeyInfo, то открываемая
таблица должна быть index b-tree,
где объект KeyInfo определяет содержание и последовательность сопоставления
того b-дерева индекса. Иначе, если P4 целочисленное значение, то открываемая
таблица должна быть table b-tree
с числом колонок не меньше значения P4. Значение P4 может быть integer (P4_INT32) или указателем на структуру
KeyInfo (P4_KEYINFO). Если это указатель на объект KeyInfo, то открываемая
таблица должна быть
index b-tree,
где объект KeyInfo определяет содержание и последовательность сопоставления
того b-дерева индекса. Иначе, если P4 целочисленное значение, то открываемая
таблица должна быть table b-tree
с числом колонок не меньше P4. Допустимые биты P5:
Эта инструкция работает как OpenRead
за исключением того, что это открывает курсор в режиме read/write. Если P1 или P2 отличные от нуля (true), результат 1 (true)
даже если другой вход NULL. NULL и false или два NULL дают
на выходе NULL. Адрес клетки в родительской структуре определяется, добавляя значение
аргумента P1 к значению аргумента P1 инструкции
Program. Этот код операции вызывает анализатор, чтобы создать новую виртуальную
машину, затем управляет новой виртуальной машиной. Перестановка действительна только для следующего кода операции, который
должен быть Compare, у которого есть
установленный бит OPFLAG_PERMUTE в P5. Первое целое число во множестве целого числа P4 это
длина множества и не является частью перестановки. Prev действителен только после
SeekLT, SeekLE
или Last, которыми раньше двигали курсор.
Prev не позволен после
SeekGT,
SeekGE или
Rewind. Курсор P1 должен быть открыт для реальной
таблицы, не псевдотаблицы. Если P1 не открыт, поведение не определено. Значение P3 это намек btree-внедрению.
Если P3 = 1, это означает, что P1 является индексом SQL и эта инструкция,
возможно, была опущена, если бы тот индекс был уникален. P3 обычно 0. P3
всегда 0 или 1. Если P5 положительный, и переход сделан, то счетчик события номер
P5-1 в подготовленном запросе увеличен. P1 содержит адрес элемента памяти, который содержит первый элемент памяти
во множестве значений, используемых в качестве аргументов подпрограммы.
P2 содержит адрес, чтобы перейти к тому, если подпрограмма бросает исключение
IGNORE, используя RAISE(). Регистр P3 содержит адрес элемента памяти в этой
(родительской) VM, который используется, чтобы ассигновать память, требуемую
sub-vdbe во время выполнения. P4 указатель на VM, содержащую триггер. Если P5 не 0, вызов рекурсивной программы позволен. P1 это 32-bit bitmask, указывающая, был ли каждый аргумент функции
летерминирован как постоянный во время компиляции.
Если первый аргумент был постоянным, тогда бит 0 в P1 установлен.
Это используется, чтобы определить, могут ли метаданные, связанные с
аргументом функции пользователя, используя
sqlite3_set_auxdata() API, быть безопасно сохранены до следующего вызова
этого кода операции. Этот код операции работает точно как
Function. Единственная разница в имени.
Этот код операции используется в местах, где функция должна быть чисто
недетерминирована. Некоторые встроенные функции даты/времени могут быть
детерминированы или нет в зависимости от их аргументов. Когда те функции
используются недетерминированным способом, они проверят, чтобы видеть,
вызвали ли их, используя PureFunc
вместо Function и если это так,
они бросают ошибку. Должна быть блокировка чтения на базе данных (транзакция должна быть
начата или должен быть открытый курсор)
прежде, чем выполнить эту инструкцию. Этот код операции используется, извлекая информацию из колонки, у которой
есть близость REAL. Такие значения столбцов могут все еще быть сохранены как
целые числа для эффективности, но после извлечения мы хотим, чтобы у них было
только действительное значение. Очищаемые регистры будут регистрами P2, начиная с P1,
но если бит ii в P3 установлен, то не очищается P1+ii.
Другими словами, P3 это маска регистров, чтобы сохранить. Сброс регистра очищает указатель Mem.pScopyFrom. Это означает, что, если
содержание регистра было установлено, используя
SCopy, изменение значения исходного регистра
для SCopy
больше не будет производить ошибку утверждения в
sqlite3VdbeMemAboutToChange(). Если установлен P5, то всем очищенным регистрам установили их тип в
MEM_Undefined так, чтобы любая последующая попытка прочитать такой
регистр (прежде чем это будет повторно инициализировано)
произвела ошибку утверждения. P5 должен быть установлен на каждом вызове к этому коду операции.
Однако, есть места в генераторе кода, которые очищают
регистры, прежде чем их использовать под (действительным) предположением,
что регистры не будут перераспределены для некоторой другой цели, прежде чем
они будут использоваться и следовательно это безопасно. Этот код операции доступен только в тестировании и отладке.
Это не произведено для сборок конечных версий. Цель этого кода операции
состоит в том, чтобы помочь утвердить произведенный bytecode.
Этот код операции на самом деле не способствует вычислению ответа. ReopenIdx
может использоваться только с
P5=0 или P5=OPFLAG_SEEKEQ и с P4, являющимся объектом P4_KEYINFO.
Кроме того, значение P3 должно совпасть с любым
ReopenIdx или
OpenRead
для того же самого номера курсора. Допустимве биты P5:
Этот код операции работает только на курсорах, используемых для
сортировки и открытых с OpenEphemeral
или SorterOpen. Если P3 = 1, то переход будет только, если регистр P1 хранит integer,
иначе выполнение проваливается к следующему коду операции, и
Return ничего не делает. Если P3 = 0,
P1 должен содержать целое число, иначе поднято assert().
P3 должен быть установлен в 1, когда этот код операции используется в
сочетании с BeginSubrtn,
или в 0 иначе. Значение в регистре P1 неизменно этим кодом операции. P2 не используется движком байт-кода. Однако, если P2 будет положительным
и меньше, чем текущий адрес, то средство форматирования вывода "EXPLAIN"
в CLI упорядочит все коды операции из кода операции P2, чтобы не включать
текущий Return. P2 должен быть первым кодом
операции в подпрограмме, из которой возвращается этот код операции.
Таким образом, значение P2 это намек углубления кода байта.
Посмотрите tag-20220407a в wherecode.c и shell.c. Если P2 = 0, это является утверждением, что таблица P1
никогда не пуста, и следовательно переход никогда сделан не будет. Этот код операции оставляет курсор формируемым, чтобы переместиться в
передовой порядок с начала к концу. Другими словами, курсор формируется,
чтобы использовать Next, но не
Prev. Этот код операции должен сопровождаться кодом операции
Insert или InsertIdx с установленным флагом
OPFLAG_PREFORMAT, чтобы закончить операцию по вставке. Если курсор P1 индекс, то содержание ключ строки.
Если курсор P2 таблица, то извлеченное содержание является данными. Если курсор P1 должен указывать на действительную строку (не NULL)
реальной таблицы, не псевдотаблицы. Если P3!=0, тогда этим кодам операции позволяют превратить эфемерный
указатель в страницу базы данных. Это означает, что содержание выходного
регистра будет лишено законной силы, как только курсор перемещается,
включая шаги, вызванные другими курсорами, которые сохраняют
текущее положение курсоров, чтобы они могли написать ту же самую таблицу.
Если P3 = 0, копия данных сделана в памяти.
P3!=0 быстрей, но P3=0 надежней. Если P3!=0, содержание регистра P2 неподходящее для использования в
OP_Result, и любой OP_Result лишит законной силы содержание регистра P2.
Содержание регистра P2 лишено законной силы такими кодами операции, как
Function или
любым использованием другого курсора, указывающего на
ту же самую таблицу. P1 может быть обычной или виртуальной
таблицей. Раньше был отдельный код операции OP_VRowid для использования
с виртуальными таблицами, но этот код операции теперь работает на
оба типа таблицы. Утверждение терпит неудачу, если P2 не целое число. Объект RowSet оптимизирован для случая, где наборы целых чисел вставляются
в отличные фазы, причем каждый набор не содержит дубликатов.
Каждый набор определяется уникальным значением P4.
У первого набора должно быть P4=0, у заключительного набора должен быть
P4 =-1, для всех других наборов должен быть P4>0. Это позволяет оптимизацию: (a) когда P4=0 нет никакой потребности
проверить объект RowSet на P3, поскольку это, как гарантируют, не будет
содержать его, (b), когда P4 = -1 там не будет никакой потребности
вставить значение, поскольку это никогда не будет проверяться,
(c) когда значение, которое является частью набора X, вставляется, нет
никакой потребности искать, чтобы видеть, было ли то же самое значение ранее
вставлено как часть набора X (только если это было ранее вставлено как часть
некоторого другого набора). Эта инструкция делает мелкую копию из значения.
Если значение последовательность или blob,
копия только указатель на оригинал, следовательно если оригинал меняется,
копия тоже. Хуже, если оригинал освобожден, копия становится
недействительной. Таким образом программа должна гарантировать, что оригинал
не изменится в течение целой жизни копии. Используйте
Copy, чтобы сделать полную копию. Предполагается, что курсор используется только для добавления и поэтому
если курсор действителен, то курсор должен уже указывать в конец btree и
таким образом, никакие изменения не внесены в курсор. Курсор P1 сдвигается так, чтобы это указало на самый маленький вход,
который больше или равен значению ключа.
Если нет никаких записей, больше или равных ключу,
и P2 не ноль, то перейдите к P2. Если курсор P1 был открыт, используя флаг OPFLAG_SEEKEQ, то этот
код операции приземлится на запись, которая точно соответствует ключу, или
иначе это вызовет переход в P2. Когда курсор OPFLAG_SEEKEQ, этот код операции
должен сопровождаться кодом операции IdxLE
с теми же самыми аргументами. Код операции
IdxGT
будет пропущен, если этот код операции достигнет цели, но код операции
IdxGT
будет использоваться на последующих повторениях цикла. Флаг OPFLAG_SEEKEQ
это намек слою btree, чтобы сказать, что это поиск равенства. Этот код операции оставляет курсор формируемым, чтобы переместиться в
передовой порядок с начала к концу. Другими словами, курсор формируется,
чтобы использовать Next, но не
Prev. Курсор P1 сдвигается так, чтобы это указало на самый маленький вход,
который больше, чем значение ключа. Если нет никаких записей, больше, чем
ключ и P2 не ноль, то перейдите к P2. Этот код операции оставляет курсор формируемым, чтобы переместиться в
передовой порядок с начала к концу. Другими словами, курсор формируется,
чтобы использовать Next,
но не Prev. seekHit представляет максимум условий в индексе, для которого известно
по крайней мере одно совпадение. Если значение seekHit меньше, чем общее
количество условий равенства в поиске индекса, то код операции
IfNoHope мог бы работать, чтобы видеть,
может ли цикл IN быть оставлен рано, таким образом экономя работу.
Это часть оптимизации IN-early-out. P1 должен быть действительным курсором b-дерева. Курсор P1 сдвигается так, чтобы это указало на самый большой вход,
который меньше или равен значению ключа. Если нет никаких записей, меньше
или равных ключу, и P2 не ноль, то перейдите к P2. Этот код операции оставляет курсор формируемым, чтобы переместиться в
обратном порядке от конца к началу. Другими словами, курсор формируется,
чтобы использовать Prev, но не
Next. Если курсор P1 был открыт, используя флаг OPFLAG_SEEKEQ, то этот код
операции приземлится на запись, которая точно соответствует ключу, или иначе
это вызовет переход в P2. Когда курсор OPFLAG_SEEKEQ,
этот код операции должен сопровождаться кодом операции
IdxLE с теми же самыми аргументами.
Код операции IdxGE
будет пропущен, если этот код операции достигнет цели, но код операции
IdxGE
будет использоваться на последующих повторениях цикла.
Флаг OPFLAG_SEEKEQ это намек слою btree, чтобы сказать, что
это поиск равенства. Курсор P1 сдвигается так, чтобы это указало на самый большой вход,
который является меньше, чем значение ключа. Если нет никаких записей
меньше, чем ключ и P2 не ноль, то перейдите к P2. Этот код операции оставляет курсор формируемым, чтобы переместиться в
обратном порядке от конца к началу. Другими словами, курсор формируется,
чтобы использовать Prev, но не
Next. NotExists
выполняет ту же самую операцию, но с
NotExists
регистр P3, как должны гарантировать, будет содержать целочисленное значение.
С этим кодом операции P3 не мог бы содержать целое число. NotFound выполняет ту же самую операцию
на индексе btrees (с произвольными ключами). Этот код операции оставляет курсор в состоянии, где это не может быть
продвинуто ни в одном направлении. Другими словами,
Next и Prev
не будут работать после этого кода операции. См. также: Found,
NotFound,
NoConflict,
SeekRowid Этот код операции использует операнды P1-P4 последующего
SeekGE.
В тексте, который следует, операнды последующего кода операции
SeekGE обозначены как
SeekOP.P1-SeekOP.P4.
Только операнды P1, P2 и P5 этого кода операции также используют и называют
This.P1, This.P2 и This.P5. Этот код операции помогает оптимизировать операторов IN на многостолбцовом
индексе, где оператор IN в более поздних отношениях индекса, избегает
ненужных поисков в btree, заменяя их переходами
к следующей строке b-дерева вместо этого. Правильный ответ получен, если этот
код операции опущен или не делает ничего. SeekGE.P3 и
SeekGE.P4 определяют распакованный ключ,
который является желаемым входом, на который мы хотим, чтобы курсор
SeekGE.P1 указал. Назовите эту строку
SeekGE.P3/P4 "target". Если курсор SeekGE.P1
в настоящее время не указывает на действительную строку, то этот код операции
не работает, и контроль проходит в
SeekGE. Если курсор SeekGE.P1
указывает на действительную строку, то он мог бы быть целевой строкой, или
это могло бы быть строкой и немного перед целевой строкой, или это могло бы
быть после целевой строки. Если курсор в настоящее время перед целевой
строкой, то этот код операции пытается поместить курсор на целевую строку или
после нее вызовом sqlite3BtreeStep() на курсоре между 1 и This.P1 раз. This.P5 это флаг, который указывает, что сделать, если курсор заканчивает
тем, что указал на действительную строку, которая проходит целевую.
Если This.P5 = false (0), переход сделан на
SeekGE.P2. Если This.P5 = true (не 0),
переход сделан к This.P2. Ситуация P5=0 происходит, когда нет никаких
ограничений неравенства направо от ограничения IN. Переход на
SeekGE.P2 заканчивает цикл.
Ситуация P5!=0 происходит, когда есть ограничения неравенства направо от
оператора IN. В этом случае This.P2 укажет непосредственно на или код
установки до кода операции IdxGT или
IdxGE, который проверяет на конец цикла. Возможные исходы из этого кода операции: Транзакция должна быть начата прежде, чем выполнить этот код операции. Если P2 это SCHEMA_VERSION cookie (cookie номер 1),
внутренняя версия схемы установлена в P3-P5. "PRAGMA schema_version=N"
имеет P5 = 1, чтобы внутренняя версия схемы отличалась от версии схемы базы
данных, приводя к сбросу схемы. Сортировка достигается, записывая элементы в индекс сортировки, затем
делается перемотка того индекса и воспроизведение его с начала до конца.
Мы используем код операции Sort
вместо Rewind, чтобы сделать перемотку так,
чтобы глобальная переменная была увеличена, и регрессионные тесты могут
определить, оптимизирует ли оптимизатор правильно сортировки. Если P3 или сортировщик содержат NULL в одной из их значительных областей
(не считая области P4 в конце, которые проигнорированы),
сравнение, как предполагается, равно. Провалитесь к следующей инструкции, если две записи
выдерживают сравнение равенства друг другу.
Jump на P2, если они отличаются. Этот код операции обычно используется, чтобы переместить запись из
сортировщика в регистр, который является источником для курсора
псевдотаблицы, созданной, используя
OpenPseudo.
Тот курсор псевдотаблицы, это тот, который определяется параметром P3.
Очищение кэша колонки P3 как часть этого кода операции
спасает нас от необходимости в отдельной инструкции
NullRow, чтобы очистить тот кэш. Если аргумент P3 не 0, это указывает, что сортировщик может предположить
стабильную сортировку, рассматривая первые P3 полей каждого ключа,
чтобы прийти к необходимым результатам. Этот код операции псевдоним для Sort и
Rewind, который используется
для объектов Sorter. Если P3 не 0 и содержание регистра P3 = P5,
тип данных регистра P2 преобразовывается в BLOB.
Содержание та же самая последовательность байтов, это просто интерпретируется
как BLOB вместо последовательности, как будто это был CAST. Другими словами:
if (P3!=0 and reg[P3]=P5) reg[P2] := CAST(reg[P2]
as BLOB) P1 этоиндекс базы данных в sqlite3.aDb[] базы данных, на которой
приобретена блокировка. Блокировка чтения получена, если P3 = 0 или
блокировка записи получена, если P3=1. P2 содержит страницу корня таблицы, чтобы блокировать. P4 содержит указатель на название блокируемой таблицы.
Это используется только, чтобы произвести сообщение об ошибке, если
блокировка не может быть получена. Операнд P1 должен быть 0x7fffffff, P2 должен быть положительным. P1 это индекс файла базы данных, на котором начата транзакция.
Индекс 0 это главный файл базы данных, индекс 1 файл, используемый для
временных таблиц. Индексы 2 или больше используются для
приложенных баз данных. Если транзакция записи начата, и флаг Vdbe.usesStmtJournal = true
(этот флаг установлен, если Vdbe может изменить больше, чем одну строку
и может бросить исключение ABORT), транзакция запроса может также быть
открыта. Более определенно транзакция запроса открыта, если
соединение с базой данных в настоящее время находится не в режиме autocommit
или если есть другие активные запросы.
Транзакция запроса позволяет изменениям, внесенным этим VDBE быть отмененными
после ошибки, не имея необходимости отменять всю транзакцию. Если ни с какой
ошибкой не столкнутся, транзакция запроса автоматически передастся,
когда VDBE остановится. Если P5!=0, тогда этот код также сравнивают cookie
схемы с P3 и счетчик поколения схемы с P4. Здесь cookie изменяет свою
значение каждый раз, когда схема базы данных изменяется.
Эта операция используется, чтобы обнаружить изменение cookie и понять,
что текущий процесс должен перечитать схему. Если cookie схемы в P3
отличается от cookie схемы в заголовке базы данных или если счетчик поколения
схемы в P4 отличается от текущего счетчика поколения, то ошибка SQLITE_SCHEMA
поднята и выполнение остановлено. Функция обертки sqlite3_step()
могла бы тогда повторно подготовить запрос
и запустить повторно его с начала. Этот код операции подобен Affinity
за исключением того, что этот код операции принудительно приводит тип
регистра к типу столбца таблицы. Это используется, чтобы
осуществить "strict affinity". Столбцы GENERATED ALWAYS AS ... STATIC проверяются только если P3 = 0.
Когда P3 отличный от нуля, никакая проверка типа не происходит для
статических произведенных колонок. Виртуальные колонки вычисляются во время
выполнения запроса и таким образом они никогда не проверяются. Предварительные условия: Если какое-либо предварительное условие ложное,
ошибка утверждения происходит. Если P2 не 0, то это регистр, содержащий последовательность, которая
является файлом, в который должен быть написан результат вакуума.
Когда P2 = 0, вакуум переписывает оригинальную базу данных. Если параметр называют, то его имя появляется в P4.
Значение P4 используется sqlite3_bind_parameter_name(). Кроме того, установлен ли P4, проверьте, что это не вызывают из отзыва к
методу xSync() виртуальной таблицы. Если это будет так, код ошибки будет
установлен в SQLITE_LOCKED. Если VColumn
используется, чтобы принести значение неизменной колонки во время операции
UPDATE, то значение P5 = OPFLAG_NOCHNG. Это заставит функцию
sqlite3_vtab_nochange() возвращать true в методе xColumn
виртуального внедрения таблицы. Колонка P5 могла бы также содержать другие
биты (OPFLAG_LENGTHARG или OPFLAG_TYPEOFARG), но те биты не использованы
VColumn. P4 NULL или последовательность, которая была произведена методом
xBestIndex модуля. Интерпретацию последовательности P4 оставляют
внедрению модуля. Этот код операции вызывает метод xFilter
на виртуальной таблице, определенный P1. Параметр плана запросов целого числа
для xFilter сохранен в регистре P3. Регистр P3+1 хранит параметр argc,
который будет передан к методу xFilter. Регистры P3+2..P3+1+argc это
дополнительные argc параметров, которые передаются к xFilter как argv.
Регистр P3+2 становится argv[0], когда передано к xFilter. Переход сделан к P2, если бы набор результатов после фильтрации
был бы пуст. Метод xUpdate сделает DELETE или INSERT или оба. Элемент argv[0] (который
соответствует элементу памяти P3) является rowid строки, чтобы удалить.
Если argv[0] = NULL, никакое удаление не происходит. Элемент argv[1] это
rowid новой строки. Это может быть NULL, чтобы виртуальная таблица выбрала
новый rowid для себя. Последующие элементы во множестве это
значения колонок в новой строке. Если P2=1, никакая вставка не выполняется. argv[0] это rowid
строки, чтобы удалить. P1 это флаг boolean. Если это установлено в true и xUpdate успешен,
значение, возвращенное sqlite3_last_insert_rowid(), установлено к значению
rowid для вставленной строки. P5 это ошибочные действия (OE_Replace, OE_Fail, OE_Ignore), чтобы
применить в случае ограничительной неудачи для
вставки или обновления. Если подпрограмма, которая начата этой инструкцией, закончит с
Yield или
Return,
перейдите к следующей инструкции. Но если она закончит с
EndCoroutine, перейдите на
P2 вместо того, чтобы продолжить следующую инструкцию. См. также: InitCoroutine
Choose any three.
1. Обзор
2. Введение
2.1. Исходный текст VDBE
2.2. Формат инструкций
2.3. Регистры
2.4. Курсоры B-Tree
2.5. Подпрограммы
2.6. Самоизменение кода
3. Просмотр Bytecode
$ sqlite3 ex1.db
sqlite> explain delete from tbl1 where two<20;
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- ------------- -- -------------
0 Init 0 12 0 00 Start at 12
1 Null 0 1 0 00 r[1]=NULL
2 OpenWrite 0 2 0 3 00 root=2 iDb=0; tbl1
3 Rewind 0 10 0 00
4 Column 0 1 2 00 r[2]=tbl1.two
5 Ge 3 9 2 (BINARY) 51 if r[2]>=r[3] goto 9
6 Rowid 0 4 0 00 r[4]=rowid
7 Once 0 8 0 00
8 Delete 0 1 0 tbl1 02
9 Next 0 4 0 01
10 Noop 0 0 0 00
11 Halt 0 0 0 00
12 Transaction 0 1 1 0 01 usesStmtJournal=0
13 TableLock 0 2 1 tbl1 00 iDb=0 root=2 write=1
14 Integer 20 3 0 00 r[3]=20
15 Goto 0 1 0 00
4. Коды операции
Имя Opcode Описание Abortable
Проверьте, что аварийное прекращение работы может произойти, проверяет
могло ли бы аварийное прекращение работы в этом пункте вызвать повреждение
базы данных. Этот код операции появляется только в отладочной сборке.
Add
Добавьте значение в регистре P1 к значению в регистре P2 и сохраните
результат в регистре P3. Если любой вход NULL, результат NULL.
AddImm
Добавьте постоянную P2 к значению в регистре P1.
Результат всегда целое число.
Affinity
Примените близость к диапазону регистров P2, начиная с P1.
AggFinal
P1 это ячейка памяти, которая является сумматором для функции окна или
совокупности. Выполните функцию finalizer на
совокупности и сохраните результат в P1.
AggInverse
Выполнить функцию xInverse для совокупности. У функции есть аргументы P5.
P4 указатель на структуру FuncDef, которая определяет функцию.
Регистр P3 является сумматором.
AggStep
Выполните функцию xStep для совокупности.
У функции есть аргументы P5. P4 указатель на структуру FuncDef, которая
определяет функцию. Регистр P3 является сумматором.
AggStep1
Выполнить xStep (если P1=0) или xInverse (если P1!=0) для совокупности.
Аргументы P5 взяты из регистра P2 и его преемников.
У функции есть аргументы P5. P4 указатель на структуру FuncDef, которая
определяет функцию. Регистр P3 является сумматором.
AggValue
Вызовите xValue() и сохраните результат в регистре P3.
And
Возьмите логический AND значений в P1 и P2
и напишите результат в регистр P3.
AutoCommit
Установите флаг auto-commit базы данных в P1 (1 или 0). Если P2 = true,
отмените любые в настоящее время активные btree-транзакции.
Если есть какие-либо активные VM (кроме этой), то ROLLBACK терпит неудачу.
COMMIT терпит неудачу, если есть активная запись
VM или активный VM, использующая общий кэш.
BeginSubrtn
Отметьте начало подпрограммы, которая может быть введена, или это можно
вызвать, используя Gosub.
Подпрограмма должна быть закончена инструкцией
Return, у которой есть операнд P1, который
совпадает с операндом P2 к этому коду операции, и у этого есть P3 = 1.
Если подпрограмма будет введена напрямую, то
Return
просто провалится. Но если подпрограмма будет введена, используя
Gosub, Return
перейдет назад к первой инструкции после
Gosub.
BitAnd
Возьмите поразрядный AND значений в регистрах P1 и P2 и сохраните
результат в регистре P3. Если любой вход NULL, результат NULL.
BitNot
Интерпретируйте содержание регистра P1 как целое число.
Сохраните поразрядное дополнение до единицы значения P1 в регистр P2.
Если P1 хранит NULL, пишите NULL в P2. BitOr
Возьмите битовое OR значений в регистрах P1 и P2 и сохраните результат в
регистре P3. Если любой вход NULL, результат NULL. Blob
P4 указывает на blob P1 байт длиной. Сохраните blob в P2. Если P4 = NULL,
постройте заполненный нолем blob P1 байтов длиной в P2. Cast
Вынудите значение в регистре P1 быть типом, определенным P2.
Checkpoint
Контрольная точка базы данных P1. Не делает ничего, если P1 не в режиме
WAL. P2 один из SQLITE_CHECKPOINT_PASSIVE, FULL,
RESTART или TRUNCATE. Запишите 1 или 0 в mem[P3],
если контрольная точка возвращает SQLITE_BUSY или нет, соответственно.
Напишите число страниц в WAL после контрольной точки в mem[P3+1]
и число страниц в WAL, которые были обработаны после того, как контрольная
точка заканчивает, в mem[P3+2]. Однако, на ошибке,
mem[P3+1] и mem[P3+2] = -1. Clear
Удалите все содержание таблицы базы данных или индекса, страница корня
которого в файле базы данных дана как P1. Но, в отличие от
Destroy, не удаляйте таблицу
или индекс из файла базы данных.
Close
Закройте курсор, ранее открытый как P1. Если P1 в настоящее время не
открыт, эта инструкция ничего не делает. ClrSubtype
Очистите подтип из регистра P1. CollSeq
P4 указатель на объект CollSeq. Если следующее вызов к функции
пользователя или совокупности вызовет sqlite3GetFuncCollSeq(),
эта сортирующая последовательность будет возвращена. Это используется
встроенными min(), max() и nullif().
Column
Интерпретируйте данные, на которые указывает курсор P1, как
структуру, построенную использованием инструкции
MakeRecord. См. подробности в
MakeRecord.
Извлеките P2-ю колонку из этого записи. Если есть меньше, чем (P2+1) значений
в записи, извлекают NULL.
ColumnsUsed
Этот код операции (который существует только, если SQLite был собран с
SQLITE_ENABLE_COLUMN_USED_MASK) определяет, какие колонки таблицы или индекса
для курсора P1 используются. P4 это 64-битное целое число (P4_INT64), в
котором первые 63 бита по одному для каждой из первых 63 колонок таблицы или
индекса, которые на самом деле используются курсором. Старший бит установлен,
если какая-либо колонка после 64-й используется. Compare
Сравните два вектора регистров в reg(P1)..reg(P1+P3-1) (это
vector "A") и в reg(P2)..reg(P2+P3-1) ("B"). Сохраните результат сравнения
для использования следующим Jump.
Concat
Добавьте текст в регистре P1 в конец текста в регистре P2 и сохраните
результат в регистре P3. Если P1 или P2 = NULL, тогда сохраните NULL в P3.
Copy
Сделайте копию регистров P1.. P1+P3 в регистры P2.. P2+P3.
Count
Сохраните количество записей (целочисленное значение) в таблице или
индексе, открытом курсором P1 в регистре P2.
CreateBtree
Ассигнуйте новое b-дерево в главном файле базы данных, если P1 = 0, в
файле базы данных TEMP, если P1 = 1 или в приложенной базе данных, если
P1> 1. Аргумент P3 должен быть 1 (BTREE_INTKEY) для rowid-таблицы,
2 (BTREE_BLOBKEY) для индекса или таблицы WITHOUT ROWID.
Номер страницы корня нового b-дерева сохранен в регистре P2.
CursorHint
Предоставьте намек курсору P1, что он только должен возвратить
строки, которые удовлетворяют Expr в P4. Термины TK_REGISTER в выражении P4
относятся к значениям, в настоящее время проводимым в регистрах.
Термины TK_COLUMN в выражении P4 относятся к колонкам в b-дереве,
на которое указывает курсор P1. CursorLock
Захватите btree, на который указывает курсор P1 так, чтобы btree
не мог быть написан другим курсором.
CursorUnlock
Разблокируйте btree, на который указывает курсор P1 так, чтобы это могло
быть написано другими курсорами.
DecrJumpZero
Регистр P1 должен содержать целое число. Уменьшите значение в P1 и
перейдите к P2, если новое значение точно ноль.
DeferredSeek
P1 открытый курсор индекса, P3 курсор на соответствующей таблице.
Этот код операции делает отсроченный поиск курсора таблицы P3 в строке,
которая соответствует текущей строке P1.
Delete
Удалите запись, на которую в настоящее время указывает курсор P1.
Destroy
Удалите всю таблицу базы данных или индекс, страница корня которого в
файле базы данных дана в P1.
Divide
Разделите значение регистра P1 на значение в регистре P2
и сохраните результат в регистре P3 (P3=P2/P1). Если значение в регистре
P1 ноль, то результат NULL. Если любой вход NULL, результат NULL. DropIndex
Удалите внутренние структуры данных (в памяти), которые описывают индекс
по имени P4 в базе данных P1. Это вызывают после того, как индекс удален с
диска (через Destroy), чтобы сохранять
внутреннее представление схемы согласовывающимся с тем, что
находится на диске. DropTable
Удалите внутренние структуры данных (в памяти), которые описывают
таблицу по имени P4 в базе данных P1. Это вызывают после того, как таблица
удалена с диска (через Destroy), чтобы
сохранять внутреннее представление схемы согласовывающимся с тем, что
находится на диске. DropTrigger
Удалите внутренние структуры данных (в памяти), которые описывают
триггер по имени P4 в базе данных P1. Это вызывают после того, как таблица
удалена с диска (через Destroy), чтобы
сохранять внутреннее представление схемы согласовывающимся с тем, что
находится на диске. ElseEq
Этот код операции должен следовать за оператором сравнения
Lt или Gt.
Может быть ноль или больше кодов OP_ReleaseReg, но никаким другим
кодам операции не позволяют произойти между этой инструкцией и предыдущим
Lt или Gt.
EndCoroutine
Инструкцией по адресу в регистре P1 является
Yield.
Jump на параметр P2
Yield.
После перехода P1 становится неопределенным.
Eq
Сравните значения в регистрах P1 и P3. Если reg(P3)=reg(P1),
перейдите на адрес в P2.
Expire
Заставьте предварительно собранные запросы истекать.
Когда запрос с истекшим сроком будет выполнен, используя
sqlite3_step() он автоматически повторно подготовится (если он был
первоначально создан, используя sqlite3_prepare_v2())
или потерпит неудачу с SQLITE_SCHEMA.
Filter
Вычислите хэш на ключе в регистре P4, начиная с r[P3]. Проверьте, чтобы
видеть, найден ли хэш в фильтре bloom в регистре P1. Если это не присутствует
там, возможно, перейдите на P2. Иначе провалитесь.
FilterAdd
Вычислите хэш в P4, начиная с r[P3] и добавьте хэш
к фильтру bloom в r[P1]. FinishSeek
Если курсор P1 был ранее перемещен через
DeferredSeek,
закончите поисковые действия сейчас без дополнительной задержки.
Если поиск курсора уже выполнен, эта инструкция не делает ничего. FkCheck
Остановка с ошибкой SQLITE_CONSTRAINT, если есть какие-либо нерешенные
ограничительные нарушения внешнего ключа.
Если нет никаких ограничительных нарушений внешнего ключа, это
не делает ничего.
FkCounter
Увеличьте "ограничительный счетчик" на P2 (P2 может быть
отрицательным или положительным). Если P1 отличный от нуля, ограничительный
счетчик базы данных увеличен (отсроченные ограничения внешнего ключа).
Иначе, если P1 = 0, счетчик запроса увеличен (непосредственные
ограничения внешнего ключа). FkIfZero
Этот код операции проверяет, является ли ограничительный счетчик
внешнего ключа в настоящее время нолем. Если так, перейдите на инструкцию в
P2. Иначе перейдите к следующей инструкции.
Found
Если P4 = 0, тогда регистр P3 хранит blob, созданный
MakeRecord. Если P4>0, P3
первый из регистров P4, которые формируют распакованную запись.
Function
Вызовите функцию пользователя (P4 это указатель на объект
sqlite3_context, который содержит указатель на функцию, которой будут
управлять), с аргументами, взятыми из регистра P2.
Количество аргументов находится в объекте sqlite3_context, на который
указывает P4. Результат функции сохранен в регистре P3. Регистр P3 не должен
быть одним из входов функции.
Ge
Это работает точно так же, как код операции Lt
за исключением того, что переход сделан, если содержание регистра P3 больше
или равно содержанию регистра P1. См. код операции Lt. Gosub
Напишите текущий адрес в P1 и затем перейдите на адрес в P2. Goto
Безусловный переход на адрес в P2.
Следующая выполненная инструкция будет той, у которой
индекс в P2 с начала программы.
Gt
Это работает точно так же, как код операции Lt
за исключением того, что переход сделан, если содержание регистра P3 больше
содержания регистра P1. См. код операции Lt. Halt
Выйдите немедленно.
Все открытые курсоры и т.д. закрываются автоматически.
HaltIfNull
Проверьте значение в регистре P3. Если это NULL, тогда
Halt, используя параметры P1, P2 и P4, как
будто это было инструкцией Halt. Если
P3 не NULL, ничего не делает. P5 должен быть 1. IdxDelete
Содержание регистров P3, начиная с P2,
формирует распакованный ключ индекса. Этот код операции удаляет тот вход из
индекса, открытого курсором P1.
IdxGE
Значения регистра P4, начиная с P3, формируют распакованный ключ индекса,
который опускает PRIMARY KEY. Compare
это значение ключа с индексом, на который P1 в настоящее время указывает,
игнорируя PRIMARY KEY или области ROWID в конце.
IdxGT
Значения регистра P4, начинающиеся с P3, формируют распакованный ключ
индекса, который опускает PRIMARY KEY. Compare
это значение ключа с индексом, на который P1 в настоящее время
указывает, игнорируя PRIMARY KEY или области ROWID в конце.
IdxInsert
P2 хранит ключ индекса SQL, созданный
MakeRecord.
Этот код операции пишет ключ в индекс P1. Данные для входа nil.
IdxLE
Значение регистра P4, начиная с P3,
формирует распакованный ключ индекса, который опускает PRIMARY KEY или ROWID.
Compare это значение ключа с индексом, на
который P1 в настоящее время указывает, игнорируя PRIMARY KEY или ROWID
на индексе P1.
IdxLT
Значения регистра P4, начинающиеся с P3, формируют распакованный ключ
индекса, который опускает PRIMARY KEY или ROWID.
Compare это значение ключа с индексом, на
который P1 в настоящее время указывает, игнорируя PRIMARY KEY или ROWID
на индексе P1.
IdxRowid
Напишите в регистр P2 целое число, которое является последним входом в
записи в конце ключа индекса, на который указывает курсор P1. Это целое число
должно быть rowid записи таблицы, на которую указывает этот элемент индекса.
If
Перейдите к P2, если значение в регистре P1 true. Значение считают true,
если это числовое и отличное от нуля. Если значение в P1 NULL, тогда переход
выполняют, если и только если P3 отличный от нуля. IfNoHope
Регистр P3 первый из регистров в P4,
которые формируют распакованный запись. Курсор P1 это индекс btree.
P2 место назначения перехода. Другими словами, операнды к этому коду операции
совпадают с операндами NotFound и
IdxGT.
IfNot
Перейдите к P2, если значение в регистре P1 False. Значение считают false,
если у него есть числовое значение ноля. Если значение в P1 NULL, тогда
переход делают, если и только если P3 отличный от нуля. IfNotOpen
Если курсор P1 не открыт или если P1 установлен в NULL, используя
NullRow, перейдите на P2.
Иначе провалиться. IfNotZero
Регистр P1 должен содержать целое число. Если содержание регистра P1
первоначально больше, чем ноль, то уменьшите значение в регистре P1.
Если это отличное от нуля (отрицательное или положительное), перейдите к P2.
Если регистр P1 первоначально ноль, оставьте его
без изменений и проваливатесь. IfNullRow
Проверьте курсор P1, чтобы видеть, указывает ли он в настоящее время на
NULL. Если да, установите регистр P3 к NULL и немедленно перейдите на P2.
Если P1 не NULL, то провалитесь, не внося изменений.
IfPos
Регистр P1 должен содержать целое число. Если значение регистра P1
равняется 1 или больше, вычтите P3 из значения в P1 и перейдите к P2.
IfSmaller
Оцените количество строк в таблице P1.
Перейдите на P2, если та оценка меньше, чем
приблизительно 2**(0.1*P3).
IncrVacuum
Выполните единственный шаг возрастающей вакуумной процедуры по базе
данных P1. Если вакуум закончился, выполните переход на инструкцию в P2.
Иначе провалитесь к следующей инструкции.
Init
Программы содержат единственный случай этого кода операции как самый
первый код операции.
InitCoroutine
Настройте регистр P1 так, чтобы это
выполнило код по адресу в P3.
Insert
Напишите вход в таблицу курсора P1. Новый вход создается, если он
не существует, или данные для существующего входа переписаны.
Данные это значение MEM_Blob, сохраненное в регистре номер P2.
Ключ сохранен в регистре P3. Ключ должен быть MEM_Int.
Int64
P4 указатель на 64-bit integer.
Напишите это значение в регистр P2. IntCopy
Передайте целочисленное значение,
проводимое в регистре P1, в регистр P2.
Integer
32-bit integer в P1 записывается в P2. IntegrityCk
Сделайте анализ в настоящее время открытой базы данных.
Сохраните в регистре P1 текст сообщения об ошибке, описывающего любые
проблемы. Если никакие проблемы не найдены, сохраните NULL в регистре P1.
IsNull
Перейдите к P2, если значением в регистре P1 является NULL. IsTrue
Этот код операции осуществляет IS TRUE, IS FALSE, IS NOT TRUE и
IS NOT FALSE.
IsType
Перейдите к P2, если тип колонки в btree
один из типов, определенных битовой маской P5.
JournalMode
Измените режим журнала базы данных P1 на P3. P3 должен быть одним из
значений PAGER_JOURNALMODE_XXX. Изменяясь между различными режимами
(delete, truncate, persist, off и memory), это простая операция.
Никакой IO не требуется.
Jump
Перейдите к инструкции по адресу P1, P2 или P3
в зависимости от того, P1 меньше, равен или больше P2 соответственно.
Last
Следующее использование Rowid,
Column или
Prev для P1
будет относиться к последнему входу в таблице базы данных или индексе.
Если таблица или индекс пусты и P2> 0, то перейдите немедленно к P2.
Если P2 = 0 или если таблица или индекс не пусты,
провалитесь к следующим инструкциям.
Le
Это работает точно так же, как код операции Lt
за исключением того, что переход сделан, если содержание регистра P3 меньше
или равно содержанию регистра P1. LoadAnalysis
Прочитайте таблицу sqlite_stat1 для базы данных P1 и
загрузите содержание той таблицы во внутреннюю хэш-таблицу индекса.
Это заставит анализ использоваться, готовя все последующие запросы. Lt
Сравните значения в регистрах P1 и P3. Если reg(P3)<reg(P1),
перейдите к адресу в P2.
MakeRecord
Преобразуйте регистр P2, начиная с P1, в
формат записи,
используемый в качестве записи данных в таблице базы данных или как ключ в
индексе. Код операции Column
может расшифровать запись позже.
MaxPgcnt
Попытайтесь установить максимальный счетчик страниц для базы данных P1 в
значение в P3. Не позволяйте максимальному количеству страниц
падать ниже текущей страницы и не меняйте максимальное значение количества
страниц, если P3 = 0.
MemMax
P1 это регистр в структуре корня этой VM (структура корня отличается от
текущей структуры, если эта инструкция выполняется в рамках подпрограммы).
Установите значение регистра P1 к максимуму его текущего значения и
значения в регистре P2.
Move
Переместите значения P3 из регистров P1..P1+P3-1 в регистры
P2..P2+P3-1. Регистры P1..P1+P3-1 после этого будут содержать NULL.
Ошибка для диапазонов регистра P1.. P1+P3-1 и P2.. P2+P3-1 накладываться.
Ошибка, если P3 меньше 1. Multiply
Умножьте значение в регистре P1 на значение в P2
и сохраните результат в регистре P3.
Если любой вход NULL, результат NULL. MustBeInt
Вынудите значение в регистре P1 быть целым числом. Если значение в P1 не
целое число и не может быть преобразовано в целое число без потери данных, то
немедленно перейдите в P2, или если P2=0 поднимите
исключение SQLITE_MISMATCH. Ne
Это работает точно так же, как код операции Eq за исключением того, что
переход сделан, если операнды в регистрах P1 и P3 не равны. NewRowid
Получите новое число integer записи ("rowid"), используемое в качестве
ключа к таблице. Рекордное число ранее не используется в качестве ключа в
таблице базы данных, на которую указывает курсор P1.
Новое рекордное число написано в P2.
Next
Установите курсор P1 так, чтобы это указало на следующую пару
ключа/данных в его таблице или индексе. Если больше нет пар ключ/значение,
тогда проваливаются к следующим инструкциям.
Но если прогресс курсора был успешен, перейдите немедленно к P2.
NoConflict
Если P4=0, P3 хранит blob, созданный
MakeRecord. Если P4>0, P3
первый из регистров P4, которые формируют распакованную запись.
Noop
Ничего не делает. Эта инструкция часто полезна как
место назначения перехода. Not
Интерпретируйте значение в регистре P1 как булево значение.
Сохраните булево дополнение в регистре P2. Если значение в регистре P1
NULL, то NULL сохранен в P2. NotExists
P1 это индекс курсора, открытого на таблице SQL btree (с ключами целого
числа). P3 это целое число rowid. Если P1 не содержит запись с rowid P3,
тогда немедленно перейдите на P2. Если P2 = 0, поднимите ошибку
SQLITE_CORRUPT. Если P1 действительно содержит запись с rowid P3, тогда
оставляют курсор, указывающий на эту запись
и проваливаются к следующей инструкции.
NotFound
Если P4=0, регистр P3 хранит blob, созданный
MakeRecord. Если P4>0, P3
первый из регистров P4, которые формируют распакованную запись.
NotNull
Перейдите на P2, если значение P1 не NULL. Null
Напишите NULL в P2. Если P3 больше P2, также напишите
NULL в P3 и в каждый регистр между P2 и P3. Если P3 меньше
P2 (обычно P3 = 0), только P2 установлен в NULL.
NullRow
Переместите курсор P1 в пустую строку. Любые операции
Column, которые происходят, в то
время как курсор находится на пустой строке, будут всегда писать NULL.
Offset
Сохраните в регистр r[P3] байтовое смещение в файле базы данных,
которое является началом полезной нагрузки для записи, на которую в настоящее
время указывает тот курсор P1.
OffsetLimit
Этот код операции выполняет обычно используемое вычисление, связанное с
обработкой OFFSET и LIMIT. r[P1] содержит счетчик предела.
r[P3] содержит счетчик смещения. Код операции вычисляет общее значение LIMIT
и OFFSET и хранит его в r[P2]. Вычисленное значение r[P2] является общим
количеством строк, которое надо будут посетить, чтобы закончить запрос.
Once
Провалитесь к следующей инструкции в первый раз, когда с этим кодом
операции сталкиваются на каждом вызове программы байт-кода.
Jump на P2
на втором и всех последующих столкновениях во время той же самого вызова.
OpenAutoindex
Этот код операции работает аналогично
OpenEphemeral.
У этого есть другое имя, чтобы отличить его использование. Таблицы, созданные
этим кодом, будут использоваться для автоматически созданных
переходных индексов в соединениях. OpenDup
Откройте новый курсор P1, который указывает на ту же самую таблицу,
как курсор P2. Курсор P2 должен быть открыт предшествующим кодом операции
OpenEphemeral.
Только эфемерные курсоры могут быть дублированы.
OpenEphemeral
Откройте новый курсор P1 для переходной
таблицы. Курсор всегда открывается на чтение-запись, даже если главная база
данных только для чтения. Эфемерная таблица удалена автоматически,
когда курсор закрывается.
OpenPseudo
Откройте новый курсор, который указывает на поддельную таблицу, которая
содержит единственную строку данных. Содержание этой строки это
содержание регистра памяти P2. Другими словами, курсор P1 становится
псевдонимом для содержания MEM_Blob, содержавшегося в регистре P2.
OpenRead
Откройте курсор read-only для таблицы базы данных, страница корня которой
задана P2 в файле базы данных. Файл базы данных определяется P3.
P3 = 0 означает главную базу данных, P3 = 1 означает базу данных,
используемую для временных таблиц, P3>1 означает
соответствующую приложенную базу данных. Дайте новому курсору идентификатор
P1. Значения P1 не должны быть смежными, но все значения P1 должны быть
маленькими целыми числами. Ошибка, если P1 отрицательный.
OpenWrite
Откройте курсор чтения-записи по имени P1 на таблице или индексе,
страница корня которого P2 (или чья страница корня хранится в регистре P2,
если бит OPFLAG_P2ISREG установлен в P5, см. посмотрите ниже).
Or
Выполните логгический OR значений в регистрах P1 и P2, сохраните
ответ в регистре P3.
Pagecount
Напишите текущее число страниц в базе
данных P1 к элементу памяти P2. Param
Этот код операции когда-либо присутствует только в подпрограммах,
вызванных с помощью инструкции
Program.
Copy значение, в настоящее время хранимое
в элементе памяти вызывающей (родительской) структуры в элемент P2
в адресном пространстве текущей структуры. Это используется триггерами, чтобы
получить доступ к знаениям new.* и old.*.
ParseSchema
Прочитайте и разберите все записи от таблицы схемы базы данных P1,
которые соответствуют оператору Where P4. Если P4 = NULL,
то вся схема для P1 повторно размечена.
Permutation
Установите перестановку, используемую
Compare
в следующей инструкции. Перестановка сохранена в операнде P4.
Prev
Передвиньте курсор P1 так, чтобы он указал на предыдущую пару
ключа/данных в таблице или индексе. Если нет никаких предыдущих пар
ключ/значение, тогда перейдите к следующим инструкциям.
Но если перемещение курсора успешно, перейдите немедленно к P2.
Program
Выполните триггер, переданный как P4 (тип P4_SUBPROGRAM).
PureFunc
Вызовите функцию пользователя (P4 указатель на объект sqlite3_context,
который содержит указатель на функцию, которой будут управлять), с
аргументами, взятыми из регистра P2.
Количество аргументов находится в объекте sqlite3_context.
Результат функции сохранен в регистре P3. Регистр P3 не должен
быть одним из входов функции.
ReadCookie
Прочитайте куки номер P3 от базы данных P1 и напишите его в регистр P2.
P3 = 1 является версией схемы. P3=2 является форматом базы данных.
P3=3 является рекомендуемым размером кэша страниц и т.д. P1=0 является
главным файлом базы данных, P1 = 1 является файлом базы данных, используемым,
чтобы сохранить временные таблицы.
Real
P4 это указатель на 64-битное значение с плавающей точкой.
Напишите это значение в регистр P2. RealAffinity
Если регистр P1 содержит целое число, преобразовывает его в
действительное значение.
ReleaseReg
Освободить регистры. Любое содержание, которое было в регистрах,
ненадежно после того, как этот код операции заканчивает работу.
Remainder
Вычислите остаток после деления P2 на P1
и сохраните результат в регистре P3. Если значение P1 = 0, результат
NULL. Если любой операнд NULL, результат NULL. ReopenIdx
ReopenIdx работает аналогично
OpenRead за исключением того, что это
сначала проверяет, чтобы видеть, открыт ли курсор на P1 уже на том же самом
b-дереве и если это так, этот код операции не делает ничего.
Другими словами, если курсор уже открыт, не откройте его вновь.
ResetCount
Значение счетчика изменения копируется к счетчику
изменения дескриптора базы данных (возвращенного последующими запросами
sqlite3_changes()). Тогда внутренний счетчик изменения VM сброшен к 0.
Это используется триггерами. ResetSorter
Удалите все содержание из эфемерной
таблицы или сортировщика, который открыт на курсоре P1.
ResultRow
Регистры с P1 по P1+P2-1 содержат единственную строку
результатов. Этот код операции вызывает sqlite3_step(), чтобы закончиться с
кодом возврата SQLITE_ROW, и это настраивает структуру sqlite3_stmt, чтобы
обеспечить доступ к r(P1)..r(P1+P2-1) как к строке результата. Return
Перейдите к адресу, сохраненному в регистре P1. Если P1 регистр обратного
адреса, то это достигает возвращения из подпрограммы.
Rewind
Следующее использование Rowid,
Column или
Next для P1
будет относиться к первому входу в таблице базы данных или индексе.
Если таблица или индекс пусты, перейдите немедленно к P2. Если таблица или
индекс не пусты, провалитесь к следующим инструкциям.
RowCell
P1 и P2 оба открытые курсоры. Оба должны быть открыты на том же самом
типе таблицы: intkey или index. Этот код операции используется в качестве
части копирования текущей строки от P2 в P1. Если курсоры открыты на
intkey-таблицах, P3 содержит rowid, чтобы использовать с новой записью
в P1. Если они открыты на индексах, P3 не используется.
RowData
Напишите в регистр P2 полное содержание строки для строки, на которую
в настоящее время указывает курсор P1. Нет никакой интерпретации данных.
Это просто копируется в регистр P2 точно как это найдено в
файле базы данных.
Rowid
Сохранить в регистре P2 целое число, которое является ключом записи
таблицы, к которой P1 в настоящее время указателем.
RowSetAdd
Вставьте целочисленное значение, проводимое регистром P2 в
объект RowSet в регистре P1.
RowSetRead
Извлеките самое маленькое значение из объекта RowSet в P1 и поместите то
значение в регистр P3. Или, если объект RowSet P1
первоначально пуст, оставьте без изменений P3 и
перейдите на инструкцию в P2. RowSetTest
Регистр P3, как предполагается, содержит 64-битное целочисленное
значение. Если регистр P1 содержит объект RowSet и объект RowSet содержит
значение в P3, перейдите на P2. Иначе вставьте целое число в P3 в RowSet и
продвиньтесь к следующему коду операции.
Savepoint
Откройте, освободите или отмените точку сохранения, названную параметром
P4, в зависимости от значения P1. Чтобы открыть новую точку сохранения
устанавливают P1=0 (SAVEPOINT_BEGIN). Чтобы освободить (commit)
существующую точку сохранения ставят P1=1 (SAVEPOINT_RELEASE).
Для отмены существующей точки сохранения установиите
P1=2 (SAVEPOINT_ROLLBACK). SCopy
Сделайте копию регистра P1 в регистр P2.
SeekEnd
Курсор P1 передвиньте в конец btree
в целях добавления нового входа в btree.
SeekGE
Если курсор P1 относится к таблице SQL (B-дерево, которое использует
ключи целого числа), используйте значение в регистре P3 как ключ.
Если курсор P1 относится к индексу SQL, то P3 первый во множестве регистров
P4, которые используются в качестве распакованного ключа индекса.
SeekGT
Если курсор P1 относится к таблице SQL (B-дерево, которое использует
ключи целого числа), используйте значение в регистре P3 как ключ.
Если курсор P1 относится к индексу SQL, то P3 первый во множестве регистров
P4, которые используются в качестве распакованного ключа индекса.
SeekHit
Увеличьте или уменьшите значение seekHit для курсора P1 при
необходимости так, чтобы это было не меньше, чем P2 и не больше, чем P3.
SeekLE
Если курсор P1 относится к таблице SQL (B-дерево, которое использует
ключи целого числа), используйте значение в регистре P3 как ключ.
Если курсор P1 относится к индексу SQL, то P3 первый во множестве регистров
P4, которые используются в качестве распакованного ключа индекса.
SeekLT
Если курсор P1 относится к таблице SQL (B-дерево, которое использует
ключи целого числа), используйте значение в регистре P3 как ключ.
Если курсор P1 относится к индексу SQL, то P3 первый во множестве регистров
P4, которые используются в качестве распакованного ключа индекса.
SeekRowid
P1 это индекс курсора, открытого на таблице SQL btree (с ключами целого
числа). Если регистр P3 не содержит целое число или если P1 не содержит
запись с rowid P3, немедленно перейдите на P2. Или, если P2 = 0, поднимите
ошибку SQLITE_CORRUPT. Если P1 действительно содержит запись с rowid P3,
тогда оставляют курсор, указывающий на ту запись,
и проваливаются к следующей инструкции.
SeekScan
Этот код операции это код операции префикса к
SeekGE. Другими словами, этот код операции
должен немедленно сопровождаться SeekGE.
Это ограничение проверяется assert().
Sequence
Найдите следующий доступный порядковый номер для курсора P1.
Напишите порядковый номер в регистр P2. Порядковый номер на курсоре увеличен
после этой инструкции. SequenceTest
P1 это курсор сортировщика. Если счетчик последовательности в настоящее
время ноль, выполните переход на P2. Независимо от того, сделан
ли переход, увеличьте значение последовательности. SetCookie
Напишите целочисленное значение P3 в cookie номер P2 БД P1.
P2=1 является версией схемы. P2=2 является форматом базы данных.
P2=3 является рекомендуемым размером кэша страницы и т.д.
P1=0 является главным файлом базы данных, P1=1 является файлом базы данных,
используемым, чтобы сохранить временные таблицы.
ShiftLeft
Переместите целочисленное значение в регистре P2 налево на
число битов, определенных целым числом в регистре P1. Сохраните результат в
регистре P3. Если любой вход NULL, результат NULL. ShiftRight
Переместите целочисленное значение в регистре P2 направо на число
битов, определенных целым числом в регистре P1. Сохраните результат в
регистре P3. Если любой вход NULL, результат NULL. SoftNull
Установите регистр P1, чтобы иметь значение NULL, как указано
MakeRecord,
но не освобождайте последовательности или blob, связанные с регистром, чтобы,
если значение было последовательностью или blob, который был ранее
скопирован, используя SCopy,
копии продолжили быть действительными. Sort
Этот код операции делает точно то же самое, как
Rewind за исключением того, что это
увеличивает недокументированную глобальную переменную,
используемую для тестирования.
SorterCompare
P1 это курсор сортировщика. Эта инструкция сравнивает префикс blob в
регистре P3 против префикса входа, на который в настоящее время указывает
курсор сортировщика. Только первые P4 поля r[P3]
и записи сортировщика сравнены.
SorterData
Напишите в регистр P2 текущие данные сортировщика для курсора P1
сортировщика. Затем очистите кэш заголовка столбца на курсоре P3.
SorterInsert
Регистрир P2 хранит ключ индекса SQL, сделанный использованием инструкций
MakeRecord. Этот код операции пишет ключ
в сортировщик P1. Данные для входа nil. SorterNext
Этот код операции работает точно так же, как
Next за исключением того, что P1 должен быть объектом сортировщика, для
которого был вызван код операции SorterSort
. Этот код операции продвигает курсор к следующей сортированной записи
или переходит на P2, если больше нет сортированных записей. SorterOpen
Этот код операции работает как
OpenEphemeral за исключением того, что это открывает переходный индекс,
который специально предназначен, чтобы привести в порядок большие таблицы,
используя внешний алгоритм сортировки слиянием.
SorterSort
После того, как все записи были вставлены в объект Sorter,
определенный P1, вызовите этот код операции, чтобы на самом деле сделать
сортировку. Jump на P2
при отсутствии записей, которые будут сортированы.
SqlExec
Управляйте SQL-оператором или запросами, определенными в
последовательности P4. Отключите отзывы Auth и
Trace в то время, как те запросы
работают, если P1 = true. String
Значение последовательности P4 длиной P1 байт сохранено в регистре P2.
String8
P4 указывает на nul-законченную последовательность UTF-8.
Этот код операции преобразовывается в код операции
String прежде, чем он будет выполнен
впервые. Во время этого преобразования длина последовательности P4 вычислена
и сохранена как параметр P1. Subtract
Вычтите значение в регистре P1 из значения в регистре P2 и сохраните
результат в регистре P3. Если любой вход NULL, результат NULL. TableLock
Получите блокировку на конкретной таблице. Эта инструкция используется
только, когда опция общего кэша активирована.
Trace
Напишите P4 в вывод трассировки запроса, если
отслеживание запроса позволено.
Transaction
Начните транзакцию на базе данных P1, если транзакция еще не активна.
Если P2 отличный от нуля, то транзакция записи начата, или если транзакция
чтения уже активна, это модернизировано до транзакции записи.
Если P2 = 0, то транзакция чтения начата.
Если P2 равняется 2 или больше, тогда начата исключительная транзакция.
TypeCheck
Примените близость к диапазону регистров P2, начиная с P1.
Возьмите близость от объекта таблицы в P4. Если какое-либо значение не может
быть приведено в правильный тип, то поднимите ошибку.
Vacuum
Пропылесосьте всю базу данных P1. P1 = 0 для "main", 2 или больше для
приложенной базы данных. База данных "temp" не может вакуумироваться.
Variable
Передайте значения связанного параметра P1 в регистр P2.
VBegin
P4 может быть указателем на структуру sqlite3_vtab.
Если это так, вызовите метод xBegin для этой таблицы.
VCheck
P4 указатель на объект таблицы, который является виртуальной таблицей в
схеме P1, которая поддерживает метод xIntegrity().
Этот код операции управляет методом xIntegrity()
для той виртуальной таблицы, используя P3 в качестве целочисленного
аргумента. Если ошибка сообщена, имя таблицы предваряется сообщением об
ошибке, и то сообщение хранится в P2. Если никакие ошибки не замечены,
регистр P2 = NULL. VColumn
Сохраните в регистре P3 значение P2-й колонки текущей строки виртуальной
таблицы курсора P1.
VCreate
P2 содержит название виртуальной таблицы в базе данных P1.
Вызовите метод xCreate для той таблицы. VDestroy
P4 название виртуальной таблицы в базе данных P1. Вызовите метод xDestroy
для той таблицы. VFilter
P1 это открытый курсор, применяемый
VOpen. P2 это адрес, чтобы перейти, если
фильтрованный набор результатов пуст.
VInitIn
Установите регистр P2, чтобы быть указателем на объект ValueList для
курсора P1 с кэшем регистра P3 и выходным регистром P3+1. Объект ValueList
может использоваться в качестве первого аргумента sqlite3_vtab_in_first() и
sqlite3_vtab_in_next(), чтобы извлечь все значения, сохраненные в курсоре P1.
Регистр P3 используется, чтобы хранить значения, возвращенные
sqlite3_vtab_in_first() и sqlite3_vtab_in_next(). VNext
Продвиньте виртуальную таблицу P1 к следующей
строке в наборе результатов и перейдите на инструкцию P2.
Или, если виртуальная таблица достигла конца своего набора результатов, то
проваливается к следующей инструкции. VOpen
P4 указатель на виртуальный объект таблицы, структуру
sqlite3_vtab. P1 это номер курсора. Этот код операции открывает курсор
для виртуальной таблицы и хранит тот курсор в P1. VRename
P4 это указатель на виртуальный объект таблицы, структуру sqlite3_vtab.
Этот код операции вызывает соответствующий метод xRename.
Значение в регистре P1 передается как аргумент
zName методу xRename. VUpdate
P4 это указатель на виртуальный объект таблицы, структуру sqlite3_vtab.
Этот код операции вызывает соответствующий метод xUpdate. Значения P2
это смежные элементы памяти, начиная в P3 для передачи вызову xUpdate.
Значение в регистре (P3+P2-1) соответствует элементу p2
множества argv, переданного xUpdate.
Yield
Обменяйте счетчик команд со значением в регистре P1.
Это имеет эффект уступки.
ZeroOrNull
Если оба регистра P1 и P3 NOT NULL,
то сохраните ноль в регистре P2. Если регистр P1 или P3 NULL, поместите
NULL в регистр P2.