int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
此接口只能在虚拟表实现的 xBestIndex() 方法 中使用。在任何其他上下文中调用此接口的结果是未定义的,并且可能造成危害。
虚拟表上形式为 "column IN (...)" 的约束会作为 SQLITE_INDEX_CONSTRAINT_EQ 约束传递给 xBestIndex 方法。如果 xBestIndex 想要使用此约束,则必须将相应的 aConstraintUsage[].argvIndex 设置为正整数。然后,在处理 IN 运算符的常用模式下,SQLite 生成 字节码,该字节码为 IN 运算符右侧的每个值调用一次 xFilter() 方法。因此,虚拟表一次只能看到 IN 运算符右侧的一个值。
但是,在某些情况下,让虚拟表一次看到 IN 运算符右侧的所有值将更有利。sqlite3_vtab_in() 接口通过两种方式促进了这一点
仅当 P->aConstraint[N] 约束为可以一次处理的 IN 运算符 时,对 sqlite3_vtab_in(P,N,-1) 的调用才会返回 true(非零)。换句话说,sqlite3_vtab_in() 在第三个参数中使用 -1 是一种机制,通过该机制,虚拟表可以询问 SQLite 是否甚至可以进行 IN 运算符的一次性处理。
对 sqlite3_vtab_in(P,N,F) 的调用,其中 F==1 或 F==0,分别指示 SQLite 虚拟表是否想要一次性处理 IN 运算符。因此,当第三个参数 (F) 为非负数时,此接口是虚拟表告诉 SQLite 如何处理 IN 运算符的机制。
可以在同一个 xBestIndex 方法调用中多次调用 sqlite3_vtab_in(P,N,F) 接口。对于任何给定的 P,N 对,sqlite3_vtab_in(P,N,F) 的返回值在同一个 xBestIndex 调用中始终相同。如果接口返回 true(非零),则表示该约束是可以一次处理的 IN 运算符。如果该约束不是 IN 运算符或无法一次处理,则该接口返回 false。
如果满足以下两个条件,则选择 IN 运算符的一次性处理
P->aConstraintUsage[N].argvIndex 值设置为正整数。这是虚拟表告诉 SQLite 它想要使用第 N 个约束的方式。
F 为非负数的最后一个 sqlite3_vtab_in(P,N,F) 调用具有 F>=1。
如果上述任一条件或两个条件均不满足,则 SQLite 对 IN 约束使用传统的一次性处理策略。如果两个条件都满足,则 xFilter 方法的 argvIndex-th 参数将是一个 sqlite3_value,它看起来为 NULL,但可以传递给 sqlite3_vtab_in_first() 和 sqlite3_vtab_in_next() 以查找 IN 约束右侧的所有值。