Операционная система ЗОСРВ «Нейтрино» > Руководство разработчика > Программные интерфейсы общего назначения > Прикладные библиотеки и технологии > Библиотека менеджера QDB > Статьи и обзоры > Инструкции виртуальной машины QDB



Инструкции виртуальной машины QDB

Описание поддерживаемых инструкций

В этой статье:

Просмотр программ, генерируемых QDB
Инструкции

Каждая инструкция виртуальной машины содержит имя и до трех операндов, которые обозначаются P1, P2 и P3. Операнд P1 может быть произвольным целым числом, а операнд P2 должен являться неотрицательным целым числом. В любой операции, которая может вызывать переход на другую инструкцию, P2 всегда является адресом перехода. Операнд P3 является строкой с нулевым символом на конце или значением NULL. Операторы могут иметь один, два, три или ни одного операнда.

Виртуальная машина выполняет программу, начиная с инструкции с номером 0, до наступления одного из следующих событий:

  1. получена инструкция останова Halt
  2. значение счетчика инструкций программы стало на единицу больше адреса последней инструкции
  3. при выполнении программы произошла ошибка

В случае останова виртуальной машины освобождается вся выделенная память и закрываются все открытые курсоры базы данных. Если выполнение прерывается из-за ошибки, все незавершенные транзакции и изменения, внесенные в базу данных, аннулируются.

Виртуальная машина также включает в себя стек операндов с бесконечной глубиной, в котором хранятся операнды многих инструкций (более подробную информацию см. в их описаниях).

Виртуальная машина может иметь произвольное (в том числе нулевое) количество курсоров. Каждый курсор указывает на одну таблицу или индекс базы данных. На один индекс или таблицу могут указывать несколько курсоров. Все курсоры работают независимо друг от друга, даже если указывают на одни и те же индексы или таблицы. Курсоры — единственное средство взаимодействия виртуальной машины с файлом базы данных. Существуют инструкции для создания нового курсора (Open), чтения данных из курсора (Column), перемещения курсора на следующую запись в таблице (Next) или индексе (NextIdx) и др. Все курсоры автоматически закрываются при завершении работы виртуальной машины.

Виртуальная машина содержит произвольное количество фиксированных областей памяти, адреса которых увеличиваются, начиная с нуля. В каждой области может размещаться произвольная строка. Как правило, в ячейках памяти хранятся результаты скалярного оператора SELECT, который входит в состав более сложного выражения.

Виртуальная машина включает в себя единственного сортировщика, который накапливает, сортирует записи и воспроизводит их в порядке сортировки. Сортировщик используется для реализации условия ORDER BY оператора SELECT.

Виртуальная машина содержит единый список идентификаторов строк записей таблицы базы данных, которую требуется обновить. Условие WHERE оператора UPDATE или DELETE сканирует таблицу, помещает в список идентификаторы строк всех записей, которые подлежат изменению, а затем воспроизводит список и изменяет таблицу в рамках отдельного этапа.

Виртуальная машина может включать в себя любое количество подмножеств, которые состоят из произвольного количества строк. Множества используются для реализации оператора IN, правая часть которого является константой.

Виртуальная машина может открывать для чтения один внешний файл, который используется при выполнении команды COPY.

Виртуальная машина также может иметь один набор агрегаторов. Агрегатор — это устройство, которое реализует условие GROUP BY оператора SELECT. Агрегатор включает в себя один или несколько элементов, в которых хранятся значения, извлекаемые оператором SELECT. Все агрегаторы содержат одинаковое количество элементов, которое определяется операцией AggReset. В каждый момент времени один из агрегаторов является «текущим» или «активным». Существуют операции чтения и записи элементов активного агрегатора, изменения активного агрегатора и сканирования всех агрегаторов.

Просмотр программ, генерируемых QDB

Для каждого SQL-оператора QDB генерирует программу, которая выполняется в виртуальной машине. Если оператор содержит ключевое слово EXPLAIN, виртуальная машина не выполняет эту программу, а возвращает результаты ее инструкций так, как будто они являются запросами. Эта функция полезна для отладки, изучения работы виртуальной машины и профилирования операторов SQL. В следующем примере показан результат оператора EXPLAIN DELETE FROM tbl1 WHERE two<20;:

addr opcode p1 p2 p3
---- ------------ ----- ----- ------------------
0 Transaction 0 0
1 VerifyCookie 219 0
2 ListOpen 0 0
3 Open 0 3 tbl1
4 Rewind 0 0
5 Next 0 12
6 Column 0 1
7 Integer 20 0
8 Ge 0 5
9 Recno 0 0
10 ListWrite 0 0
11 Goto 0 5
12 Close 0 0
13 ListRewind 0 0
14 OpenWrite 0 3
15 ListRead 0 19
16 MoveTo 0 0
17 Delete 0 0
18 Goto 0 15
19 ListClose 0 0
20 Commit 0 0

Все, что необходимо сделать — это добавить ключевое слово EXPLAIN перед оператором SQL. Если перед этим ввести в qdb команду .explain, активируется режим вывода результатов в более удобном для восприятия виде.

Виртуальная машина QDB поддерживает режим трассировки, при котором в стандартное устройство вывода записываются сообщения о ее выполнении. Для включения и выключения режима трассировки используются нестандартные SQL-команды PRAGMA. Команда включения трассировки:

PRAGMA vdbe_trace=on;

Чтобы отключить трассировку, следует указать в этой команде on вместо off.

Инструкции

На текущий момент виртуальная машина поддерживает 125 инструкций, которые описаны ниже.

AbsValue
Интерпретирует вершину стека как число и заменяет его модулем этого числа. Если вершина стека содержит значение NULL, оно не изменяется.
Add
Извлекает из стека два верхних элемента, складывает их и помещает результат в стек. Если какой-либо из элементов является строкой, перед сложением он преобразуется в вещественное число типа double с помощью функции atof(). Если какой-либо из элементов равен NULL, результат равен NULL.
AddImm
Складывает значение P1 со значением, которое хранится на вершине стека. Результат всегда является вещественным числом.

Чтобы преобразовать значение на вершине стека в целое число, достаточно сложить его с нулем.
AggFinal
Выполняет функцию финализатора агрегата. P1 — область памяти, которая является накопителем агрегата.

P2 — количество аргументов ступенчатой функции, а P3 — указатель на структуру FuncDef с ее определением. В этой инструкции операнд P2 не используется, а присутствует для устранения неоднозначности, если функция может принимать разное количество аргументов. Аргумент P3 необходим только в вырожденном случае, когда ступенчатая функция не вызывалась ранее.
AggStep
Выполняет ступенчатую функцию агрегата. P2 содержит аргументы функции. P3 является указателем на структуру FuncDef, в которой хранится определение функции. P1 — область памяти, которая используется в качестве накопителя.

Аргументы P2 извлекаются из стека.
And
Извлекает из стека два значения, применяет к ним операцию логического И записывает результат типа boolean в стек.
AutoCommit
Устанавливает значение P1 (1 или 0) флага автоматической фиксации базы данных. Если значение P2 равно true, все активные транзакции btree аннулируются. При наличии активных виртуальных машин (помимо текущей) оператор COMMIT или ROLLBACK завершается с ошибкой.

Эта инструкция приводит к останову виртуальной машины.
BitAnd
Извлекает из стека два верхних элемента, преобразует их в целые числа, выполняет над ними операцию побитового И и записывает результат в стек. Если какой-либо из элементов равен NULL, результат равен NULL.
BitNot
Интерпретирует вершину стека как значение и заменяет его обратным кодом этого значения. Если вершина стека содержит значение NULL, оно не изменяется.
BitOr
Извлекает из стека два верхних элемента, преобразует их в целые числа, выполняет над ними операцию побитового ИЛИ и записывает результат в стек. Если какой-либо из элементов равен NULL, результат равен NULL.
Blob
P3 указывает на большой двоичный объект (Binary Large OBject, BLOB) длиной P1 байт, значение которого помещается в стек. Эта инструкция не формируется непосредственно компилятором; компилятор создает инструкцию OP_HexBlob, в которой шестнадцатеричное строковое представление BLOB находится в операнде P3. Эта инструкция преобразуется в OP_Blob при первом выполнении.
Callback
Извлекает из стека значения P1, формирует из них массив и обращается к функции обратного вызова, передавая ей этот массив в качестве третьего параметра.
Clear
Полностью удаляет содержимое таблицы или индекса, корневая страница которого в файле базы данных указана в операнде P1. В отличие от инструкции Destroy, эта инструкция не удаляет таблицу или индекс из файла базы данных.

Очищаемая таблица находится в главном файле базы данных, если операнд P2 равен 0. Если P2 равен 1, эта таблица находится во вспомогательном файле базы данных, где хранятся таблицы, созданные командой CREATE TEMPORARY TABLE.

См. также: Destroy.
Close
Закрывает курсор, открытый ранее как P1. Если в текущий момент курсор P1 не открыт, эта инструкция не выполняет никаких действий.
CollSeq
P3 — указатель на структуру CollSeq. Если следующий вызов пользовательской функции или агрегата обращается к функции sqlite3GetFuncCollSeq(), инструкция возвращает эту последовательность сортировки. Данная инструкция используется встроенными функциями min(), max() и nullif().
Column
Интерпретирует данные, на которые указывает курсор P1, как структуру, формируемую инструкцией MakeRecord (дополнительную информацию о формате данных см. в описании инструкции MakeRecord). Помещает в стек значение столбца с номером P2, содержащегося в данных. Если запись содержит менее чем P2 + 1 значений, в стек помещается значение NULL.

Если курсор ранее обрабатывался инструкцией KeyAsData, это поле можно извлекать из ключа, а не из данных.

Если операнд P1 имеет отрицательное значение, запись сохраняется в стеке, а не в таблице. Если P1 равен -1, используется вершина стека, если P1 равен -2 — следующая запись в стеке и т.д. В стек всегда помещается только указатель на запись, которая хранится ниже. Значение столбца не копируется. Количество столбцов в записи сохраняется в стеке над самой записью.

Если столбец содержит менее P2 столбцов, в стек помещается значение NULL. Если операнд P3 имеет тип P3_MEM, записывается значение P3. P3 является значением по умолчанию для столбца, который был добавлен с помощью команды ALTER TABLE ADD COLUMN. Если P3 является обычной строкой, в стек помещается значение NULL. Если P3 является строкой, эта строка содержит комментарий, который описывает значение, помещаемое в стек, а не значение по умолчанию.
Concat
Объединяет P1 + 2 первых элементов стека, начиная с нижнего. P1 + 2 исходных элементов извлекаются из стека, если P2 равен 0, и остаются в стеке, если P2 равен 1. Если любой из элементов стеке равен NULL, результат также равен NULL.

Если P1 равен 1, эта инструкция копирует элемент, который находится на вершине стека, в память, возвращаемую функцией sqliteMalloc().
ContextPop
Восстанавливает состояние контекста Vdbe на момент, предшествующий выполнению инструкции ContextPush. Этот контекст содержит идентификатор строки и счетчики изменений последнего и текущего операторов.
ContextPush
Сохраняет текущий контекст Vdbe для последующего восстановления с помощью инструкции ContextPop. Этот контекст содержит идентификатор строки и счетчики изменений последнего и текущего операторов.
CreateIndex
Создает новый индекс в главном файле базы данных, если операнд P2 равен 0, или во вспомогательном файле базы данных, если P2 равен 1. Номер корневой страницы нового индекса помещается в стек.
CreateTable
Создает новую таблицу в главном файле базы данных, если P2 равен 0, или во вспомогательном файле базы данных, если P2 равен 1. Номер корневой страницы новой таблицы помещается в стек.

Разница между таблицей и индексом заключается в том, что таблица содержит обязательный 4-байтовый целочисленный ключ и произвольные данные, а индекс — только произвольный ключ.

См. также: CreateIndex
Delete
Удаляет запись, на которую в текущий момент указывает курсор P1.

После удаления курсор указывает на следующую или предыдущую запись в таблице. Если он указывает на следующую запись, следующая инструкция Next не выполняет никаких действий. Таким образом, можно удалять запись, находясь в цикле Next.

Если установлен флаг OPFLAG_NCHANGE операнда P2, счетчик изменений строки инкрементируется (в противном случае не инкрементируется).

Если P1 является псевдотаблицей, эта инструкция не выполняет никаких действий.
Destroy
Полностью удаляет содержимое таблицы или индекса, корневая страница которого в файле базы данных указана в операнде P1.

Удаляемая таблица находится в главном файле базы данных, если операнд P2 равен 0. Если P2 равен 1, эта таблица находится во вспомогательном файле базы данных, где хранятся таблицы, созданные командой CREATE TEMPORARY TABLE.

Если включен режим автоматической очистки AUTOVACUUM, после удаления корневой страницы на ее место может быть помещена другая корневая страница, чтобы все корневые страницы располагались непрерывно в начале базы данных. Значение корневой страницы перед ее перемещением записывается в стек. Если не требуется перемещать страницы (удаляемая таблица является последней в базе данных), в стек помещается значение 0. Если автоматическая очистка отключена, в стек помещается значение 0.

См. также: Clear
Distinct
Интерпретирует вершину стека как запись, созданную с помощью инструкции MakeRecord. P1 — курсор таблицы, в которой объявлен индекс. Если эта таблица содержит запись, которая совпадает с вершиной стека, инструкция завершается. Если в P1 отсутствует запись, которая совпадает с вершиной стека, выполняется переход на P2.

Если совпадающая запись существует, курсор указывает на нее по завершении инструкции. Запись, которая находится на вершине стека, не извлекается из него.

Эта инструкция аналогична инструкции NotFound, но не извлекает ключ из стека.

Эта инструкция реализует команду DISTINCT оператора SELECT. Таблица P1 является не индексом, а записью, которая содержит все результаты, созданные на текущий момент.

См. также: Found, NotFound, IsUnique, NotExists
Divide
Извлекает из стека два элемента, делит первый элемент (который находился на вершине стека) на второй элемент (следующий в стеке) и записывает результат в стек. Если элемент является строкой, перед делением он преобразуется в вещественное число типа double с помощью функции atof(). При делении на ноль возвращается значение NULL. Если какой-либо из элементов равен NULL, результат равен NULL.
DropIndex
Удаляет внутренние структуры данных (в памяти), которые описывают индекс P3 базы данных P1. Эта инструкция вызывается после удаления индекса для согласования внутреннего представления схемы с содержимым диска.
DropTable
Удаляет внутренние структуры данных (в памяти), которые описывают таблицу P3 базы данных P1. Эта инструкция вызывается после удаления таблицы для согласования внутреннего представления схемы с содержимым диска.
DropTrigger
Удаляет внутренние структуры данных (в памяти), которые описывают триггер P3 базы данных P1. Эта инструкция вызывается после удаления триггера для согласования внутреннего представления схемы с содержимым диска.
Dup
Копирует элемент стека с номером P1 и помещает его на вершину стека. Поскольку элемент на вершине стека имеет номер 0, инструкция Dup 0 0 0 создает копию вершины стека.

Если элемент с номером P1 является динамически создаваемой строкой, она копируется при условии, что операнд P2 равен 0. В противном случае копируется только указатель на строку.

См. также Pull.
Eq
Извлекает из стека два верхних элемента, переходит к инструкции P2, если они равны, либо к следующей инструкции в противном случае.

Если бит 0x100 P1 равен 1 и любой из операндов равен NULL, выполняется переход. Если бит 0x100 P1 равен 0 и любой из операндов равен NULL, инструкция завершается.

Если бит 0x200 P1 равен 1 и любой из операндов равен NULL, оба операнда преобразуются в целые числа перед сравнением. Значения NULL преобразуются в 0, а все остальные значения — в 1. Таким образом, если бит 0x200 равен 1, сравнение NULL==NULL дает результат true, в противном случае — NULL. Аналогично, сравнение NULL==123 дает результат false, если бит 0x200 P1 равен 1, и NULL, если он равен 0.

В младшем байте P1 (маска 0xff) должен быть указан символ, который соответствует рекомендуемому типу данных (n, t, i или o), либо значение 0x00. Перед сравнением выполняется попытка преобразовать оба значения к рекомендуемому типу данных. Если байт равен 0x00, применяется рекомендуемый тип NUMERIC.

Если после преобразований ни одно из значений не равно NULL, значения сравниваются друг с другом. Если оба значения имеют тип BLOB или TEXT, результат сравнения определяется функцией memcmp(). Если оба значения являются числами, выполняется числовое сравнение. Если значения имеют другие типы, они считаются неравными.

Если операнд P2 равен 0, переход не выполняется, а в стек помещается целое число 1, если условие перехода выполнено, и 0 в противном случае. Если какой-либо операнд равен NULL, в стек помещается значение NULL.

Если значение P3 не равно NULL, оно является указателем на порядок сортировки (структуру CollSeq), которая определяет метод сравнения текста.
Expire
Аннулирует ранее скомпилированные операторы. При попытке выполнить аннулированный оператор с помощью функции sqlite3_step() возникает ошибка с кодом QDB_SCHEMA.

Если операнд P1 равен 0, аннулируются все операторы SQL, в противном случае — только оператор, который выполняется в текущий момент.
FifoRead
Выполняет попытку чтения одного целого значения из буфера FIFO и его записи в стек. Если буфер FIFO пуст, вместо записи в стек выполняется переход на P2.
FifoWrite
Помещает целое число, которое находится на вершине стека, в буфер FIFO.
ForceInt
Преобразует вершину стека в целое число. Если текущая вершина стека содержит не число, а NULL или строку, которую невозможно преобразовать в целое или вещественное число, это значение извлекается из стека, а управление передается инструкции P2. Если вершина стека содержит числовое значение, оно преобразуется в наименьшее целое число, которое больше или равно этому значению, если операнд P1 равен 0, или строго больше этого значения, если P1 равен 1.
Found
На вершине стека находится значение BLOB, которое создано с помощью инструкции MakeRecord, а P1 является индексом. Если в P1 существует запись, которая совпадает с вершиной стека, управление передается инструкции P2, в противном случае инструкция завершается. По окончании курсор P1 указывает на совпадающую запись, если она существует. Значение BLOB извлекается из вершины стека.

Эта инструкция используется для реализации оператора IN, в левой части которого находится оператор SELECT. P1 является не обычным, а временным индексом, в котором хранятся результаты оператора SELECT. Эта инструкция проверяет наличие левой части оператора IN (которая хранится на вершине стека) в результатах оператора SELECT.

См. также: Distinct, NotFound, IsUnique, NotExists
Function
Вызывает пользовательскую функцию, определенную в структуре Function, на которую ссылается указатель P3, с аргументами P2, извлеченными из стека. Результат функции помещается в стек.

P1 — 32-разрядная битовая маска, которая указывает, является ли каждый аргумент функции константой на этапе компиляции. Если первый аргумент является константой, бит 0 операнда P1 становится равным 1. Он позволяет оценивать надежность сохранения метаданных, которые связаны с аргументом пользовательской функции при помощи API sqlite3_set_auxdata(), до следующего вызова этой инструкции.

См. также: AggStep, AggFinal
Ge
Эта инструкция работает аналогично Eq, но выполняет переход, если элемент, который находится под вершиной стека, не меньше вершины стека. Дополнительную информацию см. в описании инструкции Eq.
Gosub
Помещает текущий адрес + 1 в стек адресов возврата и выполняет переход по адресу P2.

Стек адресов возврата имеет ограниченную глубину. Если количество операций OP_Gosub значительно превышает количество операций OP_Return, стек адресов возврата переполняется и обработка завершается с неустранимой ошибкой.
Goto
Безусловный переход по адресу P2. Следующей выполняется инструкция с индексом P2 от начала программы.
Gt
Эта инструкция работает аналогично Eq, но переход выполняется, если элемент, который находится под вершиной стека, больше вершины стека. Дополнительную информацию см. в описании инструкции Eq.
Halt
Немедленно завершает работу программы. Все открытые курсоры и буферы FIFO закрываются автоматически.

P1 — код результата, который возвращает функция sqlite3_exec(), sqlite3_reset() или sqlite3_finalize(). При нормальном завершении этот код равен QDB_OK (0). Ненулевое значение возвращается при ошибке. Если значение P1 не равно нулю, P2 определяет, выполняется ли откат текущей транзакции: Если P2 равен OE_Fail, откат не выполняется; если P2 равен OE_Rollback, откат выполняется. Если P2 равен OE_Abort, все изменения, которые были внесены при текущем выполнении VDBE, аннулируются без отката транзакции.

Если операнд P3 не равен NULL, он содержит строку с сообщением об ошибке.

Инструкция Halt 0 0 0 неявно вставляется в конец каждой программы, поэтому переход за пределы последней инструкции программы эквивалентен выполнению команды Halt.
HexBlob
P3 содержит шестнадцатеричный код объекта типа BLOB в формате UTF-8 SQL. Этот объект помещается в стек VDBE.

При первом выполнении эта инструкция преобразуется в инструкцию Blob, где указанный объект является операндом P3.
IdxDelete
На вершине стека находится ключ индекса, созданный с помощью инструкции MakeIdxKey. Эта инструкция удаляет соответствующую запись из индекса.
IdxGE
На вершине стека находится запись индекса без идентификатора строки. Эта инструкция сравнивает вершину стека с индексом, на который в текущий момент указывает операнд P1. Идентификатор строки в индексе P1 игнорируется.

Если запись индекса P1 не меньше значения на вершине стека, выполняется переход на P2, в противном случае управление передается следующей инструкции. В любом случае запись в стек выполняется один раз.

Если P3 содержит строку "+" (или другую строку, которая не равна NULL), индекс, который считывается из вершины стека, перед сравнением временно увеличивается на бесконечно малую величину. Эта инструкция работает аналогично IdxGT с одним исключением: если ключ, который считывается из стека, предшествует ключу, который находится в курсоре, результат сравнения равен false, в то время как в инструкции IdxGT он равен true.
IdxGT
На вершине стека находится запись индекса без идентификатора строки. Эта инструкция сравнивает вершину стека с индексом, на который в текущий момент указывает операнд P1. Идентификатор строки в индексе P1 игнорируется.

Количество столбцов на вершине стека может быть меньше P1.

Если запись индекса P1 больше значения на вершине стека, выполняется переход на P2, в противном случае управление передается следующей инструкции. В любом случае запись в стек выполняется один раз.
IdxInsert
На вершине стека находится ключ индекса SQL, созданный с помощью инструкции MakeIdxKey. Эта инструкция записывает указанный ключ в индекс P1. Данные записи равны NULL.

Эта инструкция работает только с индексами. Для таблиц предусмотена аналогичная инструкция с именем OP_Insert.
IdxIsNull
На вершине стека находится запись индекса, созданная с помощью инструкции MakeIdxKey. Инструкция IdxIsNull проверяет первые поля P1 этого ключа, и если хотя бы одно из них равно NULL, передает управление по адресу P2, в противном случае — следующей инструкции.

Запись индекса всегда извлекается из стека.
IdxLT
На вершине стека находится запись индекса без идентификатора строки. Эта инструкция сравнивает вершину стека с индексом, на который в текущий момент указывает операнд P1. Идентификатор строки в индексе P1 игнорируется.

Если запись индекса P1 меньше значения на вершине стека, выполняется переход на P2, в противном случае управление передается следующей инструкции. В любом случае запись в стек выполняется один раз.

Если P3 содержит строку "+" (или другую строку, которая не равна NULL), индекс, который считывается из вершины стека, перед сравнением временно увеличивается на бесконечно малую величину. Таким образом, эта инструкция работает аналогично IdxLE.
IdxRowid
Помещает в стек целое число, равное последнему элементу последней записи ключа индекса, на который указывает курсор P1. Это число должно быть идентификатором строки таблицы, на которую ссылается элемент индекса.

См. также: Rowid.
If
Извлекает из стека одно логическое значение. Если оно имеет значение true, выполняется переход на P2, в противном случае — на следующую инструкцию. Нулевое целое число считается равным false, ненулевое — равным true. Строка с нулевой длиной считается равной false, другие строки — равными true.

Если извлеченное из стека значение равно NULL, то переход выполняется при условии, что операнд P1 равен true; если P1 равен false, управление передается следующей инструкции.
IfMemPos
Если значение ячейки памяти P1 больше или равно 1, выполняется переход на P2. Эта инструкция рассчитана на то, что в ячейке памяти P1 хранится целое значение.
IfNot
Извлекает из стека одно логическое значение. Если оно имеет значение false, выполняется переход на P2, в противном случае — на следующую инструкцию. Нулевое целое число считается равным false, ненулевое — равным true. Строка с нулевой длиной считается равной false, другие строки — равными true.

Если извлеченное из стека значение равно NULL, то переход выполняется при условии, что P1 равно true; если P1 равен false, управление передается следующей инструкции.
Insert
Записывает элемент в таблицу курсора P1. Если элемент не существует, инструкция создает его; в противном случае новые данные записываются в существующий элемент вместо текущих. Данные находятся на вершине стека. Ключ — целое число, которое размещается в стеке под данными. Эта инструкция дважды извлекает содержимое из стека.

Если установлен флаг OPFLAG_NCHANGE операнда P2, счетчик изменений строки инкрементируется (в противном случае не инкрементируется). Если флаг OPFLAG_LASTROWID операнда P2 установлен, идентификатор строки сохраняется для последующего возврата функцией sqlite3_last_insert_rowID(); если указанный флаг не установлен, идентификатор не изменяется.

Эта инструкция работает только с таблицами. Для индексов предусмотена аналогичная инструкция с именем OP_IdxInsert.
Int64
P3 — строковое представление целого числа. Эта инструкция преобразует целое число в 64-разрядную форму и помещает его в стек.
Integer
Помещает в стек 32-разрядное целое значение P1.
IntegrityCk
Анализирует базу данных, которая открыта в текущий момент, и помещает в стек сообщение об ошибке либо слово ok при отсутствии ошибок.

Номера корневых страниц всех таблиц базы данных являются целочисленными значениями, которые размещены в стеке. Эта инструкция извлекает из стека максимально возможное количество целых чисел и использует их как номера корневых страниц.

Если операнд P2 не равен 0, проверяется файл не главной, а вспомогательной базы данных.

Эта инструкция предназначена только для тестирования.
IsNull
Если хотя бы одно из abs( P1 ) верхних значений в стеке равно NULL, выполняется переход на P2. Если P1 больше 0, из стека извлекаются P1 значений; в противном случае стек не изменяется.
IsUnique
На вершине стека находится целочисленный номер записи (обозначим его R). Следующим элементом в стеке является ключ индекса, созданный с помощью инструкции MakeIdxKey (обозначим его K). Эта инструкция извлекает из стека R, но не изменяет K.

А P1 является индексом. Он не содержит данные, а в его ключе находится запись, которая сгенерирована инструкцией OP_MakeRecord. Последнее поле этой записи содержит идентификатор строки, на которую указывает индекс.

Эта инструкция ищет в P1 запись, поле которой равно K, но идентификатор строки не равен R. При отсутствии такой записи немедленно выполняется переход на P2. Если хотя бы одна указанная запись существует, ее номер помещается в стек и управление передается следующей инструкции. См. также: Distinct, NotFound, NotExists, Found
Last
Следующий вызов инструкции Rowid, Column или Next перемещает P1 на последнюю запись таблицы или индекса базы данных. Если таблица или индекс пусты и P2 больше 0, немедленно выполняется переход на P2. Если P2 равен 0 либо таблица или индекс непусты, управление передается следующей инструкции.
Le
Эта инструкция работает аналогично Eq, но переход выполняется, если элемент, который находится под вершиной стека, меньше или равен вершине стека.

См. также Eq.
LoadAnalysis
Считывает таблицу sqlite_stat1 базы данных P1 и загружает содержимое этой таблицы во внутреннюю хеш-таблицу индексов. Загруженная справочная информация применяется при подготовке последующих запросов.
Lt
Эта инструкция работает аналогично Eq, но переход выполняется, если элемент, который находится под вершиной стека, меньше вершины стека.

См. также Eq.
MakeRecord
Преобразует abs( P1 ) верхних элементов стека в один элемент, который можно использовать в качестве записи таблицы базы данных или ключа индекса. Формат записи не имеет значения, если инструкция OP_Column впоследствии может успешно декодировать ее, а функция sqlite3VdbeRecordCompare() корректно сравнивает две кодированные записи. Подробнее о формате записи см. в комментариях в исходном коде.

Исходные элементы извлекаются из стека, если P1 больше 0, и остаются в стеке, если P1 меньше 0.

Если P2 не равен 0 и хотя бы один из элементов равен NULL, выполняется переход по адресу P2. Эта функция позволяет обходить проверку уникальности индексов.

P3 может являться строкой, состоящей из P1 символов. В этой строке символ с номером n задает рекомендуемый тип данных столбца, который применяется к полю ключа индекса с номером n (т.е. первый символ P3 соответствует нижнему элементу стека).

Рекомендуемые типы данных обозначаются следующими символами: Если P3 равен NULL, все поля индекса имеют рекомендуемый тип данных NONE.
MakeRecordI
Эта инструкция работает аналогично OP_MakeRecord, но считывает из стека дополнительное целое число (т.е. суммарное количество значений, считываемых из стека, равно abs( P1 + 1 )) и добавляет его в конец записи как вариант. Результатом инструкции является ключ индекса.
MemIncr
Инкрементирует целое число, которое хранится в ячейке памяти P1. Если P2 не равен 0 и результат инкрементирования равен 1, выполняется переход на P2.

Если в памяти находится не целое число, эта инструкция возвращает ошибку.
MemInt
Помещает целое значение P1 в ячейку памяти P2.
MemLoad
Помещает в стек копию значения, которое хранится в ячейке памяти P1.

Если это значение является строкой, в стек помещается указатель на нее. Если содержимое памяти впоследствии изменяется с помощью инструкции OP_MemStore, значение в стеке также изменяется.
MemMax
Записывает в ячейку памяти P1 ее текущее значение или значение на вершине стека в зависимости от того, какое из них больше. Стек не изменяется.

Если в памяти находится не целое число, эта инструкция возвращает ошибку.
MemMove
Перемещает содержимое ячейки памяти P2 в ячейку P1. Прежнее содержимое P1 стирается, а в P2 остается значение NULL.
MemNull
Записывает значение NULL в ячейку памяти P1.
MemStore
Записывает вершину стека в ячейку памяти P1. Значение P1 должно быть небольшим целым числом, поскольку место в памяти выделяется для всех ячеек в диапазоне [0; P1] включительно.

После сохранения в памяти исходные данные извлекаются из стека, если P2 равен 1, и остаются в стеке, если P2 равен 0.
MoveGe
Извлекает данные из вершины стека и использует их в качестве ключа. Курсор P1 перемещается на наименьший элемент, который больше или равен ключу, извлеченному из стека. Если не существует ни одной записи, которая больше или равна ключу, и значение P2 не равно 0, выполняется переход на P2.

См. также: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe.
MoveGt
Извлекает данные из вершины стека и использует их в качестве ключа. Курсор P1 перемещается на наименьший элемент, который больше ключа, извлеченного из стека. Если не существует ни одной записи, которая больше ключа, и значение P2 не равно 0, выполняется переход на P2.

См. также: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe.
MoveLe
Извлекает данные из вершины стека и использует их в качестве ключа. Курсор P1 перемещается на наибольший элемент, который меньше или равен ключу, извлеченному из стека. Если не существует ни одной записи, которая меньше или равна ключу, и значение P2 не равно 0, выполняется переход на P2.

См. также: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt.
MoveLt
Извлекает данные из вершины стека и использует их в качестве ключа. Курсор P1 перемещается на наибольший элемент, который меньше ключа, извлеченного из стека. Если не существует ни одной записи, которая меньше ключа, и значение P2 не равно 0, выполняется переход на P2.

См. также: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe.
Multiply
Извлекает два верхних элемента из стека, перемножает их и помещает результат в стек. Если элемент является строкой, перед умножением он преобразуется в вещественное число типа double с помощью функции atof(). Если какой-либо из элементов равен NULL, результат равен NULL.
MustBeInt
Преобразует значение на вершине стека в целое число. Если значение не является целым и не может быть преобразовано в целочисленную форму без потерь, немедленно выполняется переход на P2 либо генерируется исключение QDB_MISMATCH, если P2 равен 0.

Вершина извлекается из стека, если она не является целым числом, P2 не равен 0 и P1 равен 1; в остальных случаях глубина стека не изменяется.
Ne
Эта инструкция работает аналогично Eq, но переход выполняется в случае, если извлеченные из стека операнды не равны.

См. также Eq.
Negative
Интерпретирует вершину стека как число и заменяет его на противоположное значение этого числа. Если вершина стека содержит значение NULL, оно не изменяется.
NewRowid
Получает новый (неиспользуемый) целочисленный номер записи (rowid) для использования в качестве ключа таблицы базы данных, на которую указывает курсор P1. Новый номер записи помещается в стек.

Если значение P2 больше 0, P2 является ячейкой памяти, в которой хранится наибольший из сгенерированных номеров записей. Новые номера записей должны быть больше этого значения. При достижении максимально допустимого значения номера возникает ошибка QDB_FULL. Сгенерированный новый номер записи записывается в ячейку памяти P2. Операнд P2 используется для реализации функции AUTOINCREMENT.
Next
Перемещает курсор P1 на следующую пару ключ/данные в таблице или индексе. Если курсор указывает на последнюю пару ключ/данные, управление передается следующей инструкции; если курсор перемещен успешно, немедленно выполняется переход на P2.

См. также: Prev.
Noop
Не выполняет никаких действий. Эта инструкция часто используется в качестве адреса перехода.
Not
Интерпретирует вершину стека как логическое значение и заменяет его дополнительным кодом этого значения. Если вершина стека содержит значение NULL, оно не изменяется.
NotExists
Интерпретирует вершину стека как целочисленный ключ. Если запись с этим ключом отсутствует в таблице P1, выполняется переход на P2. Если запись существует, управление передается следующей инструкции, а курсор указывает на существующую запись. Целочисленный ключ извлекается из стека.

В инструкции NotExists ключ является целым числом, а P1 — таблицей; этим NotExists отличается от NotFound, где ключ представляет собой объект BLOB, созданный с помощью инструкции MakeRecord, а P1 — индекс.

См. также: Distinct, Found, NotFound, IsUnique.
NotFound
На вершине стека находится значение BLOB, которое создано с помощью инструкции MakeRecord, а P1 является индексом. Если в P1 нет ни одной записи, которая совпадает с объектом BLOB, выполняется переход на P1; если такая запись существует, управление передается следующей инструкции, а курсор указывает на обнаруженную запись. Объект BLOB извлекается из стека.

Отличие этой инструкции от Distinct заключается в том, что Distinct не извлекает ключ из стека.

См. также: Distinct, Found, NotExists, IsUnique.
NotNull
Выполняет переход на P2, если P1 значений в верхней части стека не равны NULL. Если P1 больше 0, из стека извлекаются P1 значений; в противном случае стек не изменяется.
Null
Помещает в стек значение NULL.
NullRow
Перемещает курсор P1 на NULL-строку. Все операции OP_Column, которые выполняются, когда курсор указывает на NULL-строку, помещают в стек значение NULL.
OpenPseudo
Открывает новый курсор, который указывает на искусственную таблицу с единственной строкой данных. При попытке записи во вторую строку данных удаляется первая строка, а при закрытии курсора удаляются все данные.

Эта инструкция создает псевдотаблицу, в которой удобно хранить таблицы триггера NEW и OLD.
OpenRead
Открывает курсор только для чтения таблицы с корневой страницей P2 в файле базы данных. Файл базы данных определяется целым числом, которое считывается из вершины стека: 0 соответствует главной базе данных, а 1 — базе данных временных таблиц. Новому курсору присваивается идентификатор P1. Все значения P1 должны быть небольшими целыми числами (не обязательно непрерывными); отрицательные значения недопустимы.

Если P2 равен 0, номер корневой страницы считывается из следующего элемента стека.

При наличии открытого курсора операции чтения базы данных блокируются. Если база данных разблокируется перед этой инструкцией, в процессе ее выполнения осуществляется повторная блокировка. Блокировка чтения позволяет другим процессам читать содержимое базы данных, но запрещает изменять его. Блокировка чтения удаляется после закрытия всех курсоров. Если эта инструкция предпринимает неудачную попытку выполнить блокировку чтения, сценарий завершается с кодом ошибки EBUSY.

Операнд P3 является указателем на структуру KeyInfo, в которой определены содержимое и порядок сортировки индексов. P3 равен NULL, если курсор не указывает на индекс.

См. также OpenWrite.
OpenVirtual
Открывает новый курсор P1, который указывает на временную или виртуальную таблицу. Курсор всегда открыт для чтения и записи, даже если главная база данных доступна только для чтения. Временная или виртуальная таблица автоматически удаляется при закрытии курсора.

P2 — количество столбцов в виртуальной таблице. Курсор указывает на таблицу BTree, если P3 равен 0, или на индекс BTree, если P3 не равен 0. Если операнд P3 не равен NULL, он указывает на структуру KeyInfo, в которой определен формат ключей индекса.
OpenWrite
Открывает курсор с именем P1 для чтения/записи таблицы или индекса с корневой страницей P2. Если P2 равен 0, номер корневой страницы считывается из элемента стека.

Операнд P3 является указателем на структуру KeyInfo, в которой определены содержимое и порядок сортировки индексов. P3 равен NULL, если курсор не указывает на индекс.

Эта инструкция работает аналогично OpenRead, но открывает курсор в режиме чтения/записи. Для одной таблицы можно открывать один или несколько курсоров чтения либо один курсор чтения/записи, но не оба типа курсоров одновременно.

См. также OpenRead.
Or
Извлекает из стека два значения, применяет к ним операцию логического ИЛИ и записывает в стек результат типа boolean.
ParseSchema
Считывает и анализирует все записи таблицы QDB_MASTER базы данных P1, которые соответствуют условию WHERE P3.

Эта инструкция реентерабельна — она вызывает анализатор, который создает новую виртуальную машину, а затем запускает ее.
Pop
Извлекает P1 элементов из вершины стека и удаляет их.
Prev
Перемещает курсор P1 на предыдущую пару ключ/данные соответствующей таблицы или индекса. Если эта пара не существует, управление передается следующей инструкции. Если курсор успешно перемещен, немедленно выполняется переход на P2.
Pull
Переносит элемент с номером P1 из текущего местоположения в стеке на его вершину. Поскольку вершина стека имеет номер 0, инструкция Pull 0 0 0 не выполняет никаких действий. Инструкция Pull 1 0 0 меняет местами два верхних элемента стека.

См. также Dup.
Push
Записывает значение вершины стека в элемент с номером P1 (нулевое значение P1 указывает на вершину стека) и извлекает вершину стека.
ReadCookie
Считывает и помещает в стек cookie с номером P2 базы данных P1. P2 == 0 соответствует версии схемы, P2 == 1 — формату базы данных, P2 == 2 — рекомендуемому размеру кеша страничной навигации и т.д. P1 == 0 соответствует главному файлу базы данных, P1 == 1 — файлу базы данных, в котором хранятся временные таблицы.

Перед выполнением этой инструкции база данных должна быть блокирована для чтения (посредством запуска транзакции или открытия курсора).
Real
Преобразует строковое значение P3 в вещественное число и помещает его в стек.
Remainder
Извлекает из стека два элемента, делит первый элемент (который находился на вершине стека) на второй элемент (следующий в стеке) и записывает остаток от деления в стек. Если элемент является строкой, перед делением он преобразуется в вещественное число типа double с помощью функции atof(). При делении на ноль возвращается значение NULL. Если какой-либо из элементов равен NULL, результат равен NULL.
ResetCount
Эта инструкция сбрасывает внутренний счетчик изменений виртуальной машины в ноль. Если операнд P1 равен true, значение счетчика изменений копируется в счетчик изменений дескриптора базы данных (возвращаемый последующими вызовами функции sqlite3_changes()) перед сбросом. Эта инструкция используется в программах-триггерах.
Return
Немедленно переходит к инструкции, следующей за последней операцией OP_Gosub, из которой не выполнен возврат. Если операция OP_Return выполнена для всех операций OP_Gosub, обработка завершается с неустранимой ошибкой.
Rewind
Следующий вызов инструкции Rowid, Column или Next перемещает P1 на первую запись таблицы или индекса базы данных. Если таблица или индекс пусты и P2 больше 0, немедленно выполняется переход на P2. Если P2 равен 0 либо таблица или индекс непусты, управление передается следующей инструкции.
RowData
Помещает в стек все данные строки, на которую указывает курсор P1. Данные не интерпретируются, а только копируются в стек в том виде, в котором хранятся в файле базы данных.

Если курсор не указывает на корректную строку, в стек помещается значение NULL.
Rowid
Помещает в стек целочисленный ключ записи таблицы, на которую в текущий момент указывает P1.
RowKey
Помещает в стек ключ всей строки, на которую указывает курсор P1. Ключ не интерпретируется, а только копируется в стек в том виде, в котором хранится в файле базы данных.

Если курсор не указывает на корректную строку, в стек помещается значение NULL.
Sequence
Помещает в стек наименьший свободный целочисленный порядковый номер для курсора P1, а затем инкрементирует этот номер.
SetCookie
Записывает вершину стека в cookie с номером P2 базы данных P1. P2 == 0 соответствует версии схемы, P2 == 1 — формату базы данных, P2 == 2 — рекомендуемому размеру кеша страничной навигации и т.д. P1 == 0 соответствует главному файлу базы данных, P1 == 1 — файлу базы данных, в котором хранятся временные таблицы.

Перед выполнением этой инструкции необходимо запускать транзакцию.
SetNumColumns
Эту инструкцию необходимо вызывать для задания количества полей в таблице перед выполнением операции OP_Column над курсором.

Инструкция устанавливает количество столбцов курсора P1 равным P2.

Если к курсору P1 необходимо применить операцию OP_KeyAsData, она должна быть вызвана перед этой инструкцией.
ShiftLeft
Извлекает из стека два верхних элемента, преобразует их в целые числа и записывает в стек второй элемент, сдвинутый на N разрядов влево, где N — верхний элемент стека. Если какой-либо из элементов равен NULL, результат равен NULL.
ShiftRight
Извлекает из стека два верхних элемента, преобразует их в целые числа и записывает в стек второй элемент, сдвинутый на N разрядов вправо, где N — верхний элемент стека. Если какой-либо из элементов равен NULL, результат равен NULL.
Sort
Эта инструкция аналогична OP_Rewind, но инкрементирует недокументированную глобальную переменную, которая используется для тестирования.

В процессе сортировки записи помещаются в индекс, который перематывается и воспроизводится от начала до конца. Мы выполняем перемотку с использованием операции OP_Sort вместо OP_Rewind, чтобы инкрементировать глобальную переменную и проверять корректность оптимизации сортировки посредством регрессионных тестов.
Statement
Запускает транзакцию отдельного оператора в составе более крупной транзакции BEGIN..COMMIT. При возникновении ошибки эта инструкция позволяет откатывать оператор, а не всю транзакцию. Транзакция оператора автоматически фиксируется при останове VDBE.

Запускаемый оператор выполняется над файлом базы данных с индексом P1. Главный файл базы данных имеет индекс 0, а файл, в котором хранятся временные таблицы — индекс 1.
String
Строковое значение P3 помещается в стек. Если P3 равен 0, в стек помещается значение NULL. P3 интерпретируется как строка, представленная во внутренней кодировке базы данных, с нулевым символом на конце.
String8
P3 указывает на строку UTF-8 с нулевым символом на конце. Перед первым выполнением эта инструкция преобразуется в OP_String.
Subtract
Извлекает из стека два элемента, вычитает первый элемент (который находился на вершине стека) из второго элемента (следующего в стеке) и записывает результат в стек. Если элемент является строкой, перед вычитанием он преобразуется в вещественное число типа double с помощью функции atof(). Если какой-либо из элементов равен NULL, результат равен NULL.
ToBlob
Преобразует значение, которое хранится на вершине стека, в объект BLOB. Числовое значение сначала преобразуется в строку. Строки не преобразуются, а интерпретируются как объекты BLOB.

Значение NULL не изменяется.
ToInt
Преобразует значение, которое хранится на вершине стека, в целое число. Если значение является вещественным, его дробная часть отбрасывается. Если значение является текстом или объектом BLOB, выполняется попытка преобразовать его в целое число с помощью эквивалента функции atoi(); если такое преобразование невозможно, сохраняется значение 0.

Значение NULL не изменяется.
ToNumeric
Преобразует значение на вершине стека в число (целое или с плавающей точкой). Если значение является текстом или объектом BLOB, выполняется попытка преобразовать его в целое число с помощью эквивалента функции atoi() или atof(); если такое преобразование невозможно, сохраняется значение 0.

Значение NULL не изменяется.
ToText
Преобразует значение, которое хранится на вершине стека, в текст. Если значение является числом, оно преобразуется в последовательность символов с помощью эквивалента функции printf(). Объекты BLOB не изменяются и интерпретируются как текст.

Значение NULL не изменяется.
Transaction
Запускает транзакцию. Транзакция завершается с помощью инструкции Commit или Rollback. В зависимости от параметра ON CONFLICT возможен откат транзакции при возникновении ошибки.

P1 — индекс файла базы данных, который обрабатывается запускаемой транзакцией. Индекс 0 соответствует главному файлу базы данных, а индекс 1 — файлу для хранения временных таблиц.

Если P2 не равен 0, запускается транзакция записи, при этом на файл базы данных устанавливается блокировка RESERVED. Другие процессы не могут запускать новые транзакции записи до окончания текущей транзакции. При запуске транзакции записи также создается журнал отката. Запуск транзакции записи предшествует внесению любых изменений в базу данных. Если P2 больше или равен 2, на файл также устанавливается блокировка EXCLUSIVE.

Если P2 равен 0, на файл базы данных устанавливается блокировка чтения.
Vacuum
Полностью очищает базу данных. Эта инструкция создает и запускает другие виртуальные машины. Ее нельзя вызывать из транзакции.
Variable
Помещает значение переменной P1 в стек. Переменная является неизвестным в исходной строке SQL, которая передается в функцию sqlite3_compile(). Знак "?" в исходной строке SQL интерпретируется как переменная. Переменные в строке SQL нумеруются слева направо, начиная с 1. Значения переменных задаются с помощью вызова sqlite3_bind().
VerifyCookie
Проверяет, равно ли значение глобального параметра базы данных с номером 0 (версии схемы) операнду P2. P1 — номер базы данных; значение 0 соответствует главному файлу, 1 — файлу временных таблиц, последующие числа — вспомогательным базам данных.

Значение cookie изменяется при изменении схемы базы данных. С помощью этой инструкции текущий процесс обнаруживает, что cookie изменился и требуется повторно считать схему.

Перед вызовом этой инструкции должна быть запущена транзакция либо выполнена операция OP_Open (для установки блокировки чтения).




Предыдущий раздел: перейти