<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>