SQLite字节码引擎(十二)

 

返回:SQLite—系列文章目录   

上一篇:SQLite的架构(十一)()

下一篇:SQLite—系列文章目录   

 

1、 摘要

SQLite 的工作原理是将 SQL 语句转换为字节码和 然后在虚拟机中运行该字节码。本文档 描述字节码引擎的工作原理。

本文档介绍SQLite内部结构。所提供的信息 使用 SQLite 进行常规应用程序开发不需要此处。 本文档适用于想要更深入地研究的人 SQLite的内部操作。

字节码引擎不是 SQLite 的 API。详 关于字节码引擎从一个版本到下一个版本的更改。 使用 SQLite 的应用程序不应依赖于任何细节 在本文档中找到。

2. 引言

SQLite 的工作原理是将每个 SQL 语句转换为字节码和 然后运行该字节码。 SQLite中的预处理语句大多只是所需的字节码 实现相应的 SQL。sqlite3_prepare_v2() 接口 是将 SQL 转换为字节码的编译器。 sqlite3_step() 接口是运行 准备好的语句中包含的字节码。

字节码虚拟机是 SQLite 的核心。 想要了解SQLite内部如何运作的程序员 必须熟悉字节码引擎。

从历史上看,SQLite 中的字节码引擎称为 “虚拟数据库引擎”或“VDBE”。本网站使用这些条款 “字节码引擎”、“VDBE”、“虚拟机”和“字节码虚拟” 机器“可以互换,因为它们的意思都是一样的。

本文还使用了术语“字节码程序”和 “准备好的语句”可以互换,因为它们大多是一回事。

2.1. VDBE源代码

字节码引擎的源代码位于 vdbe.c 源代码中 文件。本文档中的操作码定义是派生的 来自该源文件中的注释。这 源代码注释是规范的信息来源 关于字节码引擎。如有疑问,请参阅源代码。

除了主 vdbe.c 源代码文件外,还有 源代码树中的其他帮助程序代码文件,其名称均为 以“vdbe”开头 - “Virtual DataBase Engine”的缩写。

请记住,操作码的名称和含义经常从 一个版本的 SQLite 到下一个版本。因此,如果您正在研究 SQLite 的 EXPLAIN 输出,则应参考本文档的版本 (或 vdbe.c 源代码) 对应于运行 EXPLAIN 的 SQLite 版本。 否则,操作码的描述可能不准确。 本文档源自 SQLite 版本 3.45.2 入住日期为 2024-03-12 的 D8CD6D49B46A3

2.2. 指令格式

SQLite中的字节编码程序由一条或多条指令组成。 每条指令都有一个操作码和 五个操作数,分别命名为 P1、P2、P3、P4 和 P5。P1、P2 和 P3 操作数是 32 位有符号整数。这些操作数通常是指 寄存 器。对于在 b 树游标上操作的指令, P1 操作数通常是游标编号。 对于跳转指令,P2 通常是跳转目的地。 P4 可以是 32 位有符号整数、64 位有符号整数、A 64 位浮点值、字符串文本、Blob 文本、 指向排序序列比较函数的指针,或 指向应用程序定义的 SQL 实现的指针 功能,或其他各种东西。P5 是一个 16 位无符号整数 通常用于举旗。P5 标志的位有时会影响 操作码以微妙的方式。例如,如果 P5 操作数的 SQLITE_NULLEQ (0x0080) 位 在 Eq 操作码上设置,则 NULL 值比较 彼此相等。否则,NULL 值会比较不同 彼此之间。

某些操作码使用所有五个操作数。某些操作码使用 一两个。某些操作码不使用任何操作数。

字节码引擎在指令编号 0 上开始执行。 执行将继续进行,直到看到 Halt 指令,或者直到 程序计数器大于 最后一条指令,或直到出现错误。 当字节码引擎停止时,所有内存 它分配的已释放,并且它可能释放所有数据库游标 已经开放了,已经关闭了。如果执行由于 错误,则终止任何待处理事务并进行更改 回滚到数据库。

ResultRow 操作码导致 字节码引擎暂停,相应的 sqlite3_step() 调用返回SQLITE_ROW。在调用 ResultRow 之前,字节编码程序将 已将查询的单行结果加载到序列中 的寄存器。C 语言 API(如 sqlite3_column_int() 或 sqlite3_column_text() )从中提取查询结果 寄存 器。字节码引擎在下一条指令中恢复 在下一次调用的 ResultRow 之后 更改为 sqlite3_step()。

2.3. 寄存器

每个字节码程序都有一个固定的(但可能很大)的 寄存 器。单个寄存器可以保存各种对象:

  • 一个 NULL 值
  • 带符号的 64 位整数
  • IEEE 双精度(64 位)浮点数
  • 任意长度的字符串
  • 任意长度的 BLOB
  • RowSet 对象(请参阅 RowSetAddRowSetRead 和 RowSetTest 操作码)
  • A Frame 对象(由子程序使用 - 参见 Program)

寄存器也可以是“未定义的”,这意味着它没有价值 完全。Undefined 不同于 NULL。取决于编译时间 选项,尝试读取未定义的寄存器通常会导致 运行时错误。如果代码生成器 (sqlite3_prepare_v2()) ever 生成一个准备好的语句,读取一个未定义的寄存器, 这是代码生成器中的一个错误。

寄存器的编号以 0 开头。 大多数操作码至少引用一个寄存器。

单个预处理语句中的寄存器数是固定的 在编译时。当以下情况下,所有寄存器的内容都会被清除 准备好的语句将被重置定稿

内部 Mem 对象存储单个寄存器的值。 API 中公开的抽象sqlite3_value对象实际上是 只是一个 Mem 对象或寄存器。

2.4. B树光标

准备好的语句可以有 零个或多个打开的游标。每个游标都由 小整数,通常是操作码的 P1 参数 使用光标。 可以在同一索引或表上打开多个游标。 所有游标都独立运行,甚至光标指向同一 索引或表。 虚拟机与数据库交互的唯一方式 文件通过光标。 虚拟机中的说明可以创建新游标 (例如:OpenRead 或 OpenWrite), 从游标()读取数据, 将光标移动到表中的下一个条目 (例如:下一个上一个),依此类推。 所有光标都是自动的 当准备好的语句被重置定稿时关闭。

2.5. 子程序、协程和子程序

字节码引擎没有用于存储返回地址的堆栈 子例程。退货地址必须存储在寄存器中。 因此,字节码子例程不是可重入的。

Gosub 操作码将当前程序计数器存储到 然后,寄存器 P1 跳转到地址 P2。返回操作码跳转 以解决 P1+1。因此,每个子例程都与两个整数相关联: 子例程中入口点的地址和寄存器编号 用于保存退货地址。

Yield 操作码将程序计数器的值交换为 寄存器 P1 中的整数值。此操作码用于实现 协程。协程通常用于实现来自 根据需要提取哪些内容。

触发器需要可重入。 由于字节码 子例程不可重入,必须使用不同的机制来 实现触发器。每个触发器都使用单独的字节码实现 程序具有自己的操作码、程序计数器和寄存器集。程序操作码调用触发器子程序。程序说明 为每次调用分配并初始化一个新的寄存器集 子程序,因此子程序可以是可重入的和递归的。子程序使用 Param 操作码来访问寄存器中的内容 调用字节码程序。

2.6. 自更改代码

某些操作码是自动更改的。 例如,Init 操作码(始终是第一个操作码 在每个字节码程序中)递增其 P1 操作数。后续 Once 操作码将其 P1 操作数与 Init 操作码,以确定一次性初始化 应跳过以下代码。 另一个例子是 String8 操作码,它转换其 P4 操作数从 UTF-8 转换为正确的数据库字符串编码,然后 将自身转换为 String 操作码。

3. 查看字节码

SQLite 解释的每个 SQL 语句都会生成一个程序 对于虚拟机。但是,如果 SQL 语句以 关键字 EXPLAIN 虚拟机不会执行 程序。相反,程序的指令将被返回, 每行一条指令, 就像查询结果一样。此功能对于调试和 用于了解虚拟机的运行方式。例如:

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

任何应用程序都可以运行 EXPLAIN 查询来获取类似于 以上。 但是,不会生成显示循环结构的缩进 通过SQLite核心。命令行 shell 包含额外的逻辑 用于缩进循环。 此外,EXPLAIN 输出中的“comment”列 仅当使用 -DSQLITE_ENABLE_EXPLAIN_COMMENTS 选项编译 SQLite 时才提供。

当使用 SQLITE_DEBUG 编译时选项编译 SQLite 时, 额外的 PRAGMA 命令可用于调试和 探索VDBE的运作。例如,可以启用vdbe_trace编译指示,以使每个 VDBE 操作码的反汇编为 在执行操作码时打印在标准输出上。这些调试 编译指示包括:

4. 操作码

目前有 189 个 虚拟机定义的操作码。 下表描述了所有当前定义的操作码。 此表是通过扫描源代码自动生成的 从文件 vdbe.c.

切记:VDBE 操作码不是接口的一部分 SQLite 的定义。操作码的数量及其名称和含义 从SQLite的一个版本更改为下一个版本。 下表中显示的操作码对 SQLite 有效 版本 3.45.2 入住日期为 2024-03-12 的 D8CD6D49B46A3

操作码名称 描述
可中止 验证是否可以发生中止。断言此时是否中止可能会导致数据库损坏。此操作码仅在调试中出现 建立。

如果没有写入,或者有写入,则中止是安全的主动声明日记。

将寄存器 P1 中的值与寄存器 P2 中的值相加并将结果存储在寄存器P3中。 如果任一输入为NULL,则结果为NULL。
添加 Imm 将常量P2添加到寄存器P1中的值中。 结果始终为整数。

要强制任何寄存器为整数,只需添加 0。

亲和力 将亲和力应用于从P1 开始的一系列P2 寄存器。

P4是一个长度为 P2 字符的字符串。的第N个字符 string 指示应用于第N个的列关联存储单元在范围内。

AggFinal(英语:AggFinal P1是作为聚合累加器的内存位置 或窗口函数。执行终结器函数 将结果存储在 P1 中。

P2是步进函数采用的参数数,并且P4是指向此函数的FuncDef 的指针。The P2 此操作码不使用参数。它只是为了消除歧义 可以采用不同数量的参数的函数。这 P4 参数仅在以下情况下需要以前未调用 step 函数。

AggInverse 执行聚合的xInverse函数。 该函数具有P5参数。P4是指向指定函数的FuncDef结构。寄存器P3是蓄电池。

P5参数取自寄存器P2及其接班人。

Agg步骤 执行聚合的xStep函数。 该函数具有P5参数。P4是指向指定函数的FuncDef结构。寄存器P3是蓄电池。

P5参数取自寄存器P2及其接班人。

Agg步骤1 执行 xStep (if P1==0)或 xInverse(if P1!=0) 函数 骨料。该函数具有P5参数。P4 是指向 指定函数的 FuncDef 结构。寄存器 P3 是 蓄电池。

P5 参数取自寄存器 P2 及其 接班人。

此操作码最初编码为 OP_AggStep0。在第一次评估时, 存储在 P4 中的 FuncDef 被转换为sqlite3_context和 操作码已更改。这样,初始化的 sqlite3_context只发生一次,而不是在每次调用 step 函数。

Agg值 调用 xValue()函数并将结果存储在寄存器 P3 中。

P2是步进函数采用的参数数,并且P4是指向此函数的FuncDef的指针。The P2此操作码不使用参数。它只是为了消除歧义可以采用不同数量的参数的函数。这 P4 参数仅在以下情况下需要以前未调用step 函数。

取寄存器 P1和 P2中值的逻辑AND,并取将结果写入寄存器 P3。

如果 P1 或 P2 为 0(false),则结果为 0,即使另一个输入为 NULL。一个NULL和 true或两个NULL给出一个 NULL 输出。

自动提交 将数据库自动提交标志设置为 P1(1 或 0)。如果 P2为true,则滚动返回任何当前处于活动状态的 btree 事务。如果有任何活动 VM(除了这个),则ROLLBACK失败。如果出现以下情况,则 COMMIT 失败有使用共享缓存的活动写入VM或活动 VM。

此指令会导致 VM 停止。

开始Subrtn 标记可内联输入的子例程的开头或者可以使用 Gosub 调用。子例程应由具有 P1 操作数的 Return 指令终止与此操作码的P2操作数相同,并且P3设置为1。 如果子例程是内联输入的,则 Return 将简单地失败。但是,如果使用 Gosub 输入子例程,则返回将跳回 Gosub 之后的第一条指令。

此例程的工作原理是将 NULL加载到P2寄存器中。当返回地址寄存器包含一个 NULL,返回指令为 一个简单地落入下一个指令的无操作(假设返回操作码的 P3 值为1)。因此,如果子程序是内联输入,则 Return 将导致内联执行继续。但是,如果子例程是通过 Gosub 输入的,则 Return 将导致返回到 Gosub 之后的地址。

此操作码与 Null 相同。它有一个不同的名称 只是为了使字节码更易于阅读和验证。

比特和 取寄存器 P1和 P2中值的按位 AND,并取将结果存储在寄存器 P3 中。 如果任一输入为 NULL,则结果为 NULL。
比特不是 将寄存器P1的内容解释为整数。存储将P1值的1补码转换为寄存器 P2。如果 P1 成立 一个 NULL,然后在 P2 中存储一个 NULL。
BitOr 取寄存器 P1 和 P2 中值的按位 OR 并 将结果存储在寄存器 P3 中。 如果任一输入为 NULL,则结果为 NULL。
斑点 P4 指向一个 P1 字节长的数据块。存储此内容 寄存器 P2 中的 blob。如果 P4 是 NULL 指针,则构造 在 P2 中长度为 P1 字节的零填充 Blob。
强制寄存器 P1 中的值为 P2 定义的类型。

  • P2=='A' → BLOB
  • P2=='B' →文本
  • P2=='C' → 数字
  • P2=='D' → INTEGER
  • P2=='E' → 实数

此例程不会更改 NULL 值。它保持 NULL。

检查站 检查点数据库 P1.如果 P1 当前不在,则这是无操作的 WAL 模式。参数 P2 是 SQLITE_CHECKPOINT_PASSIVE、FULL、 重新启动或截断。如果检查点返回,则将 1 或 0 写入 mem[P3] 分别SQLITE_BUSY与否。在 WAL检查点后进入mem[P3+1]和页数 在检查点之后被检查的 WAL 中 完成到 mem[P3+2]。但是,在错误时,mem[P3+1] 和 mem[P3+2] 初始化为 -1。
清楚 删除其根页的数据库表或索引的所有内容 在数据库文件中由 P1 给出。但是,与 Destroy 不同的是,不要 从数据库文件中删除表或索引。

如果 P2==0,则要清除的表位于主数据库文件中。如果 P2==1,则要清除的表位于辅助数据库文件中 用于存储使用 CREATE TEMPORARY TABLE 创建的表。

如果 P3 值不为零,则行更改计数递增 按要清除的表中的行数。如果 P3 大于 比零,则存储在寄存器 P3 中的值也递增 按要清除的表中的行数。

Смотритетакже

关闭 关闭之前以 P1 身份打开的光标。如果 P1 不是 目前开放,此指令是无操作的。
ClrSubtype 从寄存器 P1 中清除子类型。
CollSeq(英语:CollSeq) P4 是指向 CollSeq 对象的指针。如果下次调用用户函数 或聚合调用 sqlite3GetFuncCollSeq(),此排序规则序列将 被退回。这由内置的 min()、max() 和 nullif() 使用 功能。

如果 P1 不为零,则它是一个寄存器,后续 min() 或 如果当前行不是最小值或 max() aggregate 将设置为 1 最大。通过此指令,P1寄存器初始化为0。

实现上述函数时使用的接口 检索此操作码设置的排序规则序列不可用 公然地。只有内置函数才能访问此功能。

将游标 P1 指向的数据解释为使用 MakeRecord 指令。(有关其他操作码,请参阅 MakeRecord 操作码 有关数据格式的信息。提取 P2 列 从这个记录。如果小于 (P2+1) 值,提取 NULL。

提取的值存储在寄存器 P3 中。

如果记录包含的字段少于 P2,则提取 NULL。或 如果 P4 参数是 P4_MEM则使用 P4 参数的值作为 结果。

如果在 P5 中设置了 OPFLAG_LENGTHARG 位,则保证结果 仅由 length() 函数或等效函数使用。内容 不加载大型 Blob,从而节省 CPU 周期。如果 设置OPFLAG_TYPEOFARG位,则结果将仅由 typeof() 函数或 IS NULL 或 IS NOT NULL 运算符或 等效。在这种情况下,可以省略所有内容加载。

列已用 此操作码(仅当 SQLite 编译时才存在 SQLITE_ENABLE_COLUMN_USED_MASK) 标识 使用游标 P1 的表或索引。P4 是一个 64 位整数 (P4_INT64) 其中前 63 位是 实际使用的表或索引的前 63 列 通过光标。如果后面有任何列,则设置高阶位 使用第 64 个。
比较 比较 reg(P1) 中的两个寄存器向量。reg(P1+P3-1) (调用此 向量 “A”) 和 reg(P2) 中。.reg(P2+P3-1) (“B”)。保存结果 供下一个跳转指令使用的比较。

如果 P5 设置了 OPFLAG_PERMUTE 位,则比较顺序为 由最新的排列运算符确定。如果 OPFLAG_PERMUTE位是清楚的,然后依次比较寄存器 次序。

P4 是一个 KeyInfo 结构,用于定义排序序列和排序 用于比较的订单。排列适用于寄存器 只。KeyInfo 元素按顺序使用。

比较是排序比较,所以 NULL 比较相等, NULL 小于数字,数字小于字符串, 字符串小于 blob。

此操作码后必须紧跟跳转操作码。

康卡特 将寄存器 P1 中的文本添加到文本的末尾 注册 P2 并将结果存储在寄存器 P3 中。 如果 P1 或 P2 文本为 NULL,则将 NULL 存储在 P3 中。

P3 = P2 ||小一

P1 和 P3 是同一个寄存器是非法的。有时 如果 P3 与 P2 的寄存器相同,则实现能够 以避免 memcpy()。

复制 制作寄存器 P1 的副本。P1+P3 进入寄存器 P2..P2+P3 中。

如果设置了 P5 的0x0002位,则还要MEM_Subtype清除 目的地。P5 的0x0001位表示此复制操作码不能 被合并。0x0001位由查询规划器使用,而不是 在查询执行期间发挥作用。

此指令对值进行深层复制。重复项 由任何字符串或 blob 常量组成。另请参阅 SCopy

计数 存储表或索引中的条目数(整数值) 由寄存器 P2 中的光标 P1 打开。

如果 P3==0,则获得精确计数,这涉及访问 表的每个 btree 页面。但是,如果 P3 不为零,则估计值 根据当前光标位置返回。

创建Btree 如果 P1==0 或 如果 P1==1,则为 TEMP 数据库文件,如果 P1==1,则在附加数据库中 第 1>1 页。rowid 表的 P3 参数必须为 1 (BTREE_INTKEY) 对于索引或 WITHOUT ROWID 表,它必须为 2 (BTREE_BLOBKEY)。 新 b 树的根页码存储在寄存器 P2 中。
游标提示 向游标 P1 提供提示,表明它只需要返回 满足 P4 中的 Expr。TK_REGISTER P4 表达式中的术语是指 到当前保存在寄存器中的值。P4 中的TK_COLUMN条款 表达式 是指光标 P1 指向的 b 树中的列。
光标锁定 锁定光标 P1 指向的 btree,使 btree 不能 由另一个光标写入。
光标解锁 解锁光标 P1 指向的 btree,以便它可以 由其他光标写入。
DecrJumpZero(十进制跳零) 寄存器 P1 必须保存一个整数。递减 P1 中的值 如果新值正好为零,则跳转到 P2。
延期寻求 P1 是打开索引光标,P3 是相应索引上的光标 桌子。此操作码对 P3 表游标执行延迟寻道 到与 P1 的当前行相对应的行。

这是一个延迟的搜索。实际上什么都没有发生,直到 光标用于读取记录。这样,如果没有读取 发生,不会发生不必要的 I/O。

P4 可以是一个整数数组(类型 P4_INTARRAY),包含 P3 表中每列一个条目。如果数组条目 a(i) 为非零,则从游标 P3 读取列 a(i)-1 为 相当于执行延迟寻道,然后读取第 I 列 从 P1 开始。此信息存储在 P3 中并用于重定向 将 P3 读取到 P1,从而可能避免了 查找并读取光标 P3。

删除 删除 P1 光标当前指向的记录。

如果设置了 P5 参数的OPFLAG_SAVEPOSITION位,则 光标将向左指向下一个或上一个 记录在表中。如果它左指向下一条记录,则 下一个 Next 指令将是 no-op。因此,在这种情况下 可以从 Next 循环中删除记录。如果 OPFLAG_SAVEPOSITION P5 的位是明确的,那么光标将是 处于未定义状态。

如果在 P5 上设置了 OPFLAG_AUXDELETE 位,则表示 delete 是与删除表行相关的几个选项之一,并且 其所有关联的索引条目。这些删除之一就是 “主要”删除。其他人都在OPFLAG_FORDELETE 光标或否则用 AUXDELETE 标志标记。

如果设置了 P2 的OPFLAG_NCHANGE (0x01) 标志(注意:P2 而不是 P5),则 行更改计数递增(否则不递增)。

如果设置了 P2(不是 P5!) 的 OPFLAG_ISNOOP (0x40) 标志,则 运行用于删除的 pre-update-hook,但 btree 在其他方面保持不变。 当 Delete 后面紧跟着具有相同键的 Insert 时,就会发生这种情况,从而导致 btree 条目被覆盖。

P1 不能是伪表。它必须是一张真正的桌子 多行。

如果 P4 不为 NULL,则它指向 Table 对象。在这种情况下,任一 可以调用更新和/或更新前挂钩。P1 光标必须 在调用此操作码之前使用 NotFound 定位 这种情况。具体来说,如果配置了一个,则更新前的钩子是 如果 P4 不为 NULL,则调用。如果配置了 update-hook,则调用 update-hook, P4 不为 NULL,并且 OPFLAG_NCHANGE 标志设置在 P2 中。

如果在 P2 中设置了 OPFLAG_ISUPDATE 标志,则 P3 包含地址 包含行的 rowid 将的值的存储单元格 由更新设置为。

摧毁 删除其根页在数据库中的整个数据库表或索引 文件由 P1 给出。

如果 P3==0,则要销毁的表位于主数据库文件中。如果 P3==1,则要销毁的表在辅助数据库文件中 用于存储使用 CREATE TEMPORARY TABLE 创建的表。

如果启用了 AUTOVACUUM,则可能是另一个根页面 可能会移动到新删除的根页面中,以便保留所有 数据库开头连续的根页。前者 移动的根页面的值 - 移动发生前的值 - 存储在寄存器 P2 中。如果不需要页面移动(因为 被删除的表已经是数据库中的最后一个表),然后是一个 零存储在寄存器 P2 中。如果禁用 AUTOVACUUM,则为零 存储在寄存器 P2 中。

如果存在任何活动读取器 VM,则此操作码会引发错误 它被调用。这样做是为了避免与以下因素相关的困难 在 AUTOVACUUM 中移动根页面时更新现有游标 数据库。即使数据库不是 AUTOVACUUM,也会引发此错误 db,以避免引入 autovacuum 之间的不兼容 和非自动真空模式。

另请参阅:清除

将寄存器 P1 中的值除以寄存器 P2 中的值 并将结果存储在寄存器 P3 (P3=P2/P1) 中。如果 寄存器 P1 为零,则结果为 NULL。如果任一输入是 NULL,则结果为 NULL。
滴索引 删除内部(内存中)数据结构,这些结构描述 数据库 P1 中名为 P4 的索引。这是在索引之后调用的 从磁盘中删除(使用 Destroy 操作码) 为了保持 架构与磁盘上的内容一致。
DropTable(滴表) 删除内部(内存中)数据结构,这些结构描述 数据库 P1 中名为 P4 的表。这是在表之后调用的 从磁盘中删除(使用 Destroy 操作码)以保持 的内部表示 架构与磁盘上的内容一致。
DropTrigger(滴触发器) 删除内部(内存中)数据结构,这些结构描述 数据库 P1 中名为 P4 的触发器。这是在触发器之后调用的 从磁盘中删除(使用 Destroy 操作码)以保持 的内部表示 架构与磁盘上的内容一致。
ElseEq(其他方程) 此操作码必须遵循 Lt 或 Gt 比较运算符。那里 可以是零个或多个操作码OP_ReleaseReg干预,但不能是其他操作码 允许在此指令和上一个 Lt 或 Gt 之间出现操作码。

如果对相同的两个操作数进行 Eq 比较的结果为 之前的 Lt 或 Gt 为真,然后跳转到 P2。如果 对前两个操作数进行方程比较的结果 本来是 false 或 NULL,然后失败。

End协程 寄存器 P1 中地址处的指令是 Yield跳转到该 Yield 的 P2 参数。 跳转后,寄存器 P1 变为未定义。

另请参阅:InitCoroutine

情 商 比较寄存器 P1 和 P3 中的值。如果 reg(P3)==reg(P1) 那么 跳转到地址 P2。

P5 的SQLITE_AFF_MASK部分必须是亲和力字符 - SQLITE_AFF_TEXT、SQLITE_AFF_INTEGER等。尝试 根据这种亲和力强制两个输入,然后 进行比较。如果SQLITE_AFF_MASK 0x00,则数字 使用亲和力。请注意,会存储关联转化 返回到输入寄存器 P1 和 P3。所以这个操作码会导致 对寄存器 P1 和 P3 的持续更改。

一旦发生任何转换,并且两个值都不是 NULL, 比较这些值。如果两个值都是 blob,则 memcmp() 为 用于确定比较结果。如果两个值 是文本,则在 P4 用于进行比较。如果未指定 P4,则 memcmp() 用于比较文本字符串。如果两个值都是 数字,则使用数字比较。如果两个值 属于不同的类型,则认为数字小于 字符串和字符串被视为小于 Blob。

如果在 P5 中设置了SQLITE_NULLEQ则比较结果始终是 true 或 false,并且从不为 NULL。如果两个操作数都为 NULL,则结果为 的比较是正确的。如果任一操作数为 NULL,则结果为 false。 如果两个操作数均为 NULL,则结果与以下结果相同 P5 省略了SQLITE_NULLEQ标志。

此操作码保存比较结果,以供新的跳转操作码使用。

到期 导致预编译语句过期。当对帐单过期时 使用 sqlite3_step() 执行,它将自动执行 重新准备自身(如果它最初是使用 sqlite3_prepare_v2()) 创建的) 否则它会因SQLITE_SCHEMA而失败。

如果 P1 为 0,则所有 SQL 语句都将过期。如果 P1 不为零, 则只有当前正在执行的语句过期。

如果 P2 为 0,则 SQL 语句将立即过期。如果 P2 为 1, 则允许正在运行的 SQL 语句继续运行直至完成。 当发生 CREATE INDEX 或类似的架构更改时,会发生 P2==1 情况 这可能有助于语句运行得更快,但不会影响 操作的正确性。

滤波器 计算 P4 寄存器中包含的密钥的哈希值 与r[P3]。检查是否在 由寄存器 P1 托管的绽放过滤器。如果它不存在,那么 也许跳到 P2。否则失败。

假阴性是无害的。跌倒总是安全的, 即使该值位于 Bloom 过滤器中。假阴性原因 要使用的 CPU 周期更多,但仍应产生正确的 答。但是,错误的答案很可能来自以下原因 误报 - 如果跳转在应该失败的时候进行。

过滤器添加 在以 r[P3] 开头的 P4 寄存器上计算哈希值,并 将该哈希值添加到 r[P1] 中包含的 Bloom 过滤器中。
完成寻求 如果游标 P1 之前是通过 DeferredSeek 移动的,请完成该操作 立即寻求操作,不再拖延。如果光标查找有 已经发生,此指令是无操作的。
FkCheck(英语:FkCheck 如果有任何未解决的问题,则因SQLITE_CONSTRAINT错误而停止 外键约束冲突。如果没有外键 约束冲突,这是无操作的。

当准备好的语句时,还会检查 FK 约束冲突 出口。此操作码用于在之前引发外键约束错误 返回结果,例如行更改计数或 RETURNING 子句。

Fk计数器 将“约束计数器”递增 P2(P2 可以是负数,也可以是正数)。 如果 P1 不为零,则数据库约束计数器递增 (延迟外键约束)。否则,如果 P1 为零,则 语句计数器递增(即时外键约束)。
FkIf零 此操作码测试外键约束计数器当前是否为零。 如果是这样,请跳转到指令 P2。否则,跌入下一个 指令。

如果 P1 不为零,则在数据库约束计数器 为零(计算延迟约束冲突的那个)。如果 P1 是 零,如果语句约束计数器为零,则进行跳转 (立即违反外键约束)。

发现 如果 P4==0,则寄存器 P3 保存由 MakeRecord 构造的 Blob。如果 P4>0 然后寄存器 P3 是形成解包的 P4 寄存器中的第一个 记录。

游标 P1 位于索引 b 树上。如果记录由 P3 和 P4 标识 是 P1 中任何条目的前缀,然后跳转到 P2 和 P1 左指向匹配的条目。

此操作使光标处于可以处于的状态 向前推进。下一条指令将起作用, 但不是上一个指令。

另请参阅:NotFoundNoConflictNotExists。寻求

功能 调用用户函数(P4 是指向 sqlite3_context 对象的指针 包含指向要运行的函数的指针),并采用参数 来自寄存器 P2 和继任者。参数数在 P4 指向的sqlite3_context对象。 函数的结果被存储 在寄存器 P3 中。寄存器 P3 不能是函数输入之一。

P1 是一个 32 位位掩码,指示每个参数是否对 函数在编译时被确定为常量。如果第一个 参数为常数,则设置 P1 的位 0。这用于确定 是否使用 sqlite3_set_auxdata() API 可以安全地保留到下一个 调用此操作码。

参见:AggStepAggFinalPureFunc

通用 电气 这就像 Lt 操作码一样工作,只是在以下情况下进行跳转 寄存器 P3 的内容大于或等于 寄存器 P1。有关其他信息,请参阅 Lt 操作码。
GetSubtype 从寄存器 P1 中提取子类型值并写入该子类型 进入寄存器 P2。如果 P1 没有子类型,则 P1 获得 NULL。
戈苏布 将当前地址写入寄存器 P1 然后跳转到地址 P2。
转到 无条件跳转到地址 P2。 执行的下一条指令将是 从开头的索引 P2 处的那个 该程序。

此操作码实际上并未使用 P1 参数。但是,它 有时设置为 1 而不是 0 作为命令行 shell 的提示 这个 Goto 是循环的底部,并且从 P2 向下的线 对于EXPLAIN输出,应缩进到当前行。

燃气轮机 这就像 Lt 操作码一样工作,只是在以下情况下进行跳转 寄存器 P3 的内容大于 寄存器 P1。有关其他信息,请参阅 Lt 操作码。
立即退出。所有打开的光标等都已关闭 自然而然。

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 之间的值(含 0 和 4),用于修改 P4 字符串。

0:(无变化) 1:NOT NULL 约束失败:P4 2:UNIQUE 约束失败:P4 3:CHECK约束失败:P4 4:外键约束失败:P4

如果 P5 不为零且 P4 为 NULL,则 “:” 之后的所有内容都是 省略。

在末尾插入了隐含的“Halt 0 0 0”指令 每个程序。因此,跳过程序的最后一条指令 与执行 Halt 相同。

HaltIfNull 检查寄存器 P3 中的值。如果为 NULL,则使用 参数 P1、P2 和 P4,就好像这是 Halt 指令一样。如果 寄存器 P3 中的值不为 NULL,则此例程为无操作。 P5 参数应为 1。
Idx删除 从寄存器 P2 表单开始的 P3 寄存器的内容 解压缩的索引键。此操作码从 由光标 P1 打开的索引。

如果 P5 不为零,则引发SQLITE_CORRUPT_INDEX错误 如果未找到匹配的索引条目。运行时会发生这种情况 UPDATE 或 DELETE 语句和要更新的索引条目 或未找到已删除。对于 IdxDelete 的某些用法(例如:EXCEPT 运算符),没有匹配并不重要 条目已找到。对于这些情况,P5 为零。另外,不要提高 如果处于writable_schema模式,则此(自我纠正和非严重)错误。

IdxGE系列 以 P3 开头的 P4 寄存器值形成一个解压缩索引 省略 PRIMARY KEY 的 key。此键值与索引进行比较 P1 当前指向,忽略 PRIMARY KEY 或 ROWID 字段在末尾。

如果 P1 索引条目大于或等于键值 然后跳转到 P2。否则,请跌至下一条指令。

IDXGT系列 以 P3 开头的 P4 寄存器值形成一个解压缩索引 省略 PRIMARY KEY 的 key。此键值与索引进行比较 P1 当前指向,忽略 PRIMARY KEY 或 ROWID 字段在末尾。

如果 P1 索引条目大于键值 然后跳转到 P2。否则,请跌至下一条指令。

Idx插入 寄存器 P2 保存使用 MakeRecord 指令创建的 SQL 索引键。此操作码写入该密钥 进入索引 P1。条目的数据为零。

如果 P4 不为零,则它是解压缩中的值数 reg(P2) 的键。在这种情况下,P3 是第一个寄存器的索引 对于解压缩的密钥。解压缩密钥的可用性有时可以 成为优化。

如果 P5 设置了 OPFLAG_APPEND 位,则这是对 b 树层的提示 此插入物很可能是附加物。

如果 P5 设置了 OPFLAG_NCHANGE 位,则更改计数器为 按此指令递增。如果OPFLAG_NCHANGE位清晰, 则更改计数器保持不变。

如果设置了 P5 的OPFLAG_USESEEKRESULT标志,则实现可能 通过避免在光标 P1 上进行不必要的搜索来加快运行速度。然而 只有在之前没有的情况下,才能设置OPFLAG_USESEEKRESULT标志 在光标上进行查找,或者如果最近的查找使用了等效键 到 P2。

此指令仅适用于索引。等效指令 对于表,则为 Insert

IdxLE系列 以 P3 开头的 P4 寄存器值形成一个解压缩索引 省略 PRIMARY KEY 或 ROWID 的键。此键值与 P1 当前指向的索引,忽略 PRIMARY KEY 或 P1 索引上的 ROWID。

如果 P1 索引条目小于或等于键值,则跳转 到 P2。否则,请跌至下一条指令。

IdxLT型 以 P3 开头的 P4 寄存器值形成一个解压缩索引 省略 PRIMARY KEY 或 ROWID 的键。此键值与 P1 当前指向的索引,忽略 PRIMARY KEY 或 P1 索引上的 ROWID。

如果 P1 索引条目小于键值,则跳转到 P2。 否则,请跌至下一条指令。

IdxRowid 将一个整数写入寄存器 P2,该整数是记录中的最后一个条目 由光标 P1 指向的索引键的末尾。这个整数应该是 此索引条目指向的表条目的 rowid。

另请参阅:RowidMakeRecord

如果 如果寄存器 P1 中的值为 true,则跳转到 P2。价值 如果它是数字和非零,则被视为 true。如果值 在 P1 为 NULL 时,当且仅当 P3 不为零时才进行跳转。
IfNoHope(伊夫诺霍普酒店) 寄存器 P3 是形成解压缩的 P4 寄存器中的第一个 记录。游标 P1 是一个索引 btree。P2 是跳转目的地。 换句话说,此操作码的操作数与 操作数添加到 NotFound 和 IdxGT。

此操作码只是一次优化尝试。如果此操作码始终 落空了,还是得到了正确答案,但还需要做额外的工作 执行。

游标 P1 的 seekHit 标志中的值 N 表示存在 一个键 P3:N,它将匹配索引中的某个记录。我们想知道 如果记录 P3:P4 有可能与 指数。如果不可能,我们可以跳过一些工作。所以如果 seekHit 小于 P4,尝试通过运行 NotFound 来确定是否匹配。

此操作码用于多列键的 IN 子句处理。 如果 IN 子句附加到键的元素,而不是 最左边的元素,如果最近的元素没有匹配项 寻找整个密钥,那么它可能是关键元素之一 左边是禁止比赛,因此“没有希望” 任何匹配项,无论检查了多少个 IN 子句元素。 在这种情况下,我们提前放弃了 IN 子句搜索,使用 操作码。操作码名称来自以下事实: 如果“没有希望”实现匹配,则进行跳跃。

参见:NotFoundSeekHit

如果不是 如果寄存器 P1 中的值为 False,则跳转到 P2。价值 如果数值为零,则视为 false。如果值 在 P1 为 NULL 时,当且仅当 P3 不为零时才进行跳转。
如果不开放 如果游标 P1 未打开,或者使用 NullRow 操作码将 P1 设置为 NULL 行,则跳转到指令 P2。否则,就失败了。
如果不是零 寄存器 P1 必须包含整数。如果寄存器 P1 的内容是 最初大于零,然后递减寄存器 P1 中的值。 如果它不为零(负或正),则也跳转到 P2。 如果寄存器 P1 最初为零,则保持其不变并失败。
IfNullRow 检查光标 P1 以查看它当前是否指向 NULL 行。 如果是,则将寄存器 P3 设置为 NULL 并立即跳转到 P2。 如果 P1 不在 NULL 行上,则不进行任何操作 变化。

如果 P1 不是打开的游标,则此操作码是无操作的。

IfPos(英语:IfPos) 寄存器 P1 必须包含整数。 如果寄存器 P1 的值为 1 或更大,则从 值并跳转到 P2。

如果寄存器 P1 的初始值小于 1,则 值保持不变,控制权传递到下一条指令。

如果变小 估计表 P1 中的行数。如果那样,请跳转到 P2 估计值小于大约 2**(0.1*P3)。
Incr真空 执行增量真空程序的单个步骤 P1 数据库。如果真空吸尘器已完成,请跳转到指令 第 2 页。否则,请跌至下一条指令。
初始化 程序包含此操作码的单个实例作为第一个实例 操作码。

如果(通过 sqlite3_trace()) 接口启用了跟踪,则 P4 中包含的 UTF-8 字符串在跟踪回调时发出。 或者,如果 P4 为空,则使用 sqlite3_sql() 返回的字符串。

如果 P2 不为零,请跳转到指令 P2。

递增 P1 的值,以便 Once 操作码将跳过 首次针对此运行对他们进行评估。

如果 P3 不为零,则它是要跳转到的地址,如果 SQLITE_CORRUPT 遇到错误。

初始化协程 设置寄存器 P1,使其屈服于协程 位于地址 P3。

如果 P2!=0,则协程实现紧随其后 此操作码。因此,跳过协程实现到 地址 P2.

另请参阅:EndCoroutine

插入 在游标 P1 的表中写入一个条目。一个新条目是 如果尚不存在,则创建或现有数据 条目被覆盖。数据是存储在寄存器中的值MEM_Blob 编号 P2。密钥存储在寄存器 P3 中。密钥必须 做一个MEM_Int。

如果设置了 P5 的OPFLAG_NCHANGE标志,则行更改计数为 递增(否则不增加)。如果设置了 P5 的OPFLAG_LASTROWID标志, 然后 rowid 被存储起来,以便后续返回 sqlite3_last_insert_rowid() 函数(否则未修改)。

如果设置了 P5 的OPFLAG_USESEEKRESULT标志,则实现可能 通过避免在光标 P1 上进行不必要的搜索来加快运行速度。然而 只有在之前没有的情况下,才能设置OPFLAG_USESEEKRESULT标志 在光标上进行查找,或者如果最近的查找使用了等于 P3 的键。

如果设置了 OPFLAG_ISUPDATE 标志,则此操作码是 UPDATE 操作。否则(如果标志是明确的),那么这个操作码 是 INSERT 操作的一部分。差异仅对以下重要 更新挂钩。

参数 P4 可能指向 Table 结构,也可能为 NULL。如果是 不是 NULL,则调用 update-hook (sqlite3.xUpdateCallback) 成功插入后。

(警告/待办事项:如果 P1 是伪游标,而 P2 是动态的 分配,则 P2 的所有权将转移到伪游标 寄存器 P2 变为短暂。如果光标已更改,则 然后,寄存器 P2 的值将发生变化。确保这不会 导致任何问题。

此指令仅适用于表。等效指令 索引为 IdxInsert

国际64 P4 是指向 64 位整数值的指针。 将该值写入寄存器 P2。
IntCopy的 将寄存器 P1 中保存的整数值传输到寄存器 P2 中。

这是 SCopy 的优化版本,仅适用于整数 值。

整数 32 位整数值 P1 写入寄存器 P2。
完整性Ck 对当前打开的数据库进行分析。存储位置 将 P1 注册为描述任何问题的错误消息文本。 如果未发现问题,则在寄存器 P1 中存储 NULL。

寄存器 P3 包含的误差比允许的最大错误数少 1。 最多会报告 reg(P3) 错误。 换言之,一旦 reg(P1) 错误出现,分析就会停止 明显。Reg(P1) 将更新为剩余的错误数。

数据库中所有表的根页码均为整数 存储在 P4_INTARRAY 参数中。

如果 P5 不为零,则对辅助数据库进行检查 文件,而不是主数据库文件。

此操作码用于实现integrity_check编译指示。

IsNull 如果寄存器 P1 中的值为 NULL,则跳转到 P2。
IsTrue(英语:IsT 此操作码实现 IS TRUE、IS FALSE、IS NOT TRUE 和 IS NOT FALSE 运算符。

将寄存器 P1 中的值解释为布尔值。存储它 寄存器 P2 中的布尔值(a 0 或 1)。或者,如果寄存器 P1 中的值为 NULL,则 P3 存储在寄存器 P2 中。如果 P4 反转答案 是 1。

逻辑总结如下:

  • 如果 P3==0 和 P4==0,则 r[P2] := r[P1] 为真
  • 如果 P3==1 和 P4==1,则 r[P2] := r[P1] 为 FALSE
  • 如果 P3==0 和 P4==1,则 r[P2] := r[P1] 不成立
  • 如果 P3==1 和 P4==0,则 r[P2] := r[P1] 不为 FALSE
IsType 如果 btree 中的列类型是指定的类型之一,则跳转到 P2 通过 P5 位掩码。

P1 通常是 btree 上的游标,其行解码缓存是 至少在P3列中有效。换句话说,应该有 列 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 值,则此操作码将认为 当数据类型应为 NULL 时,数据类型为 REAL。当 P1<0 和值 已经存储在寄存器 P3 中,那么这个操作码可以可靠地存储 区分 NULL 和 REAL。只有当 P1>=0 时才会出现问题。

跳转到地址 P2 当且仅当 由 P1 和 P3 确定的值对应于 P5 位掩码。

日记模式 将数据库 P1 的日志模式更改为 P3。P3 必须是 PAGER_JOURNALMODE_XXX值。如果在各种回滚之间切换 模式(删除、截断、保留、关闭和内存),这是一个简单的 操作。不需要 IO。

如果切换到 WAL 模式或退出 WAL 模式,则过程会更加复杂。

写一个包含最终日志模式的字符串来注册 P2。

跳转到地址 P1、P2 或 P3 处的指令,具体取决于 在最近的比较指令中,P1 向量小于 分别等于或大于 P2 向量。

此操作码必须紧跟在比较操作码之后。

最后 下次使用 P1 的 Rowid 或 Column 或 Prev 指令 将引用数据库表或索引中的最后一个条目。 如果表或索引为空且 P2>0,则立即跳转到 P2。 如果 P2 为 0 或表或索引不为空,则失败 到以下说明。

此操作码使光标配置为以相反的顺序移动, 从结束到开始。换句话说,光标是 配置为使用“上一个”,而不是“下一个”

这就像 Lt 操作码一样工作,只是在以下情况下进行跳转 寄存器 P3 的内容小于或等于 寄存器 P1。有关其他信息,请参阅 Lt 操作码。
负载分析 读取数据库 P1 的sqlite_stat1表并加载内容 将该表添加到内部索引哈希表中。这将导致 准备所有后续查询时要使用的分析。
中尉 比较寄存器 P1 和 P3 中的值。如果 reg(P3)<reg(P1) 那么 跳转到地址 P2。

如果设置了 P5 的SQLITE_JUMPIFNULL位,并且 reg(P1) 或 reg(P3) 为 NULL,则进行跳转。如果SQLITE_JUMPIFNULL bit 是明确的,如果任一操作数为 NULL,则失败。

P5 的SQLITE_AFF_MASK部分必须是亲和力字符 - SQLITE_AFF_TEXT、SQLITE_AFF_INTEGER等。尝试 根据这种亲和力强制两个输入,然后 进行比较。如果SQLITE_AFF_MASK 0x00,则数字 使用亲和力。请注意,会存储关联转化 返回到输入寄存器 P1 和 P3。所以这个操作码会导致 对寄存器 P1 和 P3 的持续更改。

一旦发生任何转换,并且两个值都不是 NULL, 比较这些值。如果两个值都是 blob,则 memcmp() 为 用于确定比较结果。如果两个值 是文本,则在 P4 用于进行比较。如果未指定 P4,则 memcmp() 用于比较文本字符串。如果两个值都是 数字,则使用数字比较。如果两个值 属于不同的类型,则认为数字小于 字符串和字符串被视为小于 Blob。

此操作码保存比较结果,以供新的跳转操作码使用。

制作记录 将以 P1 开头的 P2 寄存器转换为记录格式,用作数据库表中的数据记录或密钥 在索引中。操作码可以稍后对记录进行解码。

P4 可以是长度为 P2 字符的字符串。的第 N 个字符 string 指示应用于第 N 个的列关联 索引键的字段。

从角色到亲和力的映射由SQLITE_AFF_给出 sqliteInt.h 中定义的宏。

如果 P4 为 NULL,则所有索引字段都具有相关性 BLOB。

P5 的含义取决于 SQLITE_ENABLE_NULL_TRIM compile-time 选项已启用:

* 如果启用了 SQLITE_ENABLE_NULL_TRIM,则 P5 是索引 最右边的表,可以进行空修剪。

* 如果省略SQLITE_ENABLE_NULL_TRIM,则 P5 的值为 OPFLAG_NOCHNG_MAGIC 如果允许 MakeRecord 操作码 接受 serial_type 10 的无更改记录。此值为 仅在 assert() 中使用,不会影响最终结果。

MaxPgcnt 尝试将数据库 P1 的最大页数设置为 P3 中的值。 不要让最大页数低于当前页数,并且 如果 P3==0,则不要更改最大页数值。

在寄存器 P2 中存储更改后的最大页数。

内存最大 P1 是此 VM 根帧中的寄存器(根帧是 如果正在执行此指令,则与当前帧不同 在子程序中)。将寄存器 P1 的值设置为最大值 其当前值和寄存器 P2 中的值。

如果存储单元最初不是,则此指令将引发错误 整数。

移动 移动寄存器 P1 中的 P3 值。P1+P3-1 进入 寄存器 P2..P2+P3-1。寄存器 P1..P1+P3-1 是 左持有 NULL。这是寄存器范围的错误 第 1 页..P1+P3-1 和 P2..P2+P3-1 重叠。这是一个错误 使 P3 小于 1。
将寄存器 P1 中的值乘以寄存器 P2 中的值 并将结果存储在寄存器 P3 中。 如果任一输入为 NULL,则结果为 NULL。
MustBeInt 强制寄存器 P1 中的值为整数。如果值 在 P1 中不是整数,不能转换为整数 没有数据丢失,然后立即跳转到 P2,或者如果 P2==0 引发SQLITE_MISMATCH例外。
这就像 Eq 操作码一样工作,只是在以下情况下进行跳转 寄存器 P1 和 P3 中的操作数不相等。请参阅方程操作码 其他信息。
新罗维德 获取用作表键的新整数记录编号(也称为“rowid”)。 记录编号以前未用作数据库中的键 光标 P1 指向的表。写入新的记录编号 写入寄存器 P2。

如果 P3>0,则 P3 是此 VDBE 根帧中的寄存器,该寄存器持有 以前生成的最大记录数。没有新的记录数字 允许小于此值。当此值达到最大值时, 生成SQLITE_FULL错误。P3 寄存器更新为” 生成的记录编号。此 P3 机制用于帮助实现 AUTOINCREMENT 功能。

下一个 前进光标 P1,使其指向其 表或索引。如果没有更多的键/值对,则失败 到以下说明。但是,如果光标前进成功, 立即跳转到 P2。

Next 操作码仅在用于定位光标的 SeekGT、SeekGE 或 Rewind 操作码之后有效。不允许下一个 以关注 SeekLT、SeekLE 或 Last

P1 游标必须用于实际表,而不是伪表。P1 必须具有 在此操作码之前打开,否则程序将出现段错误。

P3 值是对 btree 实现的提示。如果 P3==1,则 表示 P1 是一个 SQL 索引,并且该指令可能是 如果该索引是唯一的,则省略。P3 通常为 0。P3 是 始终为 0 或 1。

如果 P5 为正数并且进行了跳转,则事件计数器 预制语句中的数字 P5-1 递增。

Смотритетакже

无冲突 如果 P4==0,则寄存器 P3 保存由 MakeRecord 构造的 Blob。如果 P4>0 然后寄存器 P3 是形成解包的 P4 寄存器中的第一个 记录。

游标 P1 位于索引 b 树上。如果记录由 P3 和 P4 标识 包含任何 NULL 值,请立即跳转到 P2。如果所有条款的 record 不是 NULL,然后进行检查以确定 P1 索引 btree 具有匹配的键前缀。如果没有匹配项,请跳转 立即到 P2。如果有匹配项,则失败并离开 P1 光标指向匹配行。

此操作码类似于 NotFound,但 如果搜索键输入的任何部分为 NULL,则始终采用 branch。

此操作使光标处于无法状态的状态 向任一方向前进。换句话说,在此操作之后,Next 和 Prev 操作码不起作用。

另请参阅:NotFoundFoundNotExists

努普 什么都不做。此指令通常用作跳转 目的地。
将寄存器 P1 中的值解释为布尔值。存储 寄存器 P2 中的布尔补码。如果寄存器 P1 中的值为 NULL,则 NULL 存储在 P2 中。
不存在 P1 是在 SQL 表 btree 上打开的游标的索引(整数 键)。P3 是一个整数 rowid。如果 P1 不包含 rowid P3 然后立即跳到 P2。或者,如果 P2 为 0,则提高 SQLITE_CORRUPT错误。如果 P1 确实包含 rowid 为 P3 的记录,则 将光标指向该记录并下降到下一个记录 指令。

SeekRowid 操作码执行相同的操作,但也允许 P3 寄存器包含一个非整数值,在这种情况下,跳转为 总是采取。此操作码要求 P3 始终包含整数。

NotFound 操作码对索引 btree 执行相同的操作 (使用任意多值键)。

此操作码使光标处于无法前进的状态 在任一方向上。换言之,Next 和 Prev 操作码将 不遵循此操作码。

另请参阅:FoundNotFoundNoConflictSeekRowid

未找到 如果 P4==0,则寄存器 P3 保存由 MakeRecord 构造的 Blob。如果 P4>0 然后寄存器 P3 是形成解包的 P4 寄存器中的第一个 记录。

游标 P1 位于索引 b 树上。如果记录由 P3 和 P4 标识 不是 P1 中任何条目的前缀,则跳转到 P2。如果 P1 包含前缀与 P3/P4 记录匹配的条目,然后控制 落入下一条指令,P1 左指向 匹配条目。

此操作使光标处于无法状态的状态 向任一方向前进。换句话说,在此操作之后,Next 和 Prev 操作码不起作用。

另请参阅:FoundNotExistsNoConflictIfNoHope

不为空 如果寄存器 P1 中的值不为 NULL,则跳转到 P2。
将 NULL 写入寄存器 P2。如果 P3 大于 P2,则同时写入 NULL 进入寄存器 P3 以及 P2 和 P3 之间的每个寄存器。如果 P3 小于 P2(通常 P3 为零),则只有寄存器 P2 为 设置为 NULL。

如果 P1 值不为零,则还要设置 MEM_Cleared 标志,以便 即使 Ne 或 Eq 上设置了 SQLITE_NULLEQ,NULL 值也不会相等。

NullRow 将光标 P1 移动到 null 行。任何操作 当光标位于 null 行上时发生的事件将始终发生 写入 NULL。

如果光标 P1 之前未打开,请立即将其打开到一个特殊的 伪游标,始终为每列返回 NULL。

抵消 在寄存器 r[P3] 中存储字节偏移量到数据库文件中,即 光标 P1 当前所在的记录的有效负载的开始 指点。

P2 是 sqlite_offset() 函数参数的列号。 此操作码本身不使用 P2,但 P2 值由 代码生成器。此操作码的 P1、P2 和 P3 操作数是 与相同。

仅当 SQLite 使用 -DSQLITE_ENABLE_OFFSET_SQL_FUNC选项。

OffsetLimit 此操作码执行与以下操作码关联的常用计算 LIMIT 和 OFFSET 处理。r[P1] 保存极限计数器。r[P3] 握住偏移计数器。操作码计算组合值 的 LIMIT 和 OFFSET 并将该值存储在 r[P2] 中。r[P2] 计算的值是需要 访问以完成查询。

如果 r[P3] 为零或负数,则表示没有 OFFSET r[P2] 设置为 LIMIT 的值 r[P1]。

如果 r[P1] 为零或负数,则表示没有 LIMIT r[P2] 设置为 -1。

否则,r[P2] 设置为 r[P1] 和 r[P3] 的总和。

一次 第一次出现此操作码时,请跌至下一条指令 每次调用字节码程序时都会遇到。跳转到 P2 在同一调用期间的第二次和所有后续遭遇中。

顶级程序通过比较 P1 来确定首次调用 操作数对开头 Init 操作码上的 P1 操作数 的程序。如果 P1 值不同,则失败并制作 此操作码的 P1 等于 Init 的 P1。如果 P1 值为 同样,然后跳跃。

对于子程序,VdbeFrame 中有一个位掩码,用于确定 是否应该跳楼。位掩码是必需的 因为自我更改代码技巧不适用于递归 触发器。

OpenAutoindex 此操作码的工作方式与 OpenEphemeral 相同。它有一个 不同的名称来区分其用途。使用 通过此操作码将用于自动创建的瞬态 联接中的索引。
OpenDup的 打开指向同一临时表的新游标 P1 光标 P2。P2 光标必须由先前的 OpenEphemeral 操作码打开。只能复制临时游标。

重复的临时游标用于实例化视图的自联接。

OpenEphemeral 打开一个新游标 P1 到一个瞬态表。 光标始终以读/写方式打开,即使 主数据库是只读的。转瞬即逝 当光标关闭时,表将自动删除。

如果游标 P1 已在临时表上打开,则表 被清除(所有内容都被删除)。

P2 是临时表中的列数。 如果 P4==0,则光标指向 BTree 表和 BTree 索引 如果 P4 不为 0。如果 P4 不为 NULL,则指向 KeyInfo 结构 它定义了索引中键的格式。

P5 参数可以是定义的 BTREE_* 标志的掩码 在 btree.h 中。这些标志控制着 btree 中。BTREE_OMIT_JOURNAL 和 BTREE_SINGLE 标志是 自动添加。

如果 P3 为正,则 reg[P3] 稍作修改,使其 可用作插入的零长度数据。这是一个优化 这避免了额外的 Blob 操作码来初始化该寄存器。

OpenPseudo的 打开一个新游标,该游标指向包含单个 数据行。那一行的内容就是内存的内容 寄存器 P2。换言之,游标 P1 成为 寄存器 P2 中包含的MEM_Blob内容。

由此操作码创建的伪表用于保存单个 分拣器的行输出,以便将行分解为 使用操作码的单个列。操作码 是唯一适用于伪表的游标操作码。

P3 是记录中将由 伪表。

开放读取 打开其根页为 数据库文件中的 P2。数据库文件由 P3 确定。 P3==0 表示主数据库,P3==1 表示用于 临时表,而P3>1表示使用相应的附件 数据库。为新游标指定标识符 P1。The P1 值不必是连续的,但所有 P1 值都应该是小整数。 P1 为负数是错误的。

允许的 P5 位:

  • 0x02 OPFLAG_SEEKEQ:此光标仅用于 相等查找(作为 SeekLE/IdxLT 的一对操作码 SeekGE/IdxGT 实现)

P4 值可以是整数 (P4_INT32) 或指向 KeyInfo 结构 (P4_KEYINFO)。如果它是指向 KeyInfo 的指针 对象,则打开的表必须是索引 B 树,其中 KeyInfo 对象定义内容和整理 该索引 b 树的序列。否则,如果 P4 是整数 值,则打开的表必须是具有 列数不小于 P4 的值。

参见:OpenWriteReopenIdx

OpenWrite的 在根目录或索引上打开名为 P1 的读/写游标 page 为 P2(或者其根页保存在寄存器 P2 中,如果 OPFLAG_P2ISREG位设置在 P5 中 - 见下文)。

P4 值可以是整数 (P4_INT32) 或指向 KeyInfo 结构 (P4_KEYINFO)。如果它是指向 KeyInfo 的指针 对象,则打开的表必须是索引 B 树,其中 KeyInfo 对象定义内容和整理 该索引 b 树的序列。否则,如果 P4 是整数 值,则打开的表必须是具有 列数不小于 P4 的值。

允许的 P5 位:

  • 0x02 OPFLAG_SEEKEQ:此光标仅用于 相等查找(作为 SeekLE/IdxLT 的一对操作码 SeekGE/IdxGT 实现)
  • 0x08 OPFLAG_FORDELETE:此光标仅用于查找 ,然后删除索引 btree 中的条目。这是一个 向存储引擎提示允许存储引擎执行以下操作 忽视。官方 SQLite b*tree 存储未使用提示 引擎,但由 COMDB2 使用。
  • 0x10 OPFLAG_P2ISREG:使用寄存器 P2 的内容 作为根页面,而不是 P2 本身的值。

此指令的工作方式与 OpenRead 类似,只是它打开了光标 在读/写模式下。

参见:OpenReadReopenIdx

取寄存器 P1 和 P2 中值的逻辑 OR,然后 将答案存储在寄存器 P3 中。

如果 P1 或 P2 为非零 (true),则结果为 1 (true) 即使另一个输入为 NULL。一个 NULL 和 false 或两个 NULL 给出 NULL 输出。

页数 将数据库 P1 中的当前页数写入存储单元 P2。
参数 此操作码仅存在于通过程序指令调用的子程序中。复制当前存储在内存中的值 调用(父)帧的单元格到当前帧中的单元格 P2 地址空间。触发程序使用它来访问新的。 和 old.* 值。

父框架中单元格的地址是通过添加 P1 参数的值到 P1 参数的值到 调用程序说明。

ParseSchema 解析架构 读取并解析数据库 P1 的架构表中的所有条目 与 WHERE 子句 P4 匹配。如果 P4 是 NULL 指针,则 将重新分析 P1 的整个架构。

此操作码调用解析器以创建新的虚拟机, 然后运行新的虚拟机。因此,它是一个可重入的操作码。

排列 在下一个中设置 Compare 运算符使用的排列 指令。排列存储在 P4 操作数中。

排列仅对下一个操作码有效,该操作码必须是 在 P5 中设置了 OPFLAG_PERMUTE 位的比较

P4 整数数组中的第一个整数是数组的长度 并且不会成为排列的一部分。

昨日 备份游标 P1,使其指向其 表或索引。如果没有以前的键/值对,则失败 到以下说明。但是,如果游标备份成功, 立即跳转到 P2。

上一个操作码仅在用于定位光标的 SeekLT、SeekLE 或 Last 操作码之后有效。上一页是不允许的 关注 SeekGT、SeekGE 或 Rewind

P1 游标必须用于实际表,而不是伪表。如果 P1 是 未打开,则行为未定义。

P3 值是对 btree 实现的提示。如果 P3==1,则 表示 P1 是一个 SQL 索引,并且该指令可能是 如果该索引是唯一的,则省略。P3 通常为 0。P3 是 始终为 0 或 1。

如果 P5 为正数并且进行了跳转,则事件计数器 预制语句中的数字 P5-1 递增。

程序 执行作为 P4(类型 P4_SUBPROGRAM)传递的触发器程序。

P1 包含包含第一个存储器的存储单元的地址 用作子程序参数的值数组中的单元格。小二 包含子程序抛出 IGNORE 时要跳转到的地址 使用 RAISE() 函数的异常。寄存器 P3 包含地址 此(父)VM 中用于分配 子 VDBE 在运行时所需的内存。

P4 是指向包含触发器程序的 VM 的指针。

如果 P5 不为零,则启用递归程序调用。

PureFunc 调用用户函数(P4 是指向 sqlite3_context 对象的指针 包含指向要运行的函数的指针),并采用参数 来自寄存器 P2 和继任者。参数数在 P4 指向的sqlite3_context对象。 函数的结果被存储 在寄存器 P3 中。寄存器 P3 不能是函数输入之一。

P1 是一个 32 位位掩码,指示每个参数是否对 函数在编译时被确定为常量。如果第一个 参数为常数,则设置 P1 的位 0。这用于确定 是否使用 sqlite3_set_auxdata() API 可以安全地保留到下一个 调用此操作码。

此操作码的工作方式与 Function 完全相同。唯一的区别在于 它的名字。此操作码用于函数必须位于的地方 纯粹是非确定性的。一些内置的日期/时间函数可以是 要么是确定性的,要么是非确定性的,这取决于他们的论点。 当这些函数以非确定性方式使用时,它们将检查 查看是否使用 PureFunc 而不是 Function 调用它们,以及 如果是,他们会抛出错误。

另请参阅:AggStepAggFinal函数

读取Cookie 从数据库 P1 中读取 cookie 编号 P3 并将其写入寄存器 P2。 P3==1 是架构版本。P3==2 是数据库格式。 P3==3 是建议的寻呼机缓存大小,依此类推。P1==0 是 主数据库文件,P1==1 是用于存储的数据库文件 临时表。

数据库上必须有读锁(事务 必须启动或必须有一个打开的光标)之前 执行此指令。

真正 P4 是指向 64 位浮点值的指针。 将该值写入寄存器 P2。
真实亲和力 如果寄存器 P1 包含整数,请将其转换为实数。

从以下列中提取信息时,使用此操作码 具有真正的亲和力。此类列值仍可存储为 整数,以提高空间效率,但在提取后我们需要它们 只有真正的价值。

发布注册 从服务中释放寄存器。中的任何内容 此操作码完成后,寄存器不可靠。

释放的寄存器将是从 P1 开始的 P2 寄存器, 除非设置了 P3 的位 ii,否则不要释放寄存器 P1+ii。 换句话说,P3 是要保留的寄存器掩码。

释放寄存器会清除 Mem.pScopyFrom 指针。这意味着 如果已发布寄存器的内容是使用 SCopy 设置的, 对 SCopy 的源寄存器值的更改将不再 在 sqlite3VdbeMemAboutToChange() 中生成断言错误。

如果设置了 P5,则所有释放的寄存器都设置了其类型 MEM_Undefined以便任何后续尝试读取释放 寄存器(在重新初始化之前)将生成断言错误。

每次调用此操作码时都应设置 P5。 但是,代码生成器中的某些地方会释放寄存器 在使用之前,在(有效)假设寄存器 在使用之前不会出于其他目的重新分配,并且 因此可以安全释放。

此操作码仅在测试和调试版本中可用。是的 未为发布版本生成。此操作码的目的是帮助 验证生成的字节码。此操作码实际上没有贡献 计算答案。

剩余 计算整数寄存器 P2 除以 注册 P1 并将结果存储在寄存器 P3 中。 如果寄存器 P1 中的值为零,则结果为 NULL。 如果任一操作数为 NULL,则结果为 NULL。
重新打开Idx ReopenIdx 操作码的工作方式与 OpenRead 类似,只是它首先 检查 P1 上的光标是否已在同一 b-tree,如果是,则此操作码变为无操作。换言之, 如果光标已打开,请不要重新打开它。

ReopenIdx 操作码只能与 P5==0 或 P5== 一起使用OPFLAG_SEEKEQ P4 是一个P4_KEYINFO对象。此外,P3 值必须 与同一游标的所有其他 ReopenIdx 或 OpenRead 相同 数。

允许的 P5 位:

  • 0x02 OPFLAG_SEEKEQ:此光标仅用于 相等查找(作为 SeekLE/IdxLT 的一对操作码 SeekGE/IdxGT 实现)

另请参阅:OpenReadOpenWrite

重置计数 更改计数器的值将复制到数据库句柄 更改计数器(由后续调用 sqlite3_changes() 返回)。 然后,VM 内部更改计数器重置为 0。 这由触发程序使用。
重置排序器 从临时表或排序器中删除所有内容 在光标 P1 上打开。

此操作码仅适用于用于排序和 使用 OpenEphemeral 或 SorterOpen 打开。

结果行 寄存器 P1 到 P1+P2-1 包含一行 结果。此操作码导致 sqlite3_step() 调用终止 使用SQLITE_ROW返回代码,它设置了sqlite3_stmt 结构以提供对 r(P1) 的访问。r(P1+P2-1) 值为 结果行。
返回 跳转到寄存器 P1 中存储的地址。如果 P1 是退货地址 register,然后完成从子例程返回。

如果 P3 为 1,则仅当寄存器 P1 包含整数时才会进行跳转 值,否则执行将落入下一个操作码,并且 Return 将变为无操作。如果 P3 为 0,则寄存器 P1 必须持有 整数,否则会引发 assert()。当 P3 设置为 1 时 此操作码与 BeginSubrtn 结合使用,并设置为 0 否则。

寄存器 P1 中的值不受此操作码的影响。

字节码引擎不使用 P2。但是,如果 P2 为阳性 并且也小于当前地址,然后输出“EXPLAIN” CLI 中的格式化程序将向上缩进 P2 操作码中的所有操作码 不包括当前的申报表。P2 应为第一个操作码 在返回此操作码的子例程中。因此,P2 value 是字节码缩进提示。请参阅 tag-20220407a wherecode.c 和 shell.c。

重绕 下次使用 Rowid 或 Column 或 P1 的 Next 指令 将引用数据库表或索引中的第一个条目。 如果表或索引为空,请立即跳转到 P2。 如果表或索引不为空,则跌至以下内容 指令。

如果 P2 为零,则断言 P1 表从不为零 空的,因此永远不会进行跳跃。

此操作码将光标配置为向前移动, 从头到尾。换句话说,光标是 配置为使用“下一步”,而不是“上一页”。

RowCell(行单元格) P1 和 P2 都是打开的光标。两者都必须在同一类型上打开 of table - intkey 或 index。此操作码用作复制的一部分 从 P2 到 P1 的当前行。如果光标在 intkey 上打开 表中,寄存器 P3 包含要与新记录一起使用的 rowid 第 1 页。如果在索引表上打开它们,则不使用 P3。

此操作码后跟 Insert 或 InsertIdx 操作码 设置OPFLAG_PREFORMAT标志以完成插入操作。

行数据 将 当前指向的光标 P1。 没有对数据的解释。 它只是完全按照 P2 寄存器复制到 P2 寄存器上 它可以在数据库文件中找到。

如果游标 P1 是索引,则内容是行的键。 如果游标 P2 是表,则提取的内容就是数据。

如果 P1 光标必须指向有效行(而不是 NULL 行) 一个真实的表,而不是一个伪表。

如果 P3!=0,则允许此操作码生成临时指针 进入数据库页面。这意味着输出的内容 一旦光标移动,寄存器将失效 - 包括 由“保存”当前光标的其他光标引起的移动 position,以便它们可以写入同一表。如果 P3==0 然后将数据的副本制作到内存中。P3!=0 更快,但 P3==0 更安全。

如果 P3!=0,则 P2 寄存器的内容不适合使用 在OP_Result中,任何OP_Result都会使 P2 寄存器内容失效。 P2 寄存器内容因 Function 或 通过使用指向同一表的另一个光标。

罗维德 在寄存器 P2 中存储一个整数,该整数是表条目的键 P1 当前指向。

P1 可以是普通表,也可以是虚拟表。曾经有 是用于虚拟表的单独OP_VRowid操作码,但是这 一个操作码现在适用于两种表类型。

RowSet添加 将寄存器 P2 保存的整数值插入到 RowSet 对象中 保存在寄存器 P1 中。

如果 P2 不是整数,则断言失败。

RowSetRead 从 P1 中的 RowSet 对象中提取最小值 并将该值放入寄存器 P3 中。 或者,如果 RowSet 对象 P1 最初为空,则保留 P3 保持不变,然后跳转到指令 P2。
RowSet测试 假定寄存器 P3 保存 64 位整数值。如果寄存器 P1 包含一个 RowSet 对象,而该 RowSet 对象包含 P3 中保存的值,跳转到寄存器 P2。否则,请插入 P3 中的整数进入 RowSet 并继续到 下一个操作码。

RowSet 对象针对整数集的情况进行了优化 以不同的阶段插入,每组不包含重复项。 每个集合都由唯一的 P4 值标识。第一组 必须有 P4==0,最终集合必须有 P4==-1,对于所有其他集合 必须有 P4>0。

这允许优化:(a) 当 P4==0 时,无需测试 P3 的 RowSet 对象,因为它保证不包含它, (b) 当 P4==-1 时,无需插入该值,因为它将 从不测试,并且 (c) 当属于集合 X 的值 插入后,无需搜索即可查看是否相同的值 以前作为集合 X 的一部分插入(仅当它以前是 作为其他集合的一部分插入)。

保存点 打开、释放或回滚由参数 P4 命名的保存点,具体取决于 在 P1 的值上。要打开新的保存点,请设置 P1==0 (SAVEPOINT_BEGIN)。 释放(提交)现有保存点集 P1==1 (SAVEPOINT_RELEASE)。 要回滚现有保存点,请设置 P1==2 (SAVEPOINT_ROLLBACK)。
SCopy(斯科比酒店) 将寄存器 P1 的浅拷贝复制到寄存器 P2 中。

此指令创建该值的浅拷贝。如果值 是字符串或 blob,则副本只是指向 原件,因此,如果原件发生变化,副本也会发生变化。 更糟糕的是,如果原件被取消分配,副本将失效。 因此,程序必须保证原始内容不会更改 在副本的生命周期内。使用“复制”完成 复制。

寻求结束 将光标 P1 放在 btree 的末尾,以便 将新条目追加到 btree 上。

假设光标仅用于追加,因此 如果光标有效,则光标必须已经指向 在 btree 的末尾,因此不会对 光标。

SeekGE公司 如果游标 P1 引用 SQL 表(使用整数键的 B 树), 使用寄存器 P3 中的值作为密钥。如果游标 P1 引用 到 SQL 索引,则 P3 是 P4 寄存器数组中的第一个 用作解压缩的索引键。

重新定位光标 P1,使其指向 大于或等于键值。如果没有记录 大于或等于键且 P2 不为零,则跳转到 P2。

如果光标 P1 是使用 OPFLAG_SEEKEQ 标志打开的,那么这个 操作码将落在与密钥完全匹配的记录上,或者 否则将导致跳转到 P2。当光标OPFLAG_SEEKEQ时, 此操作码后跟具有相同参数的 IdxLE 操作码。 如果此操作码成功,则将跳过 IdxGT 操作码,但 IdxGT 操作码将用于后续循环迭代。这 OPFLAG_SEEKEQ flags 是对 btree 层的提示,表明这 是一种平等搜索。

此操作码将光标配置为向前移动, 从头到尾。换句话说,光标是 配置为使用“下一步”,而不是“上一页”。

另请参阅:FoundNotFound、SeekLt、SeekGt、SeekLe

SeekGT系列 如果游标 P1 引用 SQL 表(使用整数键的 B 树), 使用寄存器 P3 中的值作为密钥。如果游标 P1 引用 到 SQL 索引,则 P3 是 P4 寄存器数组中的第一个 用作解压缩的索引键。

重新定位光标 P1,使其指向 大于键值。如果没有大于 键和 P2 不为零,然后跳转到 P2。

此操作码将光标配置为向前移动, 从头到尾。换句话说,光标是 配置为使用“下一步”,而不是“上一页”。

另请参阅:FoundNotFound、SeekLt、SeekGe、SeekLe

SeekHit的 如有必要,增加或减少游标 P1 的 seekHit 值, 使其不小于 P2 且不大于 P3。

seekHit 整数表示索引中项的最大值,其 已知至少有一场比赛。如果 seekHit 值较小 比索引查找中的相等项总数,则 IfNoHope 操作码可能会运行以查看是否可以放弃 IN 循环 尽早,从而节省工作。这是 IN-early-out 优化的一部分。

P1 必须是有效的 b 树游标。

SeekLE的 如果游标 P1 引用 SQL 表(使用整数键的 B 树), 使用寄存器 P3 中的值作为密钥。如果游标 P1 引用 到 SQL 索引,则 P3 是 P4 寄存器数组中的第一个 用作解压缩的索引键。

重新定位光标 P1,使其指向 小于或等于键值。如果没有记录 小于或等于密钥且 P2 不为零,则跳转到 P2。

此操作码使光标配置为以相反的顺序移动, 从结束到开始。换句话说,光标是 配置为使用“上一个”,而不是“下一个”

如果光标 P1 是使用 OPFLAG_SEEKEQ 标志打开的,那么这个 操作码将落在与密钥完全匹配的记录上,或者 否则将导致跳转到 P2。当光标OPFLAG_SEEKEQ时, 此操作码后跟具有相同参数的 IdxLE 操作码。 如果此操作码成功,将跳过 IdxGE 操作码,但 IdxGE 操作码将用于后续循环迭代。这 OPFLAG_SEEKEQ flags 是对 btree 层的提示,表明这 是一种平等搜索。

另请参阅:FoundNotFound、SeekGt、SeekGe、SeekLt

寻求LT 如果游标 P1 引用 SQL 表(使用整数键的 B 树), 使用寄存器 P3 中的值作为密钥。如果游标 P1 引用 到 SQL 索引,则 P3 是 P4 寄存器数组中的第一个 用作解压缩的索引键。

重新定位光标 P1,使其指向 小于键值。如果没有小于 键和 P2 不为零,然后跳转到 P2。

此操作码使光标配置为以相反的顺序移动, 从结束到开始。换句话说,光标是 配置为使用“上一个”,而不是“下一个”

另请参阅:FoundNotFound、SeekGt、SeekGe、SeekLe

SeekRowid P1 是在 SQL 表 btree 上打开的游标的索引(整数 键)。如果寄存器 P3 不包含整数或 P1 不包含整数 包含具有 rowid P3 的记录,然后立即跳转到 P2。 或者,如果 P2 为 0,则引发SQLITE_CORRUPT错误。如果 P1 包含 然后带有 rowid P3 的记录 将光标指向该记录并下降到下一个记录 指令。

NotExists 操作码执行相同的操作,但使用 NotExists 时,必须保证 P3 寄存器包含整数值。有了这个 操作码,寄存器 P3 可能不包含整数。

NotFound 操作码对索引 btree 执行相同的操作 (使用任意多值键)。

此操作码使光标处于无法前进的状态 在任一方向上。换言之,Next 和 Prev 操作码将 不遵循此操作码。

另请参阅:FoundNotFoundNoConflictSeekRowid

SeekScan 扫描 此操作码是 SeekGE 的前缀操作码。换句话说,这个 操作码必须紧跟 SeekGE。此约束是 由 assert() 语句检查。

此操作码使用后续 SeekGE 的 P1 到 P4 操作数。在下面的文本中,后续 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 行“目标”。

如果 SeekGE.P1 光标当前未指向有效行, 那么这个操作码是无操作的,控制会传递到 SeekGE 中。

如果 SeekGE.P1 光标指向有效行,然后指向该行 可能是目标行,也可能靠近并略高于 目标行,或者它可能位于目标行之后。如果光标是 当前在目标行之前,则此操作码尝试定位 通过调用 sqlite3BtreeStep() 在目标行上或之后的光标 在光标上 1 和 This.P1 之间。

This.P5 参数是一个标志,指示在 光标最终指向超过目标的有效行 排。如果 This.P5 为 false (0),则跳转到 SeekGE。第 2 页。如果 This.P5 为真(非零),则跳转到 This.P2。The P5==0 当对 IN 约束。跳转到 SeekGE。P2 结束循环。P5!=0 案例 当 IN 的右侧存在不等式约束时发生 算子。在这种情况下,This.P2 将直接指向 或 在 IdxGT 或 IdxGE 操作码之前设置代码,以检查 循环终止。

此操作码的可能结果:

  1. 如果光标最初未指向任何有效行,则 落入后续的 SeekGE 操作码。

  2. 如果光标向左指向目标前面的行 行,即使在对 This.P1 进行多达 sqlite3BtreeNext(),然后也落入 SeekGE。

  3. 如果光标左指向目标行,则因为它 位于目标行的开头,或者因为一个或多个 sqlite3BtreeNext() 调用将光标移动到目标行, 然后跳转到 This.P2..,

  4. 如果光标在目标行之前开始,并且调用 到 sqlite3BtreeNext() 将光标移离索引末尾 (表示目标行肯定不存在 btree),然后跳转到 SeekGE。P2,结束循环。

  5. 如果光标最终位于目标行之后的有效行上 (表示目标行在 btree 中不存在)则 如果 This.P5==0 跳转到 SeekOP.P2,如果 This.P5>0,则跳转到 This.P2。
序列 查找游标 P1 的下一个可用序列号。 将序列号写入寄存器 P2。 在此之后,光标上的序列号将递增 指令。
序列测试 P1 是排序器光标。如果序列计数器当前为零,则跳转 到 P2。无论是否进行跳转,都要递增 序列值。
设置曲奇 将整数值 P3 写入数据库 P1 的 cookie 编号 P2。 P2==1 是架构版本。P2==2 是数据库格式。 P2==3 是推荐的寻呼机缓存 大小,等等。P1==0 是主数据库文件,P1==1 是 用于存储临时表的数据库文件。

在执行此操作码之前,必须启动事务。

如果 P2 是SCHEMA_VERSION cookie(cookie 编号 1),则内部 架构版本设置为 P3-P5。“PRAGMA schema_version=N”语句 将 P5 设置为 1,以便内部架构版本会有所不同 从数据库架构版本,导致架构重置。

SetSubtype Set the subtype value of register P2 to the integer from register P1. If P1 is NULL, clear the subtype from p2.
ShiftLeft Shift the integer value in register P2 to the left by the number of bits specified by the integer in register P1. Store the result in register P3. If either input is NULL, the result is NULL.
ShiftRight Shift the integer value in register P2 to the right by the number of bits specified by the integer in register P1. Store the result in register P3. If either input is NULL, the result is NULL.
SoftNull Set register P1 to have the value NULL as seen by the MakeRecord instruction, but do not free any string or blob memory associated with the register, so that if the value was a string or blob that was previously copied using SCopy, the copies will continue to be valid.
Sort This opcode does exactly the same thing as Rewind except that it increments an undocumented global variable used for testing.

Sorting is accomplished by writing records into a sorting index, then rewinding that index and playing it back from beginning to end. We use the Sort opcode instead of Rewind to do the rewinding so that the global variable will be incremented and regression tests can determine whether or not the optimizer is correctly optimizing out sorts.

SorterCompare P1 is a sorter cursor. This instruction compares a prefix of the record blob in register P3 against a prefix of the entry that the sorter cursor currently points to. Only the first P4 fields of r[P3] and the sorter record are compared.

If either P3 or the sorter contains a NULL in one of their significant fields (not counting the P4 fields at the end which are ignored) then the comparison is assumed to be equal.

Fall through to next instruction if the two records compare equal to each other. Jump to P2 if they are different.

SorterData Write into register P2 the current sorter data for sorter cursor P1. Then clear the column header cache on cursor P3.

This opcode is normally used to move a record out of the sorter and into a register that is the source for a pseudo-table cursor created using OpenPseudo. That pseudo-table cursor is the one that is identified by parameter P3. Clearing the P3 column cache as part of this opcode saves us from having to issue a separate NullRow instruction to clear that cache.

SorterInsert Register P2 holds an SQL index key made using the MakeRecord instructions. This opcode writes that key into the sorter P1. Data for the entry is nil.
SorterNext This opcode works just like Next except that P1 must be a sorter object for which the SorterSort opcode has been invoked. This opcode advances the cursor to the next sorted record, or jumps to P2 if there are no more sorted records.
SorterOpen This opcode works like OpenEphemeral except that it opens a transient index that is specifically designed to sort large tables using an external merge-sort algorithm.

If argument P3 is non-zero, then it indicates that the sorter may assume that a stable sort considering the first P3 fields of each key is sufficient to produce the required results.

SorterSort After all records have been inserted into the Sorter object identified by P1, invoke this opcode to actually do the sorting. Jump to P2 if there are no records to be sorted.

This opcode is an alias for Sort and Rewind that is used for Sorter objects.

SqlExec Run the SQL statement or statements specified in the P4 string. Disable Auth and Trace callbacks while those statements are running if P1 is true.
String The string value P4 of length P1 (bytes) is stored in register P2.

If P3 is not zero and the content of register P3 is equal to P5, then the datatype of the register P2 is converted to BLOB. The content is the same sequence of bytes, it is merely interpreted as a BLOB instead of a string, as if it had been CAST. In other words:

if( P3!=0 and reg[P3]==P5 ) reg[P2] := CAST(reg[P2] as BLOB)

String8 P4 points to a nul terminated UTF-8 string. This opcode is transformed into a String opcode before it is executed for the first time. During this transformation, the length of string P4 is computed and stored as the P1 parameter.
Subtract Subtract the value in register P1 from the value in register P2 and store the result in register P3. If either input is NULL, the result is NULL.
TableLock Obtain a lock on a particular table. This instruction is only used when the shared-cache feature is enabled.

P1 是数据库的 sqlite3.aDb[] 中的数据库索引 在获得锁上。如果 P3==0 或 如果 P3==1,则为写锁。

P2 包含要锁定的表的根页。

P4 包含指向被锁定表名称的指针。这只是 用于在无法获得锁时生成错误消息。

跟踪 如果语句跟踪是 启用。

操作数 P1 必须0x7fffffff,P2 必须为正。

交易 如果尚未在数据库 P1 上启动事务,则在数据库 P1 上开始事务 积极。 如果 P2 不为零,则启动写入事务,或者如果 read-transaction 已处于活动状态,它已升级为 write-transaction。 如果 P2 为零,则启动读取事务。如果 P2 为 2 或更多 然后启动独占事务。

P1 是事务所在的数据库文件的索引 开始。索引 0 是主数据库文件,索引 1 是 用于临时表的文件。2 或更多索引用于 附加的数据库。

如果启动了写入事务,并且 Vdbe.usesStmtJournal 标志为 true(如果 Vdbe 可以修改多行,则设置此标志,并且可能 抛出 ABORT 异常),也可以打开对账单交易。 更具体地说,在数据库中打开语句事务 连接当前未处于自动提交模式,或者如果有其他 活动语句。对账单事务允许通过以下方式进行的更改 VDBE 在出错后回滚,而不必回滚 整个交易。如果未遇到错误,则语句事务 将在 VDBE 停止时自动提交。

如果 P5!=0,则此操作码还会根据 P3 检查架构 cookie 以及针对 P4 的架构生成计数器。 每当数据库架构更改时,Cookie 都会更改其值。 此操作用于检测 cookie 何时发生更改 并且当前进程需要重新读取架构。如果架构 P3 中的 cookie 与数据库标头中的架构 cookie 不同,或者 如果 P4 中的架构生成计数器与当前不同 生成计数器,则引发SQLITE_SCHEMA错误并执行 停止。然后,sqlite3_step() 包装函数可能会重新准备 语句并从头开始重新运行它。

类型检查 将亲和力应用于从 P1 开始的 P2 寄存器范围。 从 P4 中的 Table 对象中获取相关性。如果有任何值 无法强制使用正确的类型,然后引发错误。

此操作码类似于 Affinity,只是此操作码 强制寄存器类型为表列类型。这是用的 实现“严格亲和力”。

生成始终为...仅当 P3 时才检查 STATIC 列 为零。当 P3 不为零时,不进行类型检查 静态生成的列。虚拟列在查询时计算 所以他们永远不会被检查。

前提 条件:

  • P2 应该是 P4 表。
  • 表 P4 应为 STRICT 表。

如果任何前提条件为 false,则发生断言错误。

真空 对整个数据库 P1 进行真空吸尘。P1 表示“main”为 0,并且为 2 或更多 对于附加的数据库。“临时”数据库可能不会被清空。

如果 P2 不为零,则它是一个寄存器,其中包含一个字符串,该字符串为 真空结果应写入的文件。什么时候 P2为零,真空覆盖原始数据库。

变量 将绑定参数 P1 的值传输到寄存器 P2 中

如果参数已命名,则其名称将显示在 P4 中。 P4 值由 sqlite3_bind_parameter_name() 使用。

维贝金 P4 可能是指向sqlite3_vtab结构的指针。如果是这样,请调用 该表的 xBegin 方法。

此外,无论是否设置了 P4,请检查是否未从中调用 在对虚拟表 xSync() 方法的回调中。如果是,则错误 代码将设置为 SQLITE_LOCKED。

VCheck P4 是指向 Table 对象的指针,该对象是架构 P1 中的虚拟表 支持 xIntegrity() 方法。此操作码运行 xIntegrity() 方法,使用 P3 作为整数参数。如果 将报告错误,并在错误之前附加表名 消息,该消息存储在 P2 中。如果未发现任何错误, 寄存器 P2 设置为 NULL。
VColumn 在寄存器 P3 中存储 P2 的值 游标 P1 的虚拟表的当前行。

如果 VColumn 操作码用于获取 在 UPDATE 操作期间不变的列,然后是 P5 value 为 OPFLAG_NOCHNG。这将导致 sqlite3_vtab_nochange() 函数在虚拟的 xColumn 方法中返回 true 表实现。P5 列可能还包含其他 位(OPFLAG_LENGTHARG 或 OPFLAG_TYPEOFARG),但这些位是 VColumn 未使用。

VCreate P2 是一个寄存器,用于保存数据库中虚拟表的名称 第 1 页。调用该表的 xCreate 方法。
VDestroy P4 是数据库 P1 中虚拟表的名称。调用 xDestroy 方法 那张桌子。
VFilter P1 是使用 VOpen 打开的光标。P2 是要跳转到的地址,如果 筛选的结果集为空。

P4 是 NULL 或由 xBestIndex 生成的字符串 模块的方法。P4 字符串的解释是左边的 到模块实现。

此操作码调用指定虚拟表上的 xFilter 方法 由 P1.xFilter 的整数查询计划参数存储在寄存器中 第 3 页。寄存器 P3+1 存储要传递给 xFilter 方法。寄存器 P3+2..P3+1+argc 是 argc 传递给 xFilter 作为 argv。寄存器 P3+2 在传递给 xFilter 时变为 argv[0]。

如果筛选后的结果集为空,则跳转到 P2。

维尼丁 将寄存器 P2 设置为指向游标 P1 的 ValueList 对象的指针 带缓存寄存器 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) 中的值对应于 传递给 xUpdate 的 argv 数组的第 2 个元素。

xUpdate 方法将执行 DELETE 和/或 INSERT 操作。 argv[0] 元素(对应于存储单元 P3) 是要删除的行的 rowid。如果 argv[0] 为 NULL,则 no 发生删除。argv[1] 元素是 new 的 rowid 排。这可以是 NULL 以使虚拟表选择新的 吵吵嚷嚷。数组中的后续元素是 新行中列的值。

如果 P2==1,则不执行插入。argv[0] 是 要删除的行。

P1 是一个布尔标志。如果设置为 true,则 xUpdate 调用 成功,则 sqlite3_last_insert_rowid() 返回的值 设置为刚插入的行的 rowid 值。

P5 是错误操作(OE_Replace、OE_Fail、OE_Ignore 等) 在插入或更新时约束失败时应用。

屈服 将程序计数器与寄存器 P1 中的值交换。这 具有屈服于协程的效果。

如果此指令启动的协程以 Yield 或 Return 结尾,则继续执行下一条指令。但是,如果 此指令启动的协程以 EndCoroutine 结尾,然后跳转到 P2 而不是继续 下一个指令。

另请参阅:InitCoroutine

零或空 如果寄存器 P1 和 P3 都不是 NULL,则将零存储在 寄存器 P2。如果寄存器 P1 或 P3 为 NULL,则将 寄存器 P2 中的 NULL。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-06 03:26:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-06 03:26:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-06 03:26:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-06 03:26:03       20 阅读

热门阅读

  1. 【二分与前缀和】python例题详解

    2024-04-06 03:26:03       14 阅读
  2. minicap安装教程

    2024-04-06 03:26:03       48 阅读
  3. OJ练习第190题——坐标移动

    2024-04-06 03:26:03       13 阅读
  4. 探索Django:打造高效、可扩展的Web应用(下)

    2024-04-06 03:26:03       15 阅读
  5. BL202 耦合器可扩展0-5V输入

    2024-04-06 03:26:03       13 阅读
  6. 常规的k8s的监控指标

    2024-04-06 03:26:03       16 阅读
  7. Spring注入方式解析与实践

    2024-04-06 03:26:03       14 阅读
  8. Python笔记|列表推导式

    2024-04-06 03:26:03       16 阅读
  9. 设计模式:原型模式

    2024-04-06 03:26:03       15 阅读