struct sqlite3_index_info { / *输入* / int nConstraint; / *约束中的条目数* / struct sqlite3_index_constraint { int iColumn; / *列受约束。-1代表ROWID * / 未签名的char op; / *约束运算符* / 可用的未签名字符;/ *如果此约束可用,则为真* / int iTermOffset; / *内部使用-xBestIndex应该忽略* / } * aConstraint; / * WHERE子句约束表* / int nOrderBy; / * ORDER BY子句中的术语数* / struct sqlite3_index_orderby { int iColumn; / *列号* / 未签名的字符描述 / *对于DESC为True。ASC错误。* / } * aOrderBy; / * ORDER BY子句* / / *输出* / struct sqlite3_index_constraint_usage { int argvIndex; / *如果> 0,则约束是xFilter的argv的一部分* / 未签名的字符省略;/ *不要为此约束编写测试代码* / } * aConstraintUsage; int idxNum; / *用于标识索引的数字* / char * idxStr; / *字符串,可能从sqlite3_malloc获得* / int needToFreeIdxStr; / *如果为true,则使用sqlite3_free()免费idxStr * / int orderByConsumed; / *如果已经订购了输出,则为True * / 双倍估算费用;/ *使用此索引的估计成本* / / *以下字段仅在SQLite 3.8.2和更高版本中可用* / sqlite3_int64估计行; / *预计返回的行数* / / *以下字段仅在SQLite 3.9.0和更高版本中可用* / int idxFlags; / * SQLITE_INDEX_SCAN_ *标志的掩码* / / *以下字段仅在SQLite 3.10.0和更高版本中可用* / sqlite3_uint64 colUsed; / *输入:语句使用的列的掩码* / };
sqlite3_index_info结构及其子结构用作虚拟表接口的一部分,以将信息传递到虚拟表模块的xBestIndex 方法并从中接收答复。**输入**下的字段是xBestIndex的输入,并且是只读的。xBestIndex将其结果插入到“输出”字段中。
aConstraint []数组记录以下形式的WHERE子句约束:
列OP expr
其中OP是=,<,<=,>或> =。使用SQLITE_INDEX_CONSTRAINT_值之一将特定运算符存储在aConstraint [] 。op中。列的索引存储在aConstraint []。iColumn中。如果可以评估右侧的expr(因此约束可用),则aConstraint []。usable为TRUE,否则为false。
优化程序会自动将“ expr OP列”形式的术语转换,并对WHERE子句进行其他简化,以尝试使尽可能多的WHERE子句术语变为上面所示的形式。aConstraint []数组仅报告与要查询的特定虚拟表相关的WHERE子句术语。
有关ORDER BY子句的信息存储在aOrderBy []中。aOrderBy的每个术语记录ORDER BY子句的一列。
colUsed字段指示当前扫描可能需要虚拟表的哪些列。虚拟表列的编号从零开始,按照它们在传递给sqlite3_declare_vtab()的CREATE TABLE语句中出现的顺序。对于前63列(第0-62列),如果SQLite可能需要该列,则在colUsed掩码内设置相应的位。如果表中至少有64列,并且必须在前63列的右边添加任何列,则colUsed的位63也将被设置。换句话说,如果表达式(colUsed&(((sqlite3_uint64)1 <<(iCol> = 63?63:iCol)))的计算结果为非零,则可能需要列iCol。
该xBestIndex方法必须填写aConstraintUsage []用什么参数传递给xFilter信息。如果argvIndex> 0,则将评估相应aConstraint []的右侧,并成为argv中的第argvIndex个条目。如果aConstraintUsage []。omit为true,则假定该约束已由虚拟表完全处理,并且字节码可能不会再次对其进行检查。aConstraintUsage []。omit标志是一个优化提示。当省略标志保留为默认设置false时,将始终以字节码单独检查约束。如果省略标志更改为true,则可以以字节码检查约束,也可以不以字节码检查约束。换句话说,当省略标志为true时,不能保证不会使用字节码再次检查约束。
记录idxNum和idxPtr值,并将其传递到 xFilter方法中。 当且仅当needToFreeIdxPtr为true时,才使用sqlite3_free()释放idxPtr。
orderByConsumed表示xFilter / xNext的输出将以正确的顺序出现,以满足ORDER BY子句,因此不需要单独的排序步骤。
EstimatedCost值是对特定策略成本的估计。成本为N表示该策略的成本类似于对具有N行的SQLite表的线性扫描。log(N)的开销表示该操作的开销类似于在具有N行的SQLite表的唯一索引字段上进行二进制搜索的开销。
EstimateRows值是该策略将返回的行数的估计值。
xBestIndex方法可以选择使用SQLITE_INDEX_SCAN_ *标志的掩码填充idxFlags字段。当前只有一个这样的标志-SQLITE_INDEX_SCAN_UNIQUE。如果xBestIndex方法设置了此标志,则SQLite会假定该策略最多可以访问一行。
此外,如果xBestIndex设置了SQLITE_INDEX_SCAN_UNIQUE标志,则SQLite还将假定,如果在同一语句中调用xUpdate()方法以删除或更新虚拟表行,并且实现返回SQLITE_CONSTRAINT,则不需要回滚任何数据库更改。换句话说,如果xUpdate()返回SQLITE_CONSTRAINT,则数据库内容必须与调用xUpdate之前的内容完全相同。相反,如果未设置SQLITE_INDEX_SCAN_UNIQUE且xUpdate返回SQLITE_CONSTRAINT,则SQLite会自动回滚xUpdate方法所做的任何数据库更改。
重要信息:SQLite版本3.8.2(2013-12-06)的EstimatedRows字段已添加到sqlite3_index_info结构中。如果虚拟表扩展名与3.8.2之前的SQLite版本一起使用,则尝试读取或写入estimatedRows字段的结果是不确定的(但可能会导致应用程序崩溃)。因此,仅当sqlite3_libversion_number()返回的值大于或等于3008002时,才应使用estimatedRows字段。类似地,为版本3.9.0(2015-10-14)添加了idxFlags字段。因此,只有在sqlite3_libversion_number()返回的值大于或等于3009000时,才可以使用它。