1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
<!DOCTYPE html>
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link href="../sqlite.css" rel="stylesheet">
<title>Virtual Table Indexing Information</title>
<!-- path=../ -->
</head>
<body>
<div class=nosearch>
<a href="../index.html">
<img class="logo" src="../images/sqlite370_banner.gif" alt="SQLite" border="0">
</a>
<div><!-- IE hack to prevent disappearing logo --></div>
<div class="tagline desktoponly">
Small. Fast. Reliable.<br>Choose any three.
</div>
<div class="menu mainmenu">
<ul>
<li><a href="../index.html">Home</a>
<li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
<li class='wideonly'><a href='../about.html'>About</a>
<li class='desktoponly'><a href="../docs.html">Documentation</a>
<li class='desktoponly'><a href="../download.html">Download</a>
<li class='wideonly'><a href='../copyright.html'>License</a>
<li class='desktoponly'><a href="../support.html">Support</a>
<li class='desktoponly'><a href="../prosupport.html">Purchase</a>
<li class='search' id='search_menubutton'>
<a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
</ul>
</div>
<div class="menu submenu" id="submenu">
<ul>
<li><a href='../about.html'>About</a>
<li><a href='../docs.html'>Documentation</a>
<li><a href='../download.html'>Download</a>
<li><a href='../support.html'>Support</a>
<li><a href='../prosupport.html'>Purchase</a>
</ul>
</div>
<div class="searchmenu" id="searchmenu">
<form method="GET" action="../search">
<select name="s" id="searchtype">
<option value="d">Search Documentation</option>
<option value="c">Search Changelog</option>
</select>
<input type="text" name="q" id="searchbox" value="">
<input type="submit" value="Go">
</form>
</div>
</div>
<script>
function toggle_div(nm) {
var w = document.getElementById(nm);
if( w.style.display=="block" ){
w.style.display = "none";
}else{
w.style.display = "block";
}
}
function toggle_search() {
var w = document.getElementById("searchmenu");
if( w.style.display=="block" ){
w.style.display = "none";
} else {
w.style.display = "block";
setTimeout(function(){
document.getElementById("searchbox").focus()
}, 30);
}
}
function div_off(nm){document.getElementById(nm).style.display="none";}
window.onbeforeunload = function(e){div_off("submenu");}
/* Disable the Search feature if we are not operating from CGI, since */
/* Search is accomplished using CGI and will not work without it. */
if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
document.getElementById("search_menubutton").style.display = "none";
}
/* Used by the Hide/Show button beside syntax diagrams, to toggle the */
function hideorshow(btn,obj){
var x = document.getElementById(obj);
var b = document.getElementById(btn);
if( x.style.display!='none' ){
x.style.display = 'none';
b.innerHTML='show';
}else{
x.style.display = '';
b.innerHTML='hide';
}
return false;
}
var antiRobot = 0;
function antiRobotGo(){
if( antiRobot!=3 ) return;
antiRobot = 7;
var j = document.getElementById("mtimelink");
if(j && j.hasAttribute("data-href")) j.href=j.getAttribute("data-href");
}
function antiRobotDefense(){
document.body.onmousedown=function(){
antiRobot |= 2;
antiRobotGo();
document.body.onmousedown=null;
}
document.body.onmousemove=function(){
antiRobot |= 2;
antiRobotGo();
document.body.onmousemove=null;
}
setTimeout(function(){
antiRobot |= 1;
antiRobotGo();
}, 100)
antiRobotGo();
}
antiRobotDefense();
</script>
<!-- keywords: sqlite3_index_info -->
<div class=nosearch>
<a href="intro.html"><h2>SQLite C Interface</h2></a>
<h2>Virtual Table Indexing Information</h2>
</div>
<blockquote><pre>
struct sqlite3_index_info {
/* Inputs */
int nConstraint; /* Number of entries in aConstraint */
struct sqlite3_index_constraint {
int iColumn; /* Column constrained. -1 for ROWID */
unsigned char op; /* Constraint operator */
unsigned char usable; /* True if this constraint is usable */
int iTermOffset; /* Used internally - xBestIndex should ignore */
} *aConstraint; /* Table of WHERE clause constraints */
int nOrderBy; /* Number of terms in the ORDER BY clause */
struct sqlite3_index_orderby {
int iColumn; /* Column number */
unsigned char desc; /* True for DESC. False for ASC. */
} *aOrderBy; /* The ORDER BY clause */
/* Outputs */
struct sqlite3_index_constraint_usage {
int argvIndex; /* if >0, constraint is part of argv to xFilter */
unsigned char omit; /* Do not code a test for this constraint */
} *aConstraintUsage;
int idxNum; /* Number used to identify the index */
char *idxStr; /* String, possibly obtained from sqlite3_malloc */
int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
int orderByConsumed; /* True if output is already ordered */
double estimatedCost; /* Estimated cost of using this index */
/* Fields below are only available in SQLite 3.8.2 and later */
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
/* Fields below are only available in SQLite 3.9.0 and later */
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
/* Fields below are only available in SQLite 3.10.0 and later */
sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */
};
</pre></blockquote>
<p>
The sqlite3_index_info structure and its substructures is used as part
of the <a href="../vtab.html">virtual table</a> interface to
pass information into and receive the reply from the <a href="../vtab.html#xbestindex">xBestIndex</a>
method of a <a href="../c3ref/module.html">virtual table module</a>. The fields under **Inputs** are the
inputs to xBestIndex and are read-only. xBestIndex inserts its
results into the **Outputs** fields.</p>
<p>The aConstraint[] array records WHERE clause constraints of the form:</p>
<p><blockquote>column OP expr</blockquote></p>
<p>where OP is =, <, <=, >, or >=. The particular operator is
stored in aConstraint[].op using one of the
<a href="../c3ref/c_index_constraint_eq.html">SQLITE_INDEX_CONSTRAINT_ values</a>.
The index of the column is stored in
aConstraint[].iColumn. aConstraint[].usable is TRUE if the
expr on the right-hand side can be evaluated (and thus the constraint
is usable) and false if it cannot.</p>
<p>The optimizer automatically inverts terms of the form "expr OP column"
and makes other simplifications to the WHERE clause in an attempt to
get as many WHERE clause terms into the form shown above as possible.
The aConstraint[] array only reports WHERE clause terms that are
relevant to the particular virtual table being queried.</p>
<p>Information about the ORDER BY clause is stored in aOrderBy[].
Each term of aOrderBy records a column of the ORDER BY clause.</p>
<p>The colUsed field indicates which columns of the virtual table may be
required by the current scan. Virtual table columns are numbered from
zero in the order in which they appear within the CREATE TABLE statement
passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
the corresponding bit is set within the colUsed mask if the column may be
required by SQLite. If the table has at least 64 columns and any column
to the right of the first 63 is required, then bit 63 of colUsed is also
set. In other words, column iCol may be required if the expression
(colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
non-zero.</p>
<p>The <a href="../vtab.html#xbestindex">xBestIndex</a> method must fill aConstraintUsage[] with information
about what parameters to pass to xFilter. If argvIndex>0 then
the right-hand side of the corresponding aConstraint[] is evaluated
and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
is true, then the constraint is assumed to be fully handled by the
virtual table and might not be checked again by the byte code. The
aConstraintUsage[].omit flag is an optimization hint. When the omit flag
is left in its default setting of false, the constraint will always be
checked separately in byte code. If the omit flag is change to true, then
the constraint may or may not be checked in byte code. In other words,
when the omit flag is true there is no guarantee that the constraint will
not be checked again using byte code.</p>
<p>The idxNum and idxPtr values are recorded and passed into the
<a href="../vtab.html#xfilter">xFilter</a> method.
<a href="../c3ref/free.html">sqlite3_free()</a> is used to free idxPtr if and only if
needToFreeIdxPtr is true.</p>
<p>The orderByConsumed means that output from <a href="../vtab.html#xfilter">xFilter</a>/<a href="../vtab.html#xnext">xNext</a> will occur in
the correct order to satisfy the ORDER BY clause so that no separate
sorting step is required.</p>
<p>The estimatedCost value is an estimate of the cost of a particular
strategy. A cost of N indicates that the cost of the strategy is similar
to a linear scan of an SQLite table with N rows. A cost of log(N)
indicates that the expense of the operation is similar to that of a
binary search on a unique indexed field of an SQLite table with N rows.</p>
<p>The estimatedRows value is an estimate of the number of rows that
will be returned by the strategy.</p>
<p>The xBestIndex method may optionally populate the idxFlags field with a
mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
assumes that the strategy may visit at most one row.</p>
<p>Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
SQLite also assumes that if a call to the xUpdate() method is made as
part of the same statement to delete or update a virtual table row and the
implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
any database changes. In other words, if the xUpdate() returns
SQLITE_CONSTRAINT, the database contents must be exactly as they were
before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
the xUpdate method are automatically rolled back by SQLite.</p>
<p>IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
structure for SQLite <a href="../releaselog/3_8_2.html">version 3.8.2</a> (2013-12-06).
If a virtual table extension is
used with an SQLite version earlier than 3.8.2, the results of attempting
to read or write the estimatedRows field are undefined (but are likely
to include crashing the application). The estimatedRows field should
therefore only be used if <a href="../c3ref/libversion.html">sqlite3_libversion_number()</a> returns a
value greater than or equal to 3008002. Similarly, the idxFlags field
was added for <a href="../releaselog/3_9_0.html">version 3.9.0</a> (2015-10-14).
It may therefore only be used if
sqlite3_libversion_number() returns a value greater than or equal to
3009000.
</p><p>3 Methods:
<a href="../c3ref/vtab_collation.html">sqlite3_vtab_collation()</a>,
<a href="../c3ref/vtab_distinct.html">sqlite3_vtab_distinct()</a>,
<a href="../c3ref/vtab_rhs_value.html">sqlite3_vtab_rhs_value()</a></p>
<p>See also lists of
<a href="objlist.html">Objects</a>,
<a href="constlist.html">Constants</a>, and
<a href="funclist.html">Functions</a>.</p>
|