<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">вс, 29 июл. 2018 г. в 4:12, Alexander Turenko <<a href="mailto:alexander.turenko@tarantool.org" target="_blank">alexander.turenko@tarantool.org</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi!<br>
<br>
Please consider my comments and questions below.<br>
<br>
WBR, Alexander Turenko.<br>
<br>
> +       /*<br>
> +        * Xfer optimization is unable to correctly insert data<br>
> +        * in case there's a conflict action other than<br>
> +        * explicit *_ABORT. This is the reason we want to only<br>
> +        * run it if the destination table is initially empty.<br>
> +        * That block generates code to make that determination.<br>
> +        */<br>
> +       if (!(onError == ON_CONFLICT_ACTION_ABORT &&<br>
> +           !is_err_action_default)) {<br>
<br>
Do you mean that:<br>
<br>
1. The optimization non-empty table case correctly works only with ABORT<br>
   conflict action (default or explicit).<br>
2. The default conflict action can be overwritten on per-column basis, so<br>
   'default abort' can really be replace or other conflict action.<br>
<br>
If so, your description doesn't give this information.<br>
<br>
To more on that, can we check per-column conflict actions instead of check<br>
whether the conflict action default or explicit? This would enable more cases<br>
with non-empty tables for the optimization. And this would look less confusing,<br>
IMHO.<br></blockquote><div><br></div><div>Well, basically, you're right. But the thing is that we're going to remove</div><div>column conflict actions, thus, I suppose, it doesn't make sense.</div><div>Nikita, Correct me if I'm wrong please.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
I have one more question on that. It seems that SQLite has this optimization<br>
working with ROLLBACK conflict action. We cannot doing so, because of some<br>
problem? Did this problem described / trackerized somewhere? Or something<br>
changes underhood and makes this impossible? Are we know exact reason or just<br>
observing it does not work?<br></blockquote><div><br></div><div>I investigated that a little. OP_IdxInsert was changed so that we can process</div><div>ABORT, FAIL or IGNORE. I took it into account in newer version hence </div><div>it is<span style="font-size:small;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span> </span>also</span> used in these cases even when the destination table is not empty.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +#ifdef SQLITE_TEST<br>
> +/*<br>
> + * The following global variable is incremented whenever the<br>
> + * transfer optimization is used.  This is used for testing<br>
> + * purposes only - to make sure the transfer optimization really<br>
> + * is happening when it is supposed to.<br>
> + */<br>
> +int sql_xfer_count = 0;<br>
> +#endif<br>
<br>
I think it would be good to mention the opcode where the counter is<br>
incremented. You can follow the style in which other counters are<br>
described (they are mostly mention opcodes).<br></blockquote><div><br></div><div>Added.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> -/* Opcode: RowData P1 P2 * * *<br>
> +/* Opcode: RowData P1 P2 * * P5<br>
<br>
We can increase the counter on per-operation basis instead of per-row by<br>
adding the flag to OP_OpenWrite. It will save some CPU cycles :)</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +#ifdef SQLITE_TEST<br>
> +       if ((pOp->p5 & OPFLAG_XFER_OPT) != 0) {<br>
> +               pOp->p5 = 0;<br>
> +               sql_xfer_count++;<br>
> +       }<br>
> +#endif<br>
<br>
1. Not actual due to 2, but it would be better to use<br>
   `pOp->p5 &= ~OPFLAG_XFER_OPT` to drop just that flag.<br>
2. It is counter-intuitive, IMHO, to change operation flags during that<br>
   operation. So, said above, vote to move it to OP_OpenWrite.<br>
<br></blockquote><div><br></div><div>Made the first.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +local bfr, aftr<br>
> +<br>
<br>
What do you plan to do with saved letters? :) Really, such abbreviations<br>
just makes reading harder with no gains.<br></blockquote><div><br></div><div>I made dis :(</div><div>(p.s. Changed it)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +local function do_xfer_test(test_number, return_code)<br>
> +       test_name = string.format("xfer-optimization-1.%d", test_number)<br>
> +       test:do_test(<br>
> +               test_name,<br>
> +               function()<br>
> +                       return {aftr - bfr}<br>
> +               end, {<br>
> +                       -- <test_name><br>
> +                       return_code<br>
> +                       -- <test_name><br>
> +               })<br>
> +end<br>
<br>
That code can be written simpler (consider tap module documentation):<br>
<br>
test:is(after - before, exp, test_name)<br>
<br>
I suggest to create wrappers like so (I didn't test it):<br>
<br>
local function do_xfer_test(test_func, test, test_name, func, exp, opts)<br>
    local opts = opts or {}<br>
    local exp_xfer_count = opts.exp_xfer_count<br>
    local before = box.sql.debug().sql_xfer_count<br>
    local ok = test_func(test, test_name, func, exp)<br>
    local after = box.sql.debug().sql_xfer_count<br>
    if exp_xfer_count ~= nil then<br>
        ok = ok and test:is(after - before, exp_xfer_count, test_name ..<br>
            '_xfer_count')<br>
    end<br>
    return ok<br>
end<br>
<br>
test.do_execsql_xfer_test = function(test, test_name, func, exp, opts)<br>
    return do_xfer_test(test.do_execsql_test, test, test_name, func, exp, opts)<br>
end<br>
<br>
test.do_catchsql_xfer_test = function(test, test_name, func, exp, opts)<br>
    return do_xfer_test(test.do_catchsql_test, test, test_name, func, exp, opts)<br>
end<br>
<br>
And use it like so:<br>
<br>
test:do_catchsql_xfer_test(<br>
    "xfer-optimization-1.1",<br>
    [[<br>
        CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER UNIQUE);<br>
        INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);<br>
        CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER UNIQUE);<br>
        INSERT INTO t2 SELECT * FROM t1;<br>
    ]], {<br>
        -- <xfer-optimization-1.1><br>
        0<br>
        -- <xfer-optimization-1.1><br>
    }), {<br>
        exp_xfer_count = 1<br>
    }<br>
)<br>
<br></blockquote><div><br></div><div>Thank you for suggestion. Added that implementation.</div><div>(Needed to change it a little bit)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
By the way, you can revive xfer cases in test/sql-tap/with2.test.lua. Or drop<br>
it if your new test includes all related cases from with2.<br>
<br></blockquote><div><br></div><div>They're alive now!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
On Fri, Jul 20, 2018 at 07:58:48PM +0300, Nikita Tatunov wrote:<br>
>    Ooops. Thank you! fixed it and pushed.<br>
> <br>
>    пт, 20 июл. 2018 г. в 19:43, n.pettik <[1]<a href="mailto:korablev@tarantool.org" target="_blank">korablev@tarantool.org</a>>:<br>
> <br>
>    LGTM.<br>
> <br>
>    diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c<br>
>    index 3c3bf37..4f52fa5 100644<br>
>    --- a/src/box/sql/insert.c<br>
>    +++ b/src/box/sql/insert.c<br>
>    @@ -1869,7 +1869,7 @@ xferOptimization(Parse * pParse, /* Parser<br>
>    context */<br>
>       * table (tab1) is initially empty.<br>
>       */<br>
> <br>
>    - /* The Vdbe we're building*/<br>
>    + /* The Vdbe struct we're building. */<br>
> <br>
>    You misunderstood me. What I mean is:<br>
>    struct Vibe *v = …;<br>
> <br>
>      Vdbe *v = sqlite3GetVdbe(pParse);<br>
> <br>
> References<br>
> <br>
>    1. mailto:<a href="mailto:korablev@tarantool.org" target="_blank">korablev@tarantool.org</a></blockquote><div><br></div><div>Diff:</div><div><br></div><div> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c</div><div>index 3c45920..c3cf94a 100644</div><div>--- a/src/box/sql/insert.c</div><div>+++ b/src/box/sql/insert.c</div><div>@@ -1715,7 +1715,6 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">   </span>/* Parser context */</div><div> <span style="white-space:pre">        </span>int iSrc, iDest;<span style="white-space:pre">     </span>/* Cursors from source and destination */</div><div> <span style="white-space:pre">   </span>int addr1;<span style="white-space:pre">           </span>/* Loop addresses */</div><div> <span style="white-space:pre">        </span>int emptyDestTest = 0;<span style="white-space:pre">       </span>/* Address of test for empty pDest */</div><div>-<span style="white-space:pre">        </span>int emptySrcTest = 0;<span style="white-space:pre">        </span>/* Address of test for empty pSrc */</div><div> <span style="white-space:pre">        </span>int regData, regTupleid;<span style="white-space:pre">     </span>/* Registers holding data and tupleid */</div><div> <span style="white-space:pre">    </span>struct session *user_session = current_session();</div><div> <span style="white-space:pre">   </span>bool is_err_action_default = false;</div><div>@@ -1881,13 +1880,15 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">   </span>/* Parser context */</div><div> </div><div> <span style="white-space:pre">       </span>/*</div><div> <span style="white-space:pre">  </span> * Xfer optimization is unable to correctly insert data</div><div>-<span style="white-space:pre">      </span> * in case there's a conflict action other than</div><div>-<span style="white-space:pre">  </span> * explicit *_ABORT. This is the reason we want to only</div><div>+<span style="white-space:pre">      </span> * in case there's a conflict action other than *_ABORT,</div><div>+<span style="white-space:pre"> </span> * *_FAIL or *_IGNORE. This is the reason we want to only</div><div> <span style="white-space:pre">   </span> * run it if the destination table is initially empty.</div><div> <span style="white-space:pre">      </span> * That block generates code to make that determination.</div><div> <span style="white-space:pre">    </span> */</div><div>-<span style="white-space:pre">  </span>if (!(onError == ON_CONFLICT_ACTION_ABORT &&</div><div>-<span style="white-space:pre"> </span>    !is_err_action_default)) {</div><div>+<span style="white-space:pre">     </span>if (!(onError == ON_CONFLICT_ACTION_ABORT ||</div><div>+<span style="white-space:pre"> </span>    onError == ON_CONFLICT_ACTION_FAIL ||</div><div>+<span style="white-space:pre">  </span>    onError == ON_CONFLICT_ACTION_IGNORE) ||</div><div>+<span style="white-space:pre">       </span>    is_err_action_default) {</div><div> <span style="white-space:pre">              </span>addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);</div><div> <span style="white-space:pre">          </span>VdbeCoverage(v);</div><div> <span style="white-space:pre">            </span>emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto);</div><div>@@ -1905,15 +1906,23 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">        </span>/* Parser context */</div><div> #endif</div><div> </div><div> <span style="white-space:pre">        </span>sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);</div><div>-<span style="white-space:pre">  </span>sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);</div><div>+<span style="white-space:pre">      </span>switch (onError) {</div><div>+<span style="white-space:pre">   </span>case ON_CONFLICT_ACTION_IGNORE:</div><div>+<span style="white-space:pre">              </span>sqlite3VdbeChangeP5(v, OPFLAG_OE_IGNORE);</div><div>+<span style="white-space:pre">            </span>break;</div><div>+<span style="white-space:pre">       </span>case ON_CONFLICT_ACTION_FAIL:</div><div>+<span style="white-space:pre">                </span>sqlite3VdbeChangeP5(v, OPFLAG_OE_FAIL);</div><div>+<span style="white-space:pre">              </span>break;</div><div>+<span style="white-space:pre">       </span>default:</div><div>+<span style="white-space:pre">             </span>sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);</div><div>+<span style="white-space:pre">              </span>break;</div><div>+<span style="white-space:pre">       </span>}</div><div> <span style="white-space:pre">   </span>sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1 + 1);</div><div> <span style="white-space:pre">     </span>VdbeCoverage(v);</div><div> <span style="white-space:pre">    </span>sqlite3VdbeJumpHere(v, addr1);</div><div> <span style="white-space:pre">      </span>sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);</div><div> <span style="white-space:pre">    </span>sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);</div><div> </div><div>-<span style="white-space:pre">   </span>if (emptySrcTest)</div><div>-<span style="white-space:pre">            </span>sqlite3VdbeJumpHere(v, emptySrcTest);</div><div> <span style="white-space:pre">       </span>sqlite3ReleaseTempReg(pParse, regTupleid);</div><div> <span style="white-space:pre">  </span>sqlite3ReleaseTempReg(pParse, regData);</div><div> <span style="white-space:pre">     </span>if (emptyDestTest) {</div><div>diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c</div><div>index aa7f250..ce01039 100644</div><div>--- a/src/box/sql/vdbe.c</div><div>+++ b/src/box/sql/vdbe.c</div><div>@@ -79,10 +79,10 @@ int sql_search_count = 0;</div><div> </div><div> #ifdef SQLITE_TEST</div><div> /*</div><div>- * The following global variable is incremented whenever the</div><div>- * transfer optimization is used.  This is used for testing</div><div>- * purposes only - to make sure the transfer optimization really</div><div>- * is happening when it is supposed to.</div><div>+ * The following global variable is incremented in OP_RowData</div><div>+ * whenever the xfer optimization is used. This is used on</div><div>+ * testing purposes only - to make sure the transfer optimization</div><div>+ * really is happening when it is supposed to.</div><div>  */</div><div> int sql_xfer_count = 0;</div><div> #endif</div><div>@@ -4008,9 +4008,13 @@ case OP_RowData: {</div><div> <span style="white-space:pre">        </span>BtCursor *pCrsr;</div><div> <span style="white-space:pre">    </span>u32 n;</div><div> </div><div>+/*</div><div>+ * Flag P5 is cleared after the first insertion using xfer</div><div>+ * optimization.</div><div>+ */</div><div> #ifdef SQLITE_TEST</div><div> <span style="white-space:pre">   </span>if ((pOp->p5 & OPFLAG_XFER_OPT) != 0) {</div><div>-<span style="white-space:pre">               </span>pOp->p5 = 0;</div><div>+<span style="white-space:pre">              </span>pOp->p5 &= ~OPFLAG_XFER_OPT;</div><div> <span style="white-space:pre">         </span>sql_xfer_count++;</div><div> <span style="white-space:pre">   </span>}</div><div> #endif</div><div>diff --git a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua</div><div>index 05d30c6..b99de2b 100755</div><div>--- a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua</div><div>+++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua</div><div>@@ -2,24 +2,28 @@</div><div> test = require("sqltester")</div><div> test:plan(46)</div><div> </div><div>-local bfr, aftr</div><div>-</div><div>-local function do_xfer_test(test_number, return_code)</div><div>-<span style="white-space:pre">   </span>test_name = string.format("xfer-optimization-1.%d", test_number)</div><div>-<span style="white-space:pre">   </span>test:do_test(</div><div>-<span style="white-space:pre">                </span>test_name,</div><div>-<span style="white-space:pre">           </span>function()</div><div>-<span style="white-space:pre">                   </span>return {aftr - bfr}</div><div>-<span style="white-space:pre">          </span>end, {</div><div>-<span style="white-space:pre">                       </span>-- <test_name></div><div>-<span style="white-space:pre">                 </span>return_code</div><div>-<span style="white-space:pre">                  </span>-- <test_name></div><div>-<span style="white-space:pre">         </span>})</div><div>+local function do_xfer_test(test, test_func, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">   </span>local opts = opts or {}</div><div>+<span style="white-space:pre">      </span>local exp_xfer_count = opts.exp_xfer_count</div><div>+<span style="white-space:pre">   </span>local before = box.sql.debug().sql_xfer_count</div><div>+<span style="white-space:pre">        </span>local ok, result = pcall(test_func, test, test_name, func, exp)</div><div>+<span style="white-space:pre">      </span>local after = box.sql.debug().sql_xfer_count</div><div>+<span style="white-space:pre"> </span>if exp_xfer_count ~= nil then</div><div>+<span style="white-space:pre">                </span>ok = ok and test:is(after - before, exp_xfer_count,</div><div>+<span style="white-space:pre">          </span>                    test_name .. '-xfer-count')</div><div>+<span style="white-space:pre">    </span>end</div><div>+<span style="white-space:pre">  </span>return ok</div><div> end</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>+test.do_execsql_xfer_test = function(test, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">     </span>return do_xfer_test(test, test.do_execsql_test, test_name, func, exp, opts)</div><div>+end</div><div>+</div><div>+test.do_catchsql_xfer_test = function(test, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">        </span>return do_xfer_test(test, test.do_catchsql_test, test_name, func, exp, opts)</div><div>+end</div><div> </div><div>-test:do_catchsql_test(</div><div>+test:do_catchsql_xfer_test(</div><div> <span style="white-space:pre">   </span>"xfer-optimization-1.1",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER UNIQUE);</div><div>@@ -30,10 +34,10 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">          </span>-- <xfer-optimization-1.1></div><div> <span style="white-space:pre">            </span>0</div><div> <span style="white-space:pre">           </span>-- <xfer-optimization-1.1></div><div>+<span style="white-space:pre">     </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div> <span style="white-space:pre">      </span>"xfer-optimization-1.2",</div><div> <span style="white-space:pre">  </span>[[</div><div>@@ -44,12 +48,8 @@ test:do_execsql_test(</div><div> <span style="white-space:pre">           </span>-- <xfer-optimization-1.2></div><div> <span style="white-space:pre">    </span>})</div><div> </div><div>-do_xfer_test(3, 1)</div><div>-</div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.4",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">        </span>"xfer-optimization-1.3",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -60,15 +60,15 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">             </span>INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);</div><div> <span style="white-space:pre">               </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.4></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.3></div><div> <span style="white-space:pre">            </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.4></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.3></div><div>+<span style="white-space:pre">     </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.5",</div><div>+<span style="white-space:pre">   </span>"xfer-optimization-1.4",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>@@ -77,12 +77,8 @@ test:do_execsql_test(</div><div> <span style="white-space:pre">                </span>-- <xfer-optimization-1.5></div><div> <span style="white-space:pre">    </span>})</div><div> </div><div>-do_xfer_test(6, 1)</div><div>-</div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.7",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">        </span>"xfer-optimization-1.5",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -91,29 +87,25 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">             </span>CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);</div><div> <span style="white-space:pre">          </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.7></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.5></div><div> <span style="white-space:pre">            </span>1, "table T2 has 2 columns but 3 values were supplied"</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.7></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.5></div><div>+<span style="white-space:pre">     </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.8",</div><div>+<span style="white-space:pre">   </span>"xfer-optimization-1.6",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.8></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.6></div><div> </div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.8></div><div>+<span style="white-space:pre">             </span>-- <xfer-optimization-1.6></div><div> <span style="white-space:pre">    </span>})</div><div> </div><div>-do_xfer_test(9, 0)</div><div>-</div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.10",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.7",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -122,29 +114,25 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">           </span>CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER);</div><div> <span style="white-space:pre">          </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.10></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.7></div><div> <span style="white-space:pre">            </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.10></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.7></div><div>+<span style="white-space:pre">     </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.11",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.8",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.11></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.8></div><div> <span style="white-space:pre">            </span>1, 1, 2, 2, 3, 3</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.11></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.8></div><div> <span style="white-space:pre">    </span>})</div><div> </div><div>-do_xfer_test(12, 1);</div><div>-</div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.13",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.9",</div><div> <span style="white-space:pre">  </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -153,29 +141,25 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">           </span>CREATE TABLE t2(b INTEGER, a INTEGER PRIMARY KEY);</div><div> <span style="white-space:pre">          </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.13></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.9></div><div> <span style="white-space:pre">            </span>1, "Duplicate key exists in unique index 'sqlite_autoindex_T2_1' in space 'T2'"</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.13></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.9></div><div>+<span style="white-space:pre">     </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.14",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.10",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.14></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.10></div><div> </div><div>-<span style="white-space:pre">           </span>-- <xfer-optimization-1.14></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.10></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-do_xfer_test(15, 0)</div><div>-</div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">     </span>"xfer-optimization-1.16",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.11",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -184,25 +168,23 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">           </span>CREATE TABLE t2(b INTEGER PRIMARY KEY, a INTEGER);</div><div> <span style="white-space:pre">          </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.16></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.11></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.16></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.11></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.17",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.12",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.17></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.12></div><div> <span style="white-space:pre">           </span>1, 1, 2, 2, 3, 2</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.17></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.12></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-do_xfer_test(18, 1)</div><div>-</div><div> -- The following tests are supposed to test if xfer-optimization is actually</div><div> -- used in the given cases (if the conflict actually occurs):</div><div> -- <span style="white-space:pre">        </span>1.0) insert w/o explicit confl. action & w/o index replace action</div><div>@@ -221,10 +203,8 @@ do_xfer_test(18, 1)</div><div> -- 1.0) insert w/o explicit confl. action & w/o index replace action</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.19",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.13",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -236,35 +216,31 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.19></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.13></div><div> <span style="white-space:pre">           </span>1, "Duplicate key exists in unique index 'sqlite_autoindex_T2_1' in space 'T2'"</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.19></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.13></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.20",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.14",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.20></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.14></div><div> <span style="white-space:pre">           </span>2, 2, 3, 4, 4, 4, 10, 10</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.20></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.14></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(21, 0)</div><div>-</div><div> -- 1.1) insert w/o explicit confl. action & w/</div><div> --      index replace action & empty dest_table</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.22",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.15",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -276,45 +252,41 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t3 VALUES (1);</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.22></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.15></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.22></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.15></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.23",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.16",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.23></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.16></div><div> <span style="white-space:pre">           </span>1, 1, 3, 3, 5, 5, 10, 10</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.23></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.16></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.24",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.17",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t3;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.24></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.17></div><div> <span style="white-space:pre">           </span>1</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.24></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.17></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-do_xfer_test(25, 1)</div><div>-</div><div> -- 1.2) insert w/o explicit confl. action & w/</div><div> -- index replace action & non-empty dest_table</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.26",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.18",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -327,34 +299,30 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.26></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.18></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.26></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.18></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.27",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.19",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.27></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.19></div><div> <span style="white-space:pre">           </span>1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 10, 10</div><div>-<span style="white-space:pre">         </span>-- <xfer-optimization-1.27></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.19></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(28, 0)</div><div>-</div><div> -- 2) insert with abort</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">        </span>"xfer-optimization-1.29",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.20",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -366,34 +334,30 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT OR ABORT INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.29></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.20></div><div> <span style="white-space:pre">           </span>1, "Duplicate key exists in unique index 'sqlite_autoindex_T2_1' in space 'T2'"</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.29></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.20></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.30",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.21",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.30></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.21></div><div> <span style="white-space:pre">           </span>2, 2, 3, 4, 4, 4, 10, 10</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.30></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.21></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(31, 1)</div><div>-</div><div> -- 3.0) insert with rollback (into empty table)</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">        </span>"xfer-optimization-1.32",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.22",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -403,34 +367,30 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">           </span>BEGIN;</div><div> <span style="white-space:pre">                      </span>INSERT OR ROLLBACK INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">        </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.32></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.22></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.32></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.22></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.33",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.23",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.33></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.23></div><div> <span style="white-space:pre">           </span>1, 1, 3, 3, 5, 5, 10, 10</div><div>-<span style="white-space:pre">             </span>-- <xfer-optimization-1.33></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.23></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(34, 1)</div><div>-</div><div> -- 3.1) insert with rollback (into non-empty table)</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.35",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.24",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -442,32 +402,28 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT OR ROLLBACK INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">        </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.35></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.24></div><div> <span style="white-space:pre">           </span>1, "UNIQUE constraint failed: T2.A"</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.35></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.24></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.36",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.25",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.36></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.25></div><div> <span style="white-space:pre">           </span>2, 2, 3, 4</div><div>-<span style="white-space:pre">           </span>-- <xfer-optimization-1.36></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.25></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(37, 0)</div><div>-</div><div> -- 4) insert with replace</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">      </span>"xfer-optimization-1.38",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.26",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -479,34 +435,30 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT OR REPLACE INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre"> </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.38></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.26></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.38></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.26></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 0</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.39",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.27",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.39></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.27></div><div> <span style="white-space:pre">           </span>1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 10, 10</div><div>-<span style="white-space:pre">         </span>-- <xfer-optimization-1.39></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.27></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(40, 0)</div><div>-</div><div> -- 5) insert with fail</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre"> </span>"xfer-optimization-1.41",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.28",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -518,34 +470,30 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT OR FAIL INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">    </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.41></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.28></div><div> <span style="white-space:pre">           </span>1, "Duplicate key exists in unique index 'sqlite_autoindex_T2_1' in space 'T2'"</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.41></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.28></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.42",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.29",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.42></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.29></div><div> <span style="white-space:pre">           </span>1, 1, 2, 2, 3, 4, 4, 4, 10, 10</div><div>-<span style="white-space:pre">               </span>-- <xfer-optimization-1.42></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.29></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(43, 0)</div><div>-</div><div> -- 6) insert with ignore</div><div> ------------------------------------------------------------------------------</div><div> </div><div>-bfr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-test:do_catchsql_test(</div><div>-<span style="white-space:pre">       </span>"xfer-optimization-1.44",</div><div>+test:do_catchsql_xfer_test(</div><div>+<span style="white-space:pre">       </span>"xfer-optimization-1.30",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">          </span>DROP TABLE t1;</div><div> <span style="white-space:pre">              </span>DROP TABLE t2;</div><div>@@ -557,25 +505,23 @@ test:do_catchsql_test(</div><div> <span style="white-space:pre">                   </span>INSERT INTO t2 VALUES (4, 4);</div><div> <span style="white-space:pre">                       </span>INSERT OR IGNORE INTO t2 SELECT * FROM t1;</div><div> <span style="white-space:pre">  </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.44></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.30></div><div> <span style="white-space:pre">           </span>0</div><div>-<span style="white-space:pre">            </span>-- <xfer-optimization-1.44></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.30></div><div>+<span style="white-space:pre">    </span>}, {</div><div>+<span style="white-space:pre">         </span>exp_xfer_count = 1</div><div> <span style="white-space:pre">  </span>})</div><div> </div><div> test:do_execsql_test(</div><div>-<span style="white-space:pre">    </span>"xfer-optimization-1.45",</div><div>+<span style="white-space:pre">  </span>"xfer-optimization-1.31",</div><div> <span style="white-space:pre"> </span>[[</div><div> <span style="white-space:pre">                  </span>INSERT INTO t2 VALUES (10, 10);</div><div> <span style="white-space:pre">             </span>COMMIT;</div><div> <span style="white-space:pre">             </span>SELECT * FROM t2;</div><div> <span style="white-space:pre">   </span>]], {</div><div>-<span style="white-space:pre">                </span>-- <xfer-optimization-1.45></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.31></div><div> <span style="white-space:pre">           </span>1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 10, 10</div><div>-<span style="white-space:pre">         </span>-- <xfer-optimization-1.45></div><div>+<span style="white-space:pre">            </span>-- <xfer-optimization-1.31></div><div> <span style="white-space:pre">   </span>})</div><div> </div><div>-aftr = box.sql.debug().sql_xfer_count</div><div>-</div><div>-do_xfer_test(46, 0)</div><div>-</div><div> test:finish_test()</div><div>diff --git a/test/sql-tap/with2.test.lua b/test/sql-tap/with2.test.lua</div><div>index fbd1f4e..bd0187f 100755</div><div>--- a/test/sql-tap/with2.test.lua</div><div>+++ b/test/sql-tap/with2.test.lua</div><div>@@ -1,6 +1,6 @@</div><div> #!/usr/bin/env tarantool</div><div> test = require("sqltester")</div><div>-test:plan(44)</div><div>+test:plan(59)</div><div> </div><div> --!./tcltestrunner.lua</div><div> -- 2014 January 11</div><div>@@ -382,43 +382,136 @@ genstmt(255), {</div><div> --     -- </4.7></div><div> -- })</div><div> </div><div>------------------------------------------------------------------------------</div><div>--- Check that adding a WITH clause to an INSERT disables the xfer </div><div>+-----------------------------------------------------------------</div><div>+-- Check that adding a WITH clause to an INSERT disables the xfer</div><div> -- optimization.</div><div>---</div><div>--- Tarantool: `sqlite3_xferopt_count` is not exported</div><div>---   Need to understand if this optimization works at all and if we really need it.</div><div>---   Commented so far.</div><div>--- function do_xfer_test(tn, bXfer, sql, res)</div><div>---     res = res or ""</div><div>---     sqlite3_xferopt_count = 0</div><div>---     X(267, "X!cmd", [=[["uplevel",[["list","do_test",["tn"],["\n    set dres [db eval {",["sql"],"}]\n    list [set ::sqlite3_xferopt_count] [set dres]\n  "],[["list",["bXfer"],["res"]]]]]]]=])</div><div>--- end</div><div> </div><div>--- test:do_execsql_test(</div><div>---     5.1,</div><div>---     [[</div><div>---         DROP TABLE IF EXISTS t1;</div><div>---         DROP TABLE IF EXISTS t2;</div><div>---         CREATE TABLE t1(a PRIMARY KEY, b);</div><div>---         CREATE TABLE t2(a PRIMARY KEY, b);</div><div>---     ]])</div><div>-</div><div>--- do_xfer_test(5.2, 1, " INSERT INTO t1 SELECT * FROM t2 ")</div><div>--- do_xfer_test(5.3, 0, " INSERT INTO t1 SELECT a, b FROM t2 ")</div><div>--- do_xfer_test(5.4, 0, " INSERT INTO t1 SELECT b, a FROM t2 ")</div><div>--- do_xfer_test(5.5, 0, [[ </div><div>---   WITH x AS (SELECT a, b FROM t2) INSERT INTO t1 SELECT * FROM x </div><div>--- ]])</div><div>--- do_xfer_test(5.6, 0, [[ </div><div>---   WITH x AS (SELECT a, b FROM t2) INSERT INTO t1 SELECT * FROM t2 </div><div>--- ]])</div><div>--- do_xfer_test(5.7, 0, [[ </div><div>---  INSERT INTO t1 WITH x AS ( SELECT * FROM t2 ) SELECT * FROM x</div><div>--- ]])</div><div>--- do_xfer_test(5.8, 0, [[ </div><div>---  INSERT INTO t1 WITH x(a,b) AS ( SELECT * FROM t2 ) SELECT * FROM x</div><div>--- ]])</div><div>+local function do_xfer_test(test, test_func, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">        </span>local opts = opts or {}</div><div>+<span style="white-space:pre">      </span>local exp_xfer_count = opts.exp_xfer_count</div><div>+<span style="white-space:pre">   </span>local before = box.sql.debug().sql_xfer_count</div><div>+<span style="white-space:pre">        </span>local ok, result = pcall(test_func, test, test_name, func, exp)</div><div>+<span style="white-space:pre">      </span>local after = box.sql.debug().sql_xfer_count</div><div>+<span style="white-space:pre"> </span>if exp_xfer_count ~= nil then</div><div>+<span style="white-space:pre">                </span>ok = ok and test:is(after - before, exp_xfer_count,</div><div>+<span style="white-space:pre">          </span>                    test_name .. '-xfer-count')</div><div>+<span style="white-space:pre">    </span>end</div><div>+<span style="white-space:pre">  </span>return ok</div><div>+end</div><div>+</div><div>+test.do_execsql_xfer_test = function(test, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">   </span>return do_xfer_test(test, test.do_execsql_test, test_name, func, exp, opts)</div><div>+end</div><div>+</div><div>+test.do_catchsql_xfer_test = function(test, test_name, func, exp, opts)</div><div>+<span style="white-space:pre">        </span>return do_xfer_test(test, test.do_catchsql_test, test_name, func, exp, opts)</div><div>+end</div><div>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre"> </span>5.1,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>DROP TABLE IF EXISTS t1;</div><div>+<span style="white-space:pre">             </span>DROP TABLE IF EXISTS t2;</div><div>+<span style="white-space:pre">             </span>CREATE TABLE t1(a PRIMARY KEY, b);</div><div>+<span style="white-space:pre">           </span>CREATE TABLE t2(a PRIMARY KEY, b);</div><div>+<span style="white-space:pre">           </span>INSERT INTO t2 VALUES (1, 1), (2, 2);</div><div>+<span style="white-space:pre">        </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.1></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.1></div><div>+<span style="white-space:pre">       </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.2,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 SELECT * FROM t2;</div><div>+<span style="white-space:pre">             </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.2></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.2></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 1</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.3,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 SELECT a, b FROM t2;</div><div>+<span style="white-space:pre">          </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.3></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.3></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.4,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 SELECT b, a FROM t2;</div><div>+<span style="white-space:pre">          </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.4></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.4></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.5,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>WITH x AS (SELECT a, b FROM t2) INSERT INTO t1 SELECT * FROM x;</div><div>+<span style="white-space:pre">              </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.5></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.5></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.6,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>WITH x AS (SELECT a, b FROM t2) INSERT INTO t1 SELECT * FROM t2;</div><div>+<span style="white-space:pre">             </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.6></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.6></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.7,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 WITH x AS (SELECT * FROM t2) SELECT * FROM x;</div><div>+<span style="white-space:pre">         </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.7></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.7></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div>+test:do_execsql_xfer_test(</div><div>+<span style="white-space:pre"> </span>5.8,</div><div>+<span style="white-space:pre"> </span>[[</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 WITH x(a,b) AS (SELECT * FROM t2) SELECT * FROM x;</div><div>+<span style="white-space:pre">            </span>DELETE FROM t1;</div><div>+<span style="white-space:pre">      </span>]], {</div><div>+<span style="white-space:pre">                </span>-- <5.8></div><div>+</div><div>+<span style="white-space:pre">               </span>-- <5.8></div><div>+<span style="white-space:pre">       </span>},  {</div><div>+<span style="white-space:pre">               </span>exp_xfer_count = 0</div><div>+<span style="white-space:pre">   </span>})</div><div>+</div><div> -----------------------------------------------------------------------------</div><div> -- Check that syntax (and other) errors in statements with WITH clauses</div><div> -- attached to them do not cause problems (e.g. memory leaks).</div></div></div>