<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 21 Mar 2018, at 16:14, Kirill Yukhin <<a href="mailto:kyukhin@tarantool.org" class="">kyukhin@tarantool.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Hello,</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">My comments inlined.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">On 21 мар 02:48, Nikita Pettik wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">Originally in SQLite, to open table (i.e. btree) it was required to pass<br class="">number of page root to OP_OpenRead or OP_OpenWrite opcodes as an<br class="">argument. However, now there are only Tarantool spaces and nothing<br class="">prevents from operating directly on pointers to them. On the other hand,<br class="">pointers are able to expire after schema changes (i.e. after DML<br class="">routine). For this reason, schema version is saved to VDBE at compile<br class="">time and checked each time during cursor opening.<br class=""><br class="">Part of #3252<br class="">---<br class="">src/box/sql/analyze.c | 17 +++++++++++++++--<br class="">src/box/sql/build.c   |  7 ++++++-<br class="">src/box/sql/expr.c    | 14 ++++++++++++--<br class="">src/box/sql/fkey.c    | 11 ++++++++++-<br class="">src/box/sql/insert.c  | 37 ++++++++++++++++++++++++++++++++-----<br class="">src/box/sql/select.c  | 11 ++++++++++-<br class="">src/box/sql/vdbe.c    | 12 ++++++++++--<br class="">src/box/sql/vdbe.h    |  1 +<br class="">src/box/sql/vdbeInt.h |  1 +<br class="">src/box/sql/vdbeaux.c | 13 +++++++++++++<br class="">src/box/sql/where.c   | 12 +++++++++++-<br class="">11 files changed, 121 insertions(+), 15 deletions(-)<br class=""><br class="">diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c<br class="">index db06d0182..57fc33c70 100644<br class="">diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c<br class="">index 9929dfb96..5d1227afa 100644<br class="">--- a/src/box/sql/vdbe.c<br class="">+++ b/src/box/sql/vdbe.c<br class="">@@ -3217,9 +3217,17 @@ case OP_OpenWrite:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>assert(p2 >= 1);<br class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>pBtCur = pCur->uc.pCursor;<br class="">-<span class="Apple-tab-span" style="white-space: pre;">       </span>pBtCur->space = space_by_id(SQLITE_PAGENO_TO_SPACEID(p2));<br class="">+<span class="Apple-tab-span" style="white-space: pre;">       </span>if (box_schema_version() == p->schema_ver) {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-tab-span" style="white-space: pre;">  </span>pIn3 = &aMem[pOp->p3];<br class="">+<span class="Apple-tab-span" style="white-space: pre;">       </span><span class="Apple-tab-span" style="white-space: pre;">  </span>/* Make sure that 64-bit pointer can fit into int64_t. */<br class="">+<span class="Apple-tab-span" style="white-space: pre;">   </span><span class="Apple-tab-span" style="white-space: pre;">  </span>assert(sizeof(pBtCur->space) >= sizeof(pIn3->u.i));<br class=""></blockquote><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I don't like this. If we're going to extensively use pointers space/index then</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">let's extend Memory struct adding dedicated types to the union.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Note, that new opcode (say, LoadPtr) will be needed.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Done. </div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">+<span class="Apple-tab-span" style="white-space: pre;">      </span><span class="Apple-tab-span" style="white-space: pre;">  </span>pBtCur->space = ((struct space *) pIn3->u.i);<br class="">+<span class="Apple-tab-span" style="white-space: pre;"> </span>} else {<br class="">+<span class="Apple-tab-span" style="white-space: pre;">    </span><span class="Apple-tab-span" style="white-space: pre;">  </span>pBtCur->space = space_by_id(SQLITE_PAGENO_TO_SPACEID(p2));<br class="">+<span class="Apple-tab-span" style="white-space: pre;">       </span>}<br class=""></blockquote><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Don't surround single stmt withcurly braces pls.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>This is only only advise (<a href="https://www.kernel.org/doc/html/v4.10/process/coding-style.html#placing-braces-and-spaces" class="">https://www.kernel.org/doc/html/v4.10/process/coding-style.html#placing-braces-and-spaces</a>):</div><div><p style="box-sizing: border-box; margin: 0px 0px 10px; color: rgb(38, 38, 38); font-family: 'Open Sans', sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255);" class="">"Do not unnecessarily use braces where a single statement will do."</p><div class="">So, I guess, both variants are allowed. </div><div class="highlight-c" style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0.75em; color: rgb(38, 38, 38); font-family: 'Open Sans', sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); position: relative;"><div class="highlight" style="box-sizing: border-box; margin: 5px 0px; border-top-left-radius: 7px; border-top-right-radius: 7px; border-bottom-right-radius: 7px; border-bottom-left-radius: 7px; font-size: 13px; color: rgb(248, 248, 242); background-color: rgb(31, 30, 30); overflow-x: auto; background-position: initial initial; background-repeat: initial initial;"></div></div></div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Also, if schema was changed then error should be returned (stmt expired or</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">smth).</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div>I have dedicated separate patch (the last one) for this issue.</div><div>It can’t be done right here since new DDL processing is also</div><div>introduced in next patch. In order to make no confusions,</div><div>I will remove this diff and place it to the last patch.</div><div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h<br class="">index 7241963e4..a1ecf729d 100644<br class="">--- a/src/box/sql/vdbe.h<br class="">+++ b/src/box/sql/vdbe.h<br class="">diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h<br class="">index 8b622de5b..99262ab7b 100644<br class="">--- a/src/box/sql/vdbeInt.h<br class="">+++ b/src/box/sql/vdbeInt.h<br class="">@@ -378,6 +378,7 @@ struct Vdbe {<br class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>i64 nFkConstraint;<span class="Apple-tab-span" style="white-space: pre;">        </span>/* Number of imm. FK constraints this VM */<br class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>i64 nStmtDefCons;<span class="Apple-tab-span" style="white-space: pre;"> </span>/* Number of def. constraints when stmt started */<br class=""><span class="Apple-tab-span" style="white-space: pre;">   </span>i64 nStmtDefImmCons;<span class="Apple-tab-span" style="white-space: pre;">      </span>/* Number of def. imm constraints when stmt started */<br class="">+<span class="Apple-tab-span" style="white-space: pre;">      </span>uint32_t schema_ver;<span class="Apple-tab-span" style="white-space: pre;">      </span>/* Schema version at the moment of VDBE creation. */<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">    </span>/*<br class=""><span class="Apple-tab-span" style="white-space: pre;">   </span><span class="Apple-converted-space"> </span>* In recursive triggers we can execute INSERT/UPDATE OR IGNORE<br class="">diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c<br class="">index 92bf9943b..b35d0712e 100644<br class="">--- a/src/box/sql/vdbeaux.c<br class="">+++ b/src/box/sql/vdbeaux.c<br class="">@@ -66,6 +66,7 @@ sqlite3VdbeCreate(Parse * pParse)<br class=""><span class="Apple-tab-span" style="white-space: pre;">   </span>p->magic = VDBE_MAGIC_INIT;<br class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>p->pParse = pParse;<br class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>p->autoCommit = (char)box_txn() == 0 ? 1 : 0;<br class="">+<span class="Apple-tab-span" style="white-space: pre;">    </span>p->schema_ver = box_schema_version();<br class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>if (!p->autoCommit) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-tab-span" style="white-space: pre;">  </span>p->psql_txn = in_txn()->psql_txn;<br class=""><span class="Apple-tab-span" style="white-space: pre;">      </span><span class="Apple-tab-span" style="white-space: pre;">  </span>p->nDeferredCons = p->psql_txn->nDeferredConsSave;<br class="">@@ -413,6 +414,18 @@ sqlite3VdbeAddOp4Int(Vdbe * p,<span class="Apple-tab-span" style="white-space: pre;">       </span>/* Add the opcode to this VM */<br class=""><span class="Apple-tab-span" style="white-space: pre;">      </span>return addr;<br class="">}<br class=""><br class="">+int<br class="">+sqlite3VdbeAddOp4Int64(Vdbe *p, int op, int p1, int p2, int p3, int64_t p4)<br class="">+{<br class="">+<span class="Apple-tab-span" style="white-space: pre;">    </span>int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);<br class="">+<span class="Apple-tab-span" style="white-space: pre;">    </span>VdbeOp *pOp = &p->aOp[addr];<br class="">+<span class="Apple-tab-span" style="white-space: pre;"> </span>pOp->p4type = P4_INT64;<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>pOp->p4.pI64 = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), sizeof(int64_t));<br class="">+<span class="Apple-tab-span" style="white-space: pre;">  </span>if (p->db->mallocFailed == 0)<br class="">+<span class="Apple-tab-span" style="white-space: pre;"> </span><span class="Apple-tab-span" style="white-space: pre;">  </span>*pOp->p4.pI64 = p4;<br class="">+<span class="Apple-tab-span" style="white-space: pre;">      </span>return addr;<br class="">+}<br class=""></blockquote><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">This is useless if LoadPTR will be introduced.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Done.</div><div><br class=""></div><div>The whole patch is below:</div><div>=======================================================================</div><div><br class=""></div><div><div>Originally in SQLite, to open table (i.e. btree) it was required to pass</div><div>number of page root to OP_OpenRead or OP_OpenWrite opcodes as an</div><div>argument. However, now there are only Tarantool spaces and nothing</div><div>prevents from operating directly on pointers to them. Thus, to pass</div><div>pointers from compile time to runtime, opcode OP_LoadPtr has been</div><div>introduced. It fetches pointer from P4 and stores to the register</div><div>specified by P2.</div><div>It is worth mentioning that, pointers are able to expire after schema</div><div>changes (i.e. after DML routine). For this reason, schema version is</div><div>saved to VDBE at compile time and checked each time during cursor</div><div>opening.</div><div><br class=""></div><div>Part of #3252</div><div>---</div><div> src/box/sql/analyze.c |  17 +++++-</div><div> src/box/sql/build.c   |   7 ++-</div><div> src/box/sql/expr.c    |  14 ++++-</div><div> src/box/sql/fkey.c    |  11 +++-</div><div> src/box/sql/insert.c  |  36 ++++++++++--</div><div> src/box/sql/opcodes.c | 137 +++++++++++++++++++++----------------------</div><div> src/box/sql/opcodes.h | 157 +++++++++++++++++++++++++-------------------------</div><div> src/box/sql/select.c  |  11 +++-</div><div> src/box/sql/vdbe.c    |  13 +++++</div><div> src/box/sql/vdbe.h    |   2 +</div><div> src/box/sql/vdbeInt.h |   3 +</div><div> src/box/sql/vdbeaux.c |  11 ++++</div><div> src/box/sql/where.c   |  12 +++-</div><div> 13 files changed, 272 insertions(+), 159 deletions(-)</div><div><br class=""></div><div>diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c</div><div>index db06d0182..d121dd2b9 100644</div><div>--- a/src/box/sql/analyze.c</div><div>+++ b/src/box/sql/analyze.c</div><div>@@ -174,10 +174,16 @@ openStatTable(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">      </span>/* Parsing context */</div><div> </div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>/* Open the sql_stat[134] tables for writing. */</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>for (i = 0; aTable[i]; i++) {</div><div>+<span class="Apple-tab-span" style="white-space:pre">               </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                       </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(aRoot[i]));</div><div>+<span class="Apple-tab-span" style="white-space:pre">            </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">              </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">              </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                            </span>     (void *) space);</div><div> <span class="Apple-tab-span" style="white-space:pre">                </span>int addr;</div><div> <span class="Apple-tab-span" style="white-space:pre">              </span>addr =</div><div> <span class="Apple-tab-span" style="white-space:pre">         </span>    sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur + i, aRoot[i],</div><div>-<span class="Apple-tab-span" style="white-space:pre">                            </span>      0);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                            </span>      space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">           </span>v->aOp[addr].p4.pKeyInfo = 0;</div><div> <span class="Apple-tab-span" style="white-space:pre">               </span>v->aOp[addr].p4type = P4_KEYINFO;</div><div> <span class="Apple-tab-span" style="white-space:pre">           </span>sqlite3VdbeChangeP5(v, aCreateTbl[i]);</div><div>@@ -814,6 +820,7 @@ analyzeOneTable(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">    </span>/* Parser context */</div><div> <span class="Apple-tab-span" style="white-space:pre">   </span>int iTabCur;<span class="Apple-tab-span" style="white-space:pre">                </span>/* Table cursor */</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>Vdbe *v;<span class="Apple-tab-span" style="white-space:pre">            </span>/* The virtual machine being built up */</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>int i;<span class="Apple-tab-span" style="white-space:pre">                      </span>/* Loop counter */</div><div>+<span class="Apple-tab-span" style="white-space:pre">  </span>int space_ptr_reg = iMem++;</div><div> <span class="Apple-tab-span" style="white-space:pre">    </span>int regStat4 = iMem++;<span class="Apple-tab-span" style="white-space:pre">      </span>/* Register to hold Stat4Accum object */</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>int regChng = iMem++;<span class="Apple-tab-span" style="white-space:pre">       </span>/* Index of changed index field */</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>int regKey = iMem++;<span class="Apple-tab-span" style="white-space:pre">        </span>/* Key argument passed to stat_push() */</div><div>@@ -910,7 +917,13 @@ analyzeOneTable(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre"> </span>/* Parser context */</div><div> </div><div> <span class="Apple-tab-span" style="white-space:pre">              </span>/* Open a read-only cursor on the index being analyzed. */</div><div> <span class="Apple-tab-span" style="white-space:pre">             </span>assert(sqlite3SchemaToIndex(db, pIdx->pSchema) == 0);</div><div>-<span class="Apple-tab-span" style="white-space:pre">            </span>sqlite3VdbeAddOp2(v, OP_OpenRead, iIdxCur, pIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">          </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                       </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">               </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">              </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                            </span>     (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">             </span>sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                           </span>  space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">         </span>sqlite3VdbeSetP4KeyInfo(pParse, pIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">         </span>VdbeComment((v, "%s", pIdx->zName));</div><div> </div><div>diff --git a/src/box/sql/build.c b/src/box/sql/build.c</div><div>index 9ad0c0605..9cdfd0b7a 100644</div><div>--- a/src/box/sql/build.c</div><div>+++ b/src/box/sql/build.c</div><div>@@ -2603,7 +2603,12 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage)</div><div> <span class="Apple-tab-span" style="white-space:pre">   </span>sqlite3VdbeJumpHere(v, addr1);</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>if (memRootPage < 0)</div><div> <span class="Apple-tab-span" style="white-space:pre">                </span>sqlite3VdbeAddOp2(v, OP_Clear, tnum, 0);</div><div>-<span class="Apple-tab-span" style="white-space:pre">    </span>sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">   </span>struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">  </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                    </span>     (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">     </span>sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, space_ptr_reg,</div><div> <span class="Apple-tab-span" style="white-space:pre">                  </span>  (char *)pKey, P4_KEYINFO);</div><div> <span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3VdbeChangeP5(v,</div><div> <span class="Apple-tab-span" style="white-space:pre">                 </span>    OPFLAG_BULKCSR | ((memRootPage >= 0) ?</div><div>diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c</div><div>index b69a176cb..009538095 100644</div><div>--- a/src/box/sql/expr.c</div><div>+++ b/src/box/sql/expr.c</div><div>@@ -35,7 +35,9 @@</div><div>  */</div><div> #include <box/coll.h></div><div> #include "sqliteInt.h"</div><div>+#include "tarantoolInt.h"</div><div> #include "box/session.h"</div><div>+#include "box/schema.h"</div><div> </div><div> /* Forward declarations */</div><div> static void exprCodeBetween(Parse *, Expr *, int,</div><div>@@ -2586,8 +2588,16 @@ sqlite3FindInIndex(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">  </span>/* Parsing context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                                                  </span>  pIdx->zName),</div><div> <span class="Apple-tab-span" style="white-space:pre">                                                        </span>  P4_DYNAMIC);</div><div> #endif</div><div>-<span class="Apple-tab-span" style="white-space:pre">                                      </span>sqlite3VdbeAddOp2(v, OP_OpenRead, iTab,</div><div>-<span class="Apple-tab-span" style="white-space:pre">                                                     </span>  pIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                      </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                               </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                       </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                      </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                      </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                                      </span>       space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                                     </span>       (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                      </span>sqlite3VdbeAddOp3(v, OP_OpenRead, iTab,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                                     </span>  pIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                                       </span>  space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">                                 </span>sqlite3VdbeSetP4KeyInfo(pParse, pIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">                                 </span>VdbeComment((v, "%s", pIdx->zName));</div><div> <span class="Apple-tab-span" style="white-space:pre">                                      </span>assert(IN_INDEX_INDEX_DESC ==</div><div>diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c</div><div>index 439f38352..77565cb50 100644</div><div>--- a/src/box/sql/fkey.c</div><div>+++ b/src/box/sql/fkey.c</div><div>@@ -35,7 +35,9 @@</div><div>  */</div><div> #include <box/coll.h></div><div> #include "sqliteInt.h"</div><div>+#include "tarantoolInt.h"</div><div> #include "box/session.h"</div><div>+#include "box/schema.h"</div><div> </div><div> #ifndef SQLITE_OMIT_FOREIGN_KEY</div><div> #ifndef SQLITE_OMIT_TRIGGER</div><div>@@ -434,7 +436,14 @@ fkLookupParent(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">   </span>/* Parse context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                    </span>int regTemp = sqlite3GetTempRange(pParse, nCol);</div><div> <span class="Apple-tab-span" style="white-space:pre">                       </span>int regRec = sqlite3GetTempReg(pParse);</div><div> </div><div>-<span class="Apple-tab-span" style="white-space:pre">                        </span>sqlite3VdbeAddOp2(v, OP_OpenRead, iCur, pIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                     </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                               </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pIdx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">                       </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                      </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">                      </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                    </span>     (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                     </span>sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                      </span>  space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">                 </span>sqlite3VdbeSetP4KeyInfo(pParse, pIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">                 </span>for (i = 0; i < nCol; i++) {</div><div> <span class="Apple-tab-span" style="white-space:pre">                                </span>sqlite3VdbeAddOp2(v, OP_Copy,</div><div>diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c</div><div>index 54fcca5c9..4f3e2f316 100644</div><div>--- a/src/box/sql/insert.c</div><div>+++ b/src/box/sql/insert.c</div><div>@@ -34,7 +34,9 @@</div><div>  * to handle INSERT statements in SQLite.</div><div>  */</div><div> #include "sqliteInt.h"</div><div>+#include "tarantoolInt.h"</div><div> #include "box/session.h"</div><div>+#include "box/schema.h"</div><div> </div><div> /*</div><div>  * Generate code that will open pTab as cursor iCur.</div><div>@@ -51,7 +53,12 @@ sqlite3OpenTable(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre"> </span>/* Generate code into this VDBE */</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>Index *pPk = sqlite3PrimaryKeyIndex(pTab);</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>assert(pPk != 0);</div><div> <span class="Apple-tab-span" style="white-space:pre">      </span>assert(pPk->tnum == pTab->tnum);</div><div>-<span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, 0);</div><div>+<span class="Apple-tab-span" style="white-space:pre">        </span>struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pPk->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">  </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                    </span>     (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">     </span>sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>sqlite3VdbeSetP4KeyInfo(pParse, pPk);</div><div> <span class="Apple-tab-span" style="white-space:pre">  </span>VdbeComment((v, "%s", pTab->zName));</div><div> }</div><div>@@ -183,7 +190,7 @@ readsTable(Parse * p, Table * pTab)</div><div> <span class="Apple-tab-span" style="white-space:pre">  </span>for (i = 1; i < iEnd; i++) {</div><div> <span class="Apple-tab-span" style="white-space:pre">                </span>VdbeOp *pOp = sqlite3VdbeGetOp(v, i);</div><div> <span class="Apple-tab-span" style="white-space:pre">          </span>assert(pOp != 0);</div><div>-<span class="Apple-tab-span" style="white-space:pre">           </span>if (pOp->opcode == OP_OpenRead && pOp->p3 == 0) {</div><div>+<span class="Apple-tab-span" style="white-space:pre">             </span>if (pOp->opcode == OP_OpenRead) {</div><div> <span class="Apple-tab-span" style="white-space:pre">                   </span>Index *pIndex;</div><div> <span class="Apple-tab-span" style="white-space:pre">                 </span>int tnum = pOp->p2;</div><div> <span class="Apple-tab-span" style="white-space:pre">                 </span>if (tnum == pTab->tnum) {</div><div>@@ -1560,6 +1567,10 @@ sqlite3OpenTableAndIndices(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">        </span>/* Parsing context */</div><div> <span class="Apple-tab-span" style="white-space:pre">          </span>*piDataCur = iDataCur;</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>if (piIdxCur)</div><div> <span class="Apple-tab-span" style="white-space:pre">          </span>*piIdxCur = iBase;</div><div>+<span class="Apple-tab-span" style="white-space:pre">  </span>struct space *space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pTab->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre"> </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_ptr_reg, 0, (void *) space);</div><div> </div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>/* One iteration of this cycle adds OpenRead/OpenWrite which</div><div> <span class="Apple-tab-span" style="white-space:pre">   </span> * opens cursor for current index.</div><div>@@ -1607,7 +1618,8 @@ sqlite3OpenTableAndIndices(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">   </span>/* Parsing context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                          </span>p5 = 0;</div><div> <span class="Apple-tab-span" style="white-space:pre">                        </span>}</div><div> <span class="Apple-tab-span" style="white-space:pre">                      </span>if (aToOpen == 0 || aToOpen[i + 1]) {</div><div>-<span class="Apple-tab-span" style="white-space:pre">                               </span>sqlite3VdbeAddOp2(v, op, iIdxCur, pIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                           </span>sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                            </span>  space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">                         </span>sqlite3VdbeSetP4KeyInfo(pParse, pIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">                         </span>sqlite3VdbeChangeP5(v, p5);</div><div> <span class="Apple-tab-span" style="white-space:pre">                            </span>VdbeComment((v, "%s", pIdx->zName));</div><div>@@ -1911,10 +1923,24 @@ xferOptimization(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">    </span>/* Parser context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                           </span>break;</div><div> <span class="Apple-tab-span" style="white-space:pre">         </span>}</div><div> <span class="Apple-tab-span" style="white-space:pre">              </span>assert(pSrcIdx);</div><div>-<span class="Apple-tab-span" style="white-space:pre">            </span>sqlite3VdbeAddOp2(v, OP_OpenRead, iSrc, pSrcIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">          </span>struct space *space_src =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                   </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pSrcIdx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">            </span>assert(space_src != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">          </span>int space_src_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">          </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_src_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                </span>     (void *) space_src);</div><div>+<span class="Apple-tab-span" style="white-space:pre">         </span>sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                           </span>  space_src_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">             </span>sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">              </span>VdbeComment((v, "%s", pSrcIdx->zName));</div><div>-<span class="Apple-tab-span" style="white-space:pre">                </span>sqlite3VdbeAddOp2(v, OP_OpenWrite, iDest, pDestIdx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">               </span>struct space *space_dest =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                  </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pDestIdx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">           </span>assert(space_dest != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">         </span>int space_dest_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">         </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0, space_dest_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                               </span>     (void *) space_dest);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                </span>sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                </span>  space_dest_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">            </span>sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);</div><div> <span class="Apple-tab-span" style="white-space:pre">             </span>sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);</div><div> <span class="Apple-tab-span" style="white-space:pre">                </span>VdbeComment((v, "%s", pDestIdx->zName));</div><div>diff --git a/src/box/sql/opcodes.c b/src/box/sql/opcodes.c</div><div>index 7a40b28a8..b108d5f9e 100644</div><div>--- a/src/box/sql/opcodes.c</div><div>+++ b/src/box/sql/opcodes.c</div><div>@@ -78,76 +78,77 @@ const char *sqlite3OpcodeName(int i){</div><div>     /*  64 */ "Integer"          OpHelp("r[P2]=P1"),</div><div>     /*  65 */ "Bool"             OpHelp("r[P2]=P1"),</div><div>     /*  66 */ "Int64"            OpHelp("r[P2]=P4"),</div><div>-    /*  67 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),</div><div>-    /*  68 */ "Null"             OpHelp("r[P2..P3]=NULL"),</div><div>-    /*  69 */ "SoftNull"         OpHelp("r[P1]=NULL"),</div><div>-    /*  70 */ "Blob"             OpHelp("r[P2]=P4 (len=P1, subtype=P3)"),</div><div>-    /*  71 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),</div><div>-    /*  72 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),</div><div>-    /*  73 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),</div><div>-    /*  74 */ "SCopy"            OpHelp("r[P2]=r[P1]"),</div><div>+    /*  67 */ "LoadPtr"          OpHelp("r[P2] = P4"),</div><div>+    /*  68 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),</div><div>+    /*  69 */ "Null"             OpHelp("r[P2..P3]=NULL"),</div><div>+    /*  70 */ "SoftNull"         OpHelp("r[P1]=NULL"),</div><div>+    /*  71 */ "Blob"             OpHelp("r[P2]=P4 (len=P1, subtype=P3)"),</div><div>+    /*  72 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),</div><div>+    /*  73 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),</div><div>+    /*  74 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),</div><div>     /*  75 */ "String8"          OpHelp("r[P2]='P4'"),</div><div>-    /*  76 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),</div><div>-    /*  77 */ "ResultRow"        OpHelp("output=r[P1@P2]"),</div><div>-    /*  78 */ "CollSeq"          OpHelp(""),</div><div>-    /*  79 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),</div><div>-    /*  80 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),</div><div>-    /*  81 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),</div><div>-    /*  82 */ "RealAffinity"     OpHelp(""),</div><div>-    /*  83 */ "Cast"             OpHelp("affinity(r[P1])"),</div><div>-    /*  84 */ "Permutation"      OpHelp(""),</div><div>-    /*  85 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),</div><div>-    /*  86 */ "Column"           OpHelp("r[P3]=PX"),</div><div>-    /*  87 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),</div><div>-    /*  88 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),</div><div>-    /*  89 */ "Count"            OpHelp("r[P2]=count()"),</div><div>-    /*  90 */ "FkCheckCommit"    OpHelp(""),</div><div>-    /*  91 */ "TTransaction"     OpHelp(""),</div><div>-    /*  92 */ "ReadCookie"       OpHelp(""),</div><div>-    /*  93 */ "SetCookie"        OpHelp(""),</div><div>-    /*  94 */ "ReopenIdx"        OpHelp("root=P2"),</div><div>-    /*  95 */ "OpenRead"         OpHelp("root=P2"),</div><div>-    /*  96 */ "OpenWrite"        OpHelp("root=P2"),</div><div>-    /*  97 */ "OpenTEphemeral"   OpHelp("nColumn = P2"),</div><div>-    /*  98 */ "SorterOpen"       OpHelp(""),</div><div>-    /*  99 */ "SequenceTest"     OpHelp("if (cursor[P1].ctr++) pc = P2"),</div><div>-    /* 100 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),</div><div>-    /* 101 */ "Close"            OpHelp(""),</div><div>-    /* 102 */ "ColumnsUsed"      OpHelp(""),</div><div>-    /* 103 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),</div><div>-    /* 104 */ "NextId"           OpHelp("r[P3]=get_max(space_index[P1]{Column[P2]})"),</div><div>-    /* 105 */ "NextIdEphemeral"  OpHelp("r[P3]=get_max(space_index[P1]{Column[P2]})"),</div><div>-    /* 106 */ "FCopy"            OpHelp("reg[P2@cur_frame]= reg[P1@root_frame(OPFLAG_SAME_FRAME)]"),</div><div>-    /* 107 */ "Delete"           OpHelp(""),</div><div>-    /* 108 */ "ResetCount"       OpHelp(""),</div><div>-    /* 109 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),</div><div>-    /* 110 */ "SorterData"       OpHelp("r[P2]=data"),</div><div>-    /* 111 */ "RowData"          OpHelp("r[P2]=data"),</div><div>-    /* 112 */ "NullRow"          OpHelp(""),</div><div>-    /* 113 */ "SorterInsert"     OpHelp("key=r[P2]"),</div><div>-    /* 114 */ "IdxReplace"       OpHelp("key=r[P2]"),</div><div>+    /*  76 */ "SCopy"            OpHelp("r[P2]=r[P1]"),</div><div>+    /*  77 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),</div><div>+    /*  78 */ "ResultRow"        OpHelp("output=r[P1@P2]"),</div><div>+    /*  79 */ "CollSeq"          OpHelp(""),</div><div>+    /*  80 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),</div><div>+    /*  81 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),</div><div>+    /*  82 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),</div><div>+    /*  83 */ "RealAffinity"     OpHelp(""),</div><div>+    /*  84 */ "Cast"             OpHelp("affinity(r[P1])"),</div><div>+    /*  85 */ "Permutation"      OpHelp(""),</div><div>+    /*  86 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),</div><div>+    /*  87 */ "Column"           OpHelp("r[P3]=PX"),</div><div>+    /*  88 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),</div><div>+    /*  89 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),</div><div>+    /*  90 */ "Count"            OpHelp("r[P2]=count()"),</div><div>+    /*  91 */ "FkCheckCommit"    OpHelp(""),</div><div>+    /*  92 */ "TTransaction"     OpHelp(""),</div><div>+    /*  93 */ "ReadCookie"       OpHelp(""),</div><div>+    /*  94 */ "SetCookie"        OpHelp(""),</div><div>+    /*  95 */ "ReopenIdx"        OpHelp("root=P2"),</div><div>+    /*  96 */ "OpenRead"         OpHelp("root=P2"),</div><div>+    /*  97 */ "OpenWrite"        OpHelp("root=P2"),</div><div>+    /*  98 */ "OpenTEphemeral"   OpHelp("nColumn = P2"),</div><div>+    /*  99 */ "SorterOpen"       OpHelp(""),</div><div>+    /* 100 */ "SequenceTest"     OpHelp("if (cursor[P1].ctr++) pc = P2"),</div><div>+    /* 101 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),</div><div>+    /* 102 */ "Close"            OpHelp(""),</div><div>+    /* 103 */ "ColumnsUsed"      OpHelp(""),</div><div>+    /* 104 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),</div><div>+    /* 105 */ "NextId"           OpHelp("r[P3]=get_max(space_index[P1]{Column[P2]})"),</div><div>+    /* 106 */ "NextIdEphemeral"  OpHelp("r[P3]=get_max(space_index[P1]{Column[P2]})"),</div><div>+    /* 107 */ "FCopy"            OpHelp("reg[P2@cur_frame]= reg[P1@root_frame(OPFLAG_SAME_FRAME)]"),</div><div>+    /* 108 */ "Delete"           OpHelp(""),</div><div>+    /* 109 */ "ResetCount"       OpHelp(""),</div><div>+    /* 110 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),</div><div>+    /* 111 */ "SorterData"       OpHelp("r[P2]=data"),</div><div>+    /* 112 */ "RowData"          OpHelp("r[P2]=data"),</div><div>+    /* 113 */ "NullRow"          OpHelp(""),</div><div>+    /* 114 */ "SorterInsert"     OpHelp("key=r[P2]"),</div><div>     /* 115 */ "Real"             OpHelp("r[P2]=P4"),</div><div>-    /* 116 */ "IdxInsert"        OpHelp("key=r[P2]"),</div><div>-    /* 117 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),</div><div>-    /* 118 */ "Clear"            OpHelp("space id = P1"),</div><div>-    /* 119 */ "ResetSorter"      OpHelp(""),</div><div>-    /* 120 */ "ParseSchema2"     OpHelp("rows=r[P1@P2]"),</div><div>-    /* 121 */ "ParseSchema3"     OpHelp("name=r[P1] sql=r[P1+1]"),</div><div>-    /* 122 */ "RenameTable"      OpHelp("P1 = root, P4 = name"),</div><div>-    /* 123 */ "LoadAnalysis"     OpHelp(""),</div><div>-    /* 124 */ "DropTable"        OpHelp(""),</div><div>-    /* 125 */ "DropIndex"        OpHelp(""),</div><div>-    /* 126 */ "DropTrigger"      OpHelp(""),</div><div>-    /* 127 */ "Param"            OpHelp(""),</div><div>-    /* 128 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),</div><div>-    /* 129 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),</div><div>-    /* 130 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),</div><div>-    /* 131 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),</div><div>-    /* 132 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),</div><div>-    /* 133 */ "Expire"           OpHelp(""),</div><div>-    /* 134 */ "IncMaxid"         OpHelp(""),</div><div>-    /* 135 */ "Noop"             OpHelp(""),</div><div>-    /* 136 */ "Explain"          OpHelp(""),</div><div>+    /* 116 */ "IdxReplace"       OpHelp("key=r[P2]"),</div><div>+    /* 117 */ "IdxInsert"        OpHelp("key=r[P2]"),</div><div>+    /* 118 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),</div><div>+    /* 119 */ "Clear"            OpHelp("space id = P1"),</div><div>+    /* 120 */ "ResetSorter"      OpHelp(""),</div><div>+    /* 121 */ "ParseSchema2"     OpHelp("rows=r[P1@P2]"),</div><div>+    /* 122 */ "ParseSchema3"     OpHelp("name=r[P1] sql=r[P1+1]"),</div><div>+    /* 123 */ "RenameTable"      OpHelp("P1 = root, P4 = name"),</div><div>+    /* 124 */ "LoadAnalysis"     OpHelp(""),</div><div>+    /* 125 */ "DropTable"        OpHelp(""),</div><div>+    /* 126 */ "DropIndex"        OpHelp(""),</div><div>+    /* 127 */ "DropTrigger"      OpHelp(""),</div><div>+    /* 128 */ "Param"            OpHelp(""),</div><div>+    /* 129 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),</div><div>+    /* 130 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),</div><div>+    /* 131 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),</div><div>+    /* 132 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),</div><div>+    /* 133 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),</div><div>+    /* 134 */ "Expire"           OpHelp(""),</div><div>+    /* 135 */ "IncMaxid"         OpHelp(""),</div><div>+    /* 136 */ "Noop"             OpHelp(""),</div><div>+    /* 137 */ "Explain"          OpHelp(""),</div><div>   };</div><div>   return azName[i];</div><div> }</div><div>diff --git a/src/box/sql/opcodes.h b/src/box/sql/opcodes.h</div><div>index af2ba1963..7b62f6d80 100644</div><div>--- a/src/box/sql/opcodes.h</div><div>+++ b/src/box/sql/opcodes.h</div><div>@@ -67,76 +67,77 @@</div><div> #define OP_Integer        64 /* synopsis: r[P2]=P1                         */</div><div> #define OP_Bool           65 /* synopsis: r[P2]=P1                         */</div><div> #define OP_Int64          66 /* synopsis: r[P2]=P4                         */</div><div>-#define OP_String         67 /* synopsis: r[P2]='P4' (len=P1)              */</div><div>-#define OP_Null           68 /* synopsis: r[P2..P3]=NULL                   */</div><div>-#define OP_SoftNull       69 /* synopsis: r[P1]=NULL                       */</div><div>-#define OP_Blob           70 /* synopsis: r[P2]=P4 (len=P1, subtype=P3)    */</div><div>-#define OP_Variable       71 /* synopsis: r[P2]=parameter(P1,P4)           */</div><div>-#define OP_Move           72 /* synopsis: r[P2@P3]=r[P1@P3]                */</div><div>-#define OP_Copy           73 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */</div><div>-#define OP_SCopy          74 /* synopsis: r[P2]=r[P1]                      */</div><div>+#define OP_LoadPtr        67 /* synopsis: r[P2] = P4                       */</div><div>+#define OP_String         68 /* synopsis: r[P2]='P4' (len=P1)              */</div><div>+#define OP_Null           69 /* synopsis: r[P2..P3]=NULL                   */</div><div>+#define OP_SoftNull       70 /* synopsis: r[P1]=NULL                       */</div><div>+#define OP_Blob           71 /* synopsis: r[P2]=P4 (len=P1, subtype=P3)    */</div><div>+#define OP_Variable       72 /* synopsis: r[P2]=parameter(P1,P4)           */</div><div>+#define OP_Move           73 /* synopsis: r[P2@P3]=r[P1@P3]                */</div><div>+#define OP_Copy           74 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */</div><div> #define OP_String8        75 /* same as TK_STRING, synopsis: r[P2]='P4'    */</div><div>-#define OP_IntCopy        76 /* synopsis: r[P2]=r[P1]                      */</div><div>-#define OP_ResultRow      77 /* synopsis: output=r[P1@P2]                  */</div><div>-#define OP_CollSeq        78</div><div>-#define OP_Function0      79 /* synopsis: r[P3]=func(r[P2@P5])             */</div><div>-#define OP_Function       80 /* synopsis: r[P3]=func(r[P2@P5])             */</div><div>-#define OP_AddImm         81 /* synopsis: r[P1]=r[P1]+P2                   */</div><div>-#define OP_RealAffinity   82</div><div>-#define OP_Cast           83 /* synopsis: affinity(r[P1])                  */</div><div>-#define OP_Permutation    84</div><div>-#define OP_Compare        85 /* synopsis: r[P1@P3] <-> r[P2@P3]            */</div><div>-#define OP_Column         86 /* synopsis: r[P3]=PX                         */</div><div>-#define OP_Affinity       87 /* synopsis: affinity(r[P1@P2])               */</div><div>-#define OP_MakeRecord     88 /* synopsis: r[P3]=mkrec(r[P1@P2])            */</div><div>-#define OP_Count          89 /* synopsis: r[P2]=count()                    */</div><div>-#define OP_FkCheckCommit  90</div><div>-#define OP_TTransaction   91</div><div>-#define OP_ReadCookie     92</div><div>-#define OP_SetCookie      93</div><div>-#define OP_ReopenIdx      94 /* synopsis: root=P2                          */</div><div>-#define OP_OpenRead       95 /* synopsis: root=P2                          */</div><div>-#define OP_OpenWrite      96 /* synopsis: root=P2                          */</div><div>-#define OP_OpenTEphemeral  97 /* synopsis: nColumn = P2                     */</div><div>-#define OP_SorterOpen     98</div><div>-#define OP_SequenceTest   99 /* synopsis: if (cursor[P1].ctr++) pc = P2    */</div><div>-#define OP_OpenPseudo    100 /* synopsis: P3 columns in r[P2]              */</div><div>-#define OP_Close         101</div><div>-#define OP_ColumnsUsed   102</div><div>-#define OP_Sequence      103 /* synopsis: r[P2]=cursor[P1].ctr++           */</div><div>-#define OP_NextId        104 /* synopsis: r[P3]=get_max(space_index[P1]{Column[P2]}) */</div><div>-#define OP_NextIdEphemeral 105 /* synopsis: r[P3]=get_max(space_index[P1]{Column[P2]}) */</div><div>-#define OP_FCopy         106 /* synopsis: reg[P2@cur_frame]= reg[P1@root_frame(OPFLAG_SAME_FRAME)] */</div><div>-#define OP_Delete        107</div><div>-#define OP_ResetCount    108</div><div>-#define OP_SorterCompare 109 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */</div><div>-#define OP_SorterData    110 /* synopsis: r[P2]=data                       */</div><div>-#define OP_RowData       111 /* synopsis: r[P2]=data                       */</div><div>-#define OP_NullRow       112</div><div>-#define OP_SorterInsert  113 /* synopsis: key=r[P2]                        */</div><div>-#define OP_IdxReplace    114 /* synopsis: key=r[P2]                        */</div><div>+#define OP_SCopy          76 /* synopsis: r[P2]=r[P1]                      */</div><div>+#define OP_IntCopy        77 /* synopsis: r[P2]=r[P1]                      */</div><div>+#define OP_ResultRow      78 /* synopsis: output=r[P1@P2]                  */</div><div>+#define OP_CollSeq        79</div><div>+#define OP_Function0      80 /* synopsis: r[P3]=func(r[P2@P5])             */</div><div>+#define OP_Function       81 /* synopsis: r[P3]=func(r[P2@P5])             */</div><div>+#define OP_AddImm         82 /* synopsis: r[P1]=r[P1]+P2                   */</div><div>+#define OP_RealAffinity   83</div><div>+#define OP_Cast           84 /* synopsis: affinity(r[P1])                  */</div><div>+#define OP_Permutation    85</div><div>+#define OP_Compare        86 /* synopsis: r[P1@P3] <-> r[P2@P3]            */</div><div>+#define OP_Column         87 /* synopsis: r[P3]=PX                         */</div><div>+#define OP_Affinity       88 /* synopsis: affinity(r[P1@P2])               */</div><div>+#define OP_MakeRecord     89 /* synopsis: r[P3]=mkrec(r[P1@P2])            */</div><div>+#define OP_Count          90 /* synopsis: r[P2]=count()                    */</div><div>+#define OP_FkCheckCommit  91</div><div>+#define OP_TTransaction   92</div><div>+#define OP_ReadCookie     93</div><div>+#define OP_SetCookie      94</div><div>+#define OP_ReopenIdx      95 /* synopsis: root=P2                          */</div><div>+#define OP_OpenRead       96 /* synopsis: root=P2                          */</div><div>+#define OP_OpenWrite      97 /* synopsis: root=P2                          */</div><div>+#define OP_OpenTEphemeral  98 /* synopsis: nColumn = P2                     */</div><div>+#define OP_SorterOpen     99</div><div>+#define OP_SequenceTest  100 /* synopsis: if (cursor[P1].ctr++) pc = P2    */</div><div>+#define OP_OpenPseudo    101 /* synopsis: P3 columns in r[P2]              */</div><div>+#define OP_Close         102</div><div>+#define OP_ColumnsUsed   103</div><div>+#define OP_Sequence      104 /* synopsis: r[P2]=cursor[P1].ctr++           */</div><div>+#define OP_NextId        105 /* synopsis: r[P3]=get_max(space_index[P1]{Column[P2]}) */</div><div>+#define OP_NextIdEphemeral 106 /* synopsis: r[P3]=get_max(space_index[P1]{Column[P2]}) */</div><div>+#define OP_FCopy         107 /* synopsis: reg[P2@cur_frame]= reg[P1@root_frame(OPFLAG_SAME_FRAME)] */</div><div>+#define OP_Delete        108</div><div>+#define OP_ResetCount    109</div><div>+#define OP_SorterCompare 110 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */</div><div>+#define OP_SorterData    111 /* synopsis: r[P2]=data                       */</div><div>+#define OP_RowData       112 /* synopsis: r[P2]=data                       */</div><div>+#define OP_NullRow       113</div><div>+#define OP_SorterInsert  114 /* synopsis: key=r[P2]                        */</div><div> #define OP_Real          115 /* same as TK_FLOAT, synopsis: r[P2]=P4       */</div><div>-#define OP_IdxInsert     116 /* synopsis: key=r[P2]                        */</div><div>-#define OP_IdxDelete     117 /* synopsis: key=r[P2@P3]                     */</div><div>-#define OP_Clear         118 /* synopsis: space id = P1                    */</div><div>-#define OP_ResetSorter   119</div><div>-#define OP_ParseSchema2  120 /* synopsis: rows=r[P1@P2]                    */</div><div>-#define OP_ParseSchema3  121 /* synopsis: name=r[P1] sql=r[P1+1]           */</div><div>-#define OP_RenameTable   122 /* synopsis: P1 = root, P4 = name             */</div><div>-#define OP_LoadAnalysis  123</div><div>-#define OP_DropTable     124</div><div>-#define OP_DropIndex     125</div><div>-#define OP_DropTrigger   126</div><div>-#define OP_Param         127</div><div>-#define OP_FkCounter     128 /* synopsis: fkctr[P1]+=P2                    */</div><div>-#define OP_OffsetLimit   129 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */</div><div>-#define OP_AggStep0      130 /* synopsis: accum=r[P3] step(r[P2@P5])       */</div><div>-#define OP_AggStep       131 /* synopsis: accum=r[P3] step(r[P2@P5])       */</div><div>-#define OP_AggFinal      132 /* synopsis: accum=r[P1] N=P2                 */</div><div>-#define OP_Expire        133</div><div>-#define OP_IncMaxid      134</div><div>-#define OP_Noop          135</div><div>-#define OP_Explain       136</div><div>+#define OP_IdxReplace    116 /* synopsis: key=r[P2]                        */</div><div>+#define OP_IdxInsert     117 /* synopsis: key=r[P2]                        */</div><div>+#define OP_IdxDelete     118 /* synopsis: key=r[P2@P3]                     */</div><div>+#define OP_Clear         119 /* synopsis: space id = P1                    */</div><div>+#define OP_ResetSorter   120</div><div>+#define OP_ParseSchema2  121 /* synopsis: rows=r[P1@P2]                    */</div><div>+#define OP_ParseSchema3  122 /* synopsis: name=r[P1] sql=r[P1+1]           */</div><div>+#define OP_RenameTable   123 /* synopsis: P1 = root, P4 = name             */</div><div>+#define OP_LoadAnalysis  124</div><div>+#define OP_DropTable     125</div><div>+#define OP_DropIndex     126</div><div>+#define OP_DropTrigger   127</div><div>+#define OP_Param         128</div><div>+#define OP_FkCounter     129 /* synopsis: fkctr[P1]+=P2                    */</div><div>+#define OP_OffsetLimit   130 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */</div><div>+#define OP_AggStep0      131 /* synopsis: accum=r[P3] step(r[P2@P5])       */</div><div>+#define OP_AggStep       132 /* synopsis: accum=r[P3] step(r[P2@P5])       */</div><div>+#define OP_AggFinal      133 /* synopsis: accum=r[P1] N=P2                 */</div><div>+#define OP_Expire        134</div><div>+#define OP_IncMaxid      135</div><div>+#define OP_Noop          136</div><div>+#define OP_Explain       137</div><div> </div><div> /* Properties such as "out2" or "jump" that are specified in</div><div> ** comments following the "case" for each opcode in the vdbe.c</div><div>@@ -157,16 +158,16 @@</div><div> /*  40 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01, 0x01,\</div><div> /*  48 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\</div><div> /*  56 */ 0x03, 0x03, 0x03, 0x01, 0x02, 0x02, 0x08, 0x00,\</div><div>-/*  64 */ 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10,\</div><div>-/*  72 */ 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,\</div><div>-/*  80 */ 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\</div><div>-/*  88 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\</div><div>-/*  96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\</div><div>-/* 104 */ 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\</div><div>-/* 112 */ 0x00, 0x04, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,\</div><div>-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\</div><div>-/* 128 */ 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\</div><div>-/* 136 */ 0x00,}</div><div>+/*  64 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10,\</div><div>+/*  72 */ 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\</div><div>+/*  80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,\</div><div>+/*  88 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,\</div><div>+/*  96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\</div><div>+/* 104 */ 0x10, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\</div><div>+/* 112 */ 0x00, 0x00, 0x04, 0x10, 0x00, 0x04, 0x00, 0x00,\</div><div>+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\</div><div>+/* 128 */ 0x10, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\</div><div>+/* 136 */ 0x00, 0x00,}</div><div> </div><div> /* The sqlite3P2Values() routine is able to run faster if it knows</div><div> ** the value of the largest JUMP opcode.  The smaller the maximum</div><div>diff --git a/src/box/sql/select.c b/src/box/sql/select.c</div><div>index 2a8c83d06..39c1be53d 100644</div><div>--- a/src/box/sql/select.c</div><div>+++ b/src/box/sql/select.c</div><div>@@ -35,7 +35,9 @@</div><div>  */</div><div> #include <box/coll.h></div><div> #include "sqliteInt.h"</div><div>+#include "tarantoolInt.h"</div><div> #include "box/session.h"</div><div>+#include "box/schema.h"</div><div> </div><div> /*</div><div>  * Trace output macros</div><div>@@ -6187,8 +6189,15 @@ sqlite3Select(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">             </span>/* The parser context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                               </span>}</div><div> </div><div> <span class="Apple-tab-span" style="white-space:pre">                         </span>/* Open a read-only cursor, execute the OP_Count, close the cursor. */</div><div>+<span class="Apple-tab-span" style="white-space:pre">                              </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                       </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(iRoot));</div><div>+<span class="Apple-tab-span" style="white-space:pre">                               </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                              </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">                              </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                              </span>     space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                            </span>     (void *) space);</div><div> <span class="Apple-tab-span" style="white-space:pre">                                </span>sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr,</div><div>-<span class="Apple-tab-span" style="white-space:pre">                                          </span>     iRoot, 0, 1);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                                </span>     iRoot, space_ptr_reg, 1);</div><div> <span class="Apple-tab-span" style="white-space:pre">                               </span>if (pKeyInfo) {</div><div> <span class="Apple-tab-span" style="white-space:pre">                                        </span>sqlite3VdbeChangeP4(v, -1,</div><div> <span class="Apple-tab-span" style="white-space:pre">                                                     </span>    (char *)pKeyInfo,</div><div>diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c</div><div>index 9929dfb96..a44a17062 100644</div><div>--- a/src/box/sql/vdbe.c</div><div>+++ b/src/box/sql/vdbe.c</div><div>@@ -1072,6 +1072,19 @@ case OP_Int64: {           /* out2 */</div><div> <span class="Apple-tab-span" style="white-space:pre">   </span>break;</div><div> }</div><div> </div><div>+/* Opcode: LoadPtr * P2 * P4 *</div><div>+ * Synopsis: r[P2] = P4</div><div>+ *</div><div>+ * P4 is a generic pointer. Copy it into register P2.</div><div>+ */</div><div>+case OP_LoadPtr: {</div><div>+<span class="Apple-tab-span" style="white-space:pre">  </span>pOut = out2Prerelease(p, pOp);</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>assert(pOp->p4type == P4_PTR);</div><div>+<span class="Apple-tab-span" style="white-space:pre">   </span>pOut->u.p = pOp->p4.p;</div><div>+<span class="Apple-tab-span" style="white-space:pre">        </span>pOut->flags = MEM_Ptr;</div><div>+<span class="Apple-tab-span" style="white-space:pre">   </span>break;</div><div>+}</div><div>+</div><div> #ifndef SQLITE_OMIT_FLOATING_POINT</div><div> /* Opcode: Real * P2 * P4 *</div><div>  * Synopsis: r[P2]=P4</div><div>diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h</div><div>index 7241963e4..340ddc766 100644</div><div>--- a/src/box/sql/vdbe.h</div><div>+++ b/src/box/sql/vdbe.h</div><div>@@ -144,6 +144,7 @@ typedef struct VdbeOpList VdbeOpList;</div><div> #define P4_INDEX    (-15)<span class="Apple-tab-span" style="white-space:pre">   </span>/* P4 is a pointer to a Index structure */</div><div> #define P4_FUNCCTX  (-16)<span class="Apple-tab-span" style="white-space:pre">       </span>/* P4 is a pointer to an sqlite3_context object */</div><div> #define P4_BOOL     (-17)<span class="Apple-tab-span" style="white-space:pre">  </span>/* P4 is a bool value */</div><div>+#define P4_PTR      (-18)<span class="Apple-tab-span" style="white-space:pre">    </span>/* P4 is a generic pointer */</div><div> </div><div> </div><div> /* Error message codes for OP_Halt */</div><div>@@ -200,6 +201,7 @@ int sqlite3VdbeAddOp3(Vdbe *, int, int, int, int);</div><div> int sqlite3VdbeAddOp4(Vdbe *, int, int, int, int, const char *zP4, int);</div><div> int sqlite3VdbeAddOp4Dup8(Vdbe *, int, int, int, int, const u8 *, int);</div><div> int sqlite3VdbeAddOp4Int(Vdbe *, int, int, int, int, int);</div><div>+int sqlite3VdbeAddOp4Ptr(Vdbe *, int, int, int, int, void *);</div><div> void sqlite3VdbeEndCoroutine(Vdbe *, int);</div><div> #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)</div><div> void sqlite3VdbeVerifyNoMallocRequired(Vdbe * p, int N);</div><div>diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h</div><div>index 8b622de5b..fcb45c8a8 100644</div><div>--- a/src/box/sql/vdbeInt.h</div><div>+++ b/src/box/sql/vdbeInt.h</div><div>@@ -196,6 +196,7 @@ struct Mem {</div><div> <span class="Apple-tab-span" style="white-space:pre">              </span>i64 i;<span class="Apple-tab-span" style="white-space:pre">              </span>/* Integer value used when MEM_Int is set in flags */</div><div> <span class="Apple-tab-span" style="white-space:pre">          </span>bool b;         /* Boolean value used when MEM_Bool is set in flags */</div><div> <span class="Apple-tab-span" style="white-space:pre">             </span>int nZero;<span class="Apple-tab-span" style="white-space:pre">  </span>/* Used when bit MEM_Zero is set in flags */</div><div>+<span class="Apple-tab-span" style="white-space:pre">                </span>void *p;<span class="Apple-tab-span" style="white-space:pre">    </span>/* Generic pointer */</div><div> <span class="Apple-tab-span" style="white-space:pre">          </span>FuncDef *pDef;<span class="Apple-tab-span" style="white-space:pre">      </span>/* Used only when flags==MEM_Agg */</div><div> <span class="Apple-tab-span" style="white-space:pre">            </span>VdbeFrame *pFrame;<span class="Apple-tab-span" style="white-space:pre">  </span>/* Used when flags==MEM_Frame */</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>} u;</div><div>@@ -239,6 +240,7 @@ struct Mem {</div><div> #define MEM_Real      0x0008<span class="Apple-tab-span" style="white-space:pre"> </span>/* Value is a real number */</div><div> #define MEM_Blob      0x0010<span class="Apple-tab-span" style="white-space:pre">        </span>/* Value is a BLOB */</div><div> #define MEM_Bool      0x0020    /* Value is a bool */</div><div>+#define MEM_Ptr       0x0040<span class="Apple-tab-span" style="white-space:pre"> </span>/* Value is a generic pointer */</div><div> #define MEM_AffMask   0x003f<span class="Apple-tab-span" style="white-space:pre">      </span>/* Mask of affinity bits */</div><div> #define MEM_Frame     0x0080<span class="Apple-tab-span" style="white-space:pre">      </span>/* Value is a VdbeFrame object */</div><div> #define MEM_Undefined 0x0100<span class="Apple-tab-span" style="white-space:pre">  </span>/* Value is undefined */</div><div>@@ -378,6 +380,7 @@ struct Vdbe {</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>i64 nFkConstraint;<span class="Apple-tab-span" style="white-space:pre">  </span>/* Number of imm. FK constraints this VM */</div><div> <span class="Apple-tab-span" style="white-space:pre">    </span>i64 nStmtDefCons;<span class="Apple-tab-span" style="white-space:pre">   </span>/* Number of def. constraints when stmt started */</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span>i64 nStmtDefImmCons;<span class="Apple-tab-span" style="white-space:pre">        </span>/* Number of def. imm constraints when stmt started */</div><div>+<span class="Apple-tab-span" style="white-space:pre">      </span>uint32_t schema_ver;<span class="Apple-tab-span" style="white-space:pre">        </span>/* Schema version at the moment of VDBE creation. */</div><div> </div><div> <span class="Apple-tab-span" style="white-space:pre">      </span>/*</div><div> <span class="Apple-tab-span" style="white-space:pre">     </span> * In recursive triggers we can execute INSERT/UPDATE OR IGNORE</div><div>diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c</div><div>index 92bf9943b..37a3c90d2 100644</div><div>--- a/src/box/sql/vdbeaux.c</div><div>+++ b/src/box/sql/vdbeaux.c</div><div>@@ -66,6 +66,7 @@ sqlite3VdbeCreate(Parse * pParse)</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>p->magic = VDBE_MAGIC_INIT;</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>p->pParse = pParse;</div><div> <span class="Apple-tab-span" style="white-space:pre"> </span>p->autoCommit = (char)box_txn() == 0 ? 1 : 0;</div><div>+<span class="Apple-tab-span" style="white-space:pre">    </span>p->schema_ver = box_schema_version();</div><div> <span class="Apple-tab-span" style="white-space:pre">       </span>if (!p->autoCommit) {</div><div> <span class="Apple-tab-span" style="white-space:pre">               </span>p->psql_txn = in_txn()->psql_txn;</div><div> <span class="Apple-tab-span" style="white-space:pre">                </span>p->nDeferredCons = p->psql_txn->nDeferredConsSave;</div><div>@@ -413,6 +414,16 @@ sqlite3VdbeAddOp4Int(Vdbe * p,<span class="Apple-tab-span" style="white-space:pre">       </span>/* Add the opcode to this VM */</div><div> <span class="Apple-tab-span" style="white-space:pre">        </span>return addr;</div><div> }</div><div> </div><div>+int</div><div>+sqlite3VdbeAddOp4Ptr(Vdbe *p, int op, int p1, int p2, int p3, void *ptr)</div><div>+{</div><div>+<span class="Apple-tab-span" style="white-space:pre"> </span>int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);</div><div>+<span class="Apple-tab-span" style="white-space:pre">    </span>VdbeOp *pOp = &p->aOp[addr];</div><div>+<span class="Apple-tab-span" style="white-space:pre"> </span>pOp->p4type = P4_PTR;</div><div>+<span class="Apple-tab-span" style="white-space:pre">    </span>pOp->p4.p = ptr;</div><div>+<span class="Apple-tab-span" style="white-space:pre"> </span>return addr;</div><div>+}</div><div>+</div><div> /* Insert the end of a co-routine</div><div>  */</div><div> void</div><div>diff --git a/src/box/sql/where.c b/src/box/sql/where.c</div><div>index 2f1c627e5..47da3c84c 100644</div><div>--- a/src/box/sql/where.c</div><div>+++ b/src/box/sql/where.c</div><div>@@ -42,6 +42,8 @@</div><div> #include "vdbeInt.h"</div><div> #include "whereInt.h"</div><div> #include "box/session.h"</div><div>+#include "box/schema.h"</div><div>+#include "tarantoolInt.h"</div><div> </div><div> /* Forward declaration of methods */</div><div> static int whereLoopResize(sqlite3 *, WhereLoop *, int);</div><div>@@ -4606,7 +4608,15 @@ sqlite3WhereBegin(Parse * pParse,<span class="Apple-tab-span" style="white-space:pre">       </span>/* The parser context */</div><div> <span class="Apple-tab-span" style="white-space:pre">                       </span>assert(pIx->pSchema == pTab->pSchema);</div><div> <span class="Apple-tab-span" style="white-space:pre">                   </span>assert(iIndexCur >= 0);</div><div> <span class="Apple-tab-span" style="white-space:pre">                     </span>if (op) {</div><div>-<span class="Apple-tab-span" style="white-space:pre">                           </span>sqlite3VdbeAddOp2(v, op, iIndexCur, pIx->tnum);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                          </span>struct space *space =</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                       </span>space_by_id(SQLITE_PAGENO_TO_SPACEID(pIx->tnum));</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                </span>assert(space != NULL);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                              </span>int space_ptr_reg = ++pParse->nMem;</div><div>+<span class="Apple-tab-span" style="white-space:pre">                              </span>sqlite3VdbeAddOp4Ptr(v, OP_LoadPtr, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                              </span>     space_ptr_reg, 0,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                            </span>     (void *) space);</div><div>+<span class="Apple-tab-span" style="white-space:pre">                             </span>sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum,</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                           </span>  space_ptr_reg);</div><div> <span class="Apple-tab-span" style="white-space:pre">                         </span>sqlite3VdbeSetP4KeyInfo(pParse, pIx);</div><div> <span class="Apple-tab-span" style="white-space:pre">                          </span>if ((pLoop->wsFlags & WHERE_CONSTRAINT) != 0</div><div> <span class="Apple-tab-span" style="white-space:pre">                            </span>    && (pLoop-></div></div><br class=""></div><br class=""></body></html>