📄 vdbe.html
字号:
illustrate our points. The result will have three column withnames "one", "two", and "both". The first two columns are directcopies of the two columns in the table and the third resultcolumn is a string formed by concatenating the first andsecond columns of the table.Finally, theWHERE clause says that we will only chose rows for the results where the "one" column begins with an "H".Here is what the VDBE program looks like for this query:</p><blockquote><tt>addr opcode p1 p2 p3 <br>---- ------------ ----- ----- -----------------------------------<br>0 ColumnName 0 0 one<br>1 ColumnName 1 0 two<br>2 ColumnName 2 0 both<br>3 Integer 0 0<br>4 OpenRead 0 3 examp<br>5 VerifyCookie 0 81<br>6 Rewind 0 18<br>7 String 0 0 H% <br>8 Column 0 0<br>9 Function 2 0 ptr(0x7f1ac0)<br>10 IfNot 1 17<br>11 Column 0 0<br>12 Column 0 1<br>13 Column 0 0<br>14 Column 0 1<br>15 Concat 2 0<br>16 Callback 3 0<br>17 Next 0 7<br>18 Close 0 0<br>19 Halt 0 0</tt></blockquote><p>Except for the WHERE clause, the structure of the program forthis example is very much like the prior example, just with anextra column. There are now 3 columns, instead of 2 as before,and there are three ColumnName instructions.A cursor is opened using the OpenRead instruction, just like in theprior example. The Rewind instruction at address 6 and theNext at address 17 form a loop over all records of the table. The Close instruction at the end is there to give theRewind instruction something to jump to when it is done. All ofthis is just like in the first query demonstration.</p><p>The Callback instruction in this example has to generatedata for three result columns instead of two, but is otherwisethe same as in the first query. When the Callback instructionis invoked, the left-most column of the result should bethe lowest in the stack and the right-most result column shouldbe the top of the stack. We can see the stack being set up this way at addresses 11 through 15. The Column instructions at11 and 12 push the values for the first two columns in the result.The two Column instructions at 13 and 14 pull in the values neededto compute the third result column and the Concat instruction at15 joins them together into a single entry on the stack.</p><p>The only thing that is really new about the current exampleis the WHERE clause which is implemented by instructions ataddresses 7 through 10. Instructions at address 7 and 8 pushonto the stack the value of the "one" column from the tableand the literal string "H%". The <a href="opcode.html#Function">Function</a> instruction at address 9 pops these two values from the stack and pushes the result of the LIKE() function back onto the stack. The <a href="opcode.html#IfNot">IfNot</a> instruction pops the top stack value and causes an immediate jump forward to the Next instruction if the top value was false (<em>not</em> not like the literal string "H%"). Taking this jump effectively skips the callback, which is the whole pointof the WHERE clause. If the resultof the comparison is true, the jump is not taken and controlfalls through to the Callback instruction below.</p><p>Notice how the LIKE operator is implemented. It is a user-defined function in SQLite, so the address of its function definition is specified in P3. The operand P1 is the number of function arguments for it to take from the stack. In this case the LIKE() function takes 2 arguments. The arguments are taken off the stack in reverse order (right-to-left), so the pattern to match is the top stack element, and the next element is the data to compare. The return value is pushed onto the stack.</p><a name="pattern1"></a><h2>A Template For SELECT Programs</h2><p>The first two query examples illustrate a kind of template thatevery SELECT program will follow. Basically, we have:</p><p><ol><li>Initialize the <b>azColumnName[]</b> array for the callback.</li><li>Open a cursor into the table to be queried.</li><li>For each record in the table, do: <ol type="a"> <li>If the WHERE clause evaluates to FALSE, then skip the steps that follow and continue to the next record.</li> <li>Compute all columns for the current row of the result.</li> <li>Invoke the callback function for the current row of the result.</li> </ol><li>Close the cursor.</li></ol></p><p>This template will be expanded considerably as we consideradditional complications such as joins, compound selects, usingindices to speed the search, sorting, and aggregate functionswith and without GROUP BY and HAVING clauses.But the same basic ideas will continue to apply.</p><h2>UPDATE And DELETE Statements</h2><p>The UPDATE and DELETE statements are coded using a templatethat is very similar to the SELECT statement template. The maindifference, of course, is that the end action is to modify thedatabase rather than invoke a callback function. Because it modifies the database it will also use transactions. Let's beginby looking at a DELETE statement:</p><blockquote><pre>DELETE FROM examp WHERE two<50;</pre></blockquote><p>This DELETE statement will remove every record from the "examp"table where the "two" column is less than 50.The code generated to do this is as follows:</p><blockquote><tt>addr opcode p1 p2 p3 <br>---- ------------ ----- ----- -----------------------------------<br>0 Transaction 1 0<br>1 Transaction 0 0<br>2 VerifyCookie 0 178<br>3 Integer 0 0<br>4 OpenRead 0 3 examp<br>5 Rewind 0 12<br>6 Column 0 1<br>7 Integer 50 0 50<br>8 Ge 1 11<br>9 Recno 0 0<br>10 ListWrite 0 0<br>11 Next 0 6<br>12 Close 0 0<br>13 ListRewind 0 0<br>14 Integer 0 0<br>15 OpenWrite 0 3<br>16 ListRead 0 20<br>17 NotExists 0 19<br>18 Delete 0 1<br>19 Goto 0 16<br>20 ListReset 0 0<br>21 Close 0 0<br>22 Commit 0 0<br>23 Halt 0 0</tt></blockquote><p>Here is what the program must do. First it has to locate all ofthe records in the table "examp" that are to be deleted. This isdone using a loop very much like the loop used in the SELECT examplesabove. Once all records have been located, then we can go back throughand delete them one by one. Note that we cannot delete each recordas soon as we find it. We have to locate all records first, thengo back and delete them. This is because the SQLite databasebackend might change the scan order after a delete operation.And if the scanorder changes in the middle of the scan, some records might bevisited more than once and other records might not be visited at all.</p><p>So the implemention of DELETE is really in two loops. The first loop (instructions 5 through 11) locates the records that are to be deleted and saves their keys onto a temporary list, and the second loop (instructions 16 through 19) uses the key list to delete the records one by one. </p><blockquote><tt>0 Transaction 1 0<br>1 Transaction 0 0<br>2 VerifyCookie 0 178<br>3 Integer 0 0<br>4 OpenRead 0 3 examp</tt></blockquote><p>Instructions 0 though 4 are as in the INSERT example. They start transactions for the main and temporary databases, verify the database schema for the main database, and open a read cursor on the table "examp". Notice that the cursor is opened for reading, not writing. At this stage of the program we are only going to be scanning the table, not changing it. We will reopen the same table for writing later, at instruction 15.</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -