<div dir="ltr">Fixes were made:<div><br><div class="gmail_quote"><div dir="ltr">чт, 19 апр. 2018 г. в 14:22, n.pettik <<a href="mailto:korablev@tarantool.org">korablev@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">>The bug was fixed so the data should now insert<br>
>correctly.<br>
<br>
Please, instead of mentioning that you just fixed bug (it is obvious),<br>
provide brief information (without digging in details) how the problem was solved. <br>
(e.g. 'now only PK is used to handle insertion').<br>
<br>
Overall, the idea is OK, but implementation could be more elegant.<br>
You don’t need to iterate through all dest/source indexes:<br>
it is possible to get PK using function sqlite3PrimaryKeyIndex();<br>
Thus, complexity reduces from O(n^2) to O(n), where n - number of indexes.<br>
<br>
But, there is even better approach: in Tarantool PK always comes with 0 ordinal<br>
number. So, you can do space lookup by id (there is macros, which converts<br>
table->tnum to space id: SQLITE_PAGENO_TO_SPACEID) and fetch real PK<br>
index with O(1) complexity: space_index(space, 0 /* PK */);<br>
It is not mandatory now, only if you are willing to do it.<br>
<br>
Also, as we have discussed, remove pls redundant uniqueness check.<br>
<br>
>       }<br>
>       if (emptySrcTest)<br>
>               sqlite3VdbeJumpHere(v, emptySrcTest);<br>
> diff --git a/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua<br>
> new file mode 100755<br>
> index 0000000..3b2bcc6<br>
> --- /dev/null<br>
> +++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua<br>
> @@ -0,0 +1,52 @@<br>
> +#!/usr/bin/env tarantool<br>
> +test = require("sqltester")<br>
> +test:plan(3)<br>
> +<br>
> +test:do_execsql_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>
> +             DROP TABLE t1;<br>
> +             DROP TABLE t2;<br>
> +     ]], {<br>
> +             -- <xfer-optimization-1.1><br>
> +<br>
> +             -- <xfer-optimization-1.1><br>
> +     })<br>
<br>
do_execsql_test() returns result of last executed query.<br>
In this case, it is ‘DROP TABLE’, which always (in this particular case)<br>
will return nothing (i.e. table will be successfully dropped).<br>
To catch some error, you can use do_catchsql_test() function.<br>
After you check that insertion occurs without errors, you need<br>
to check that all rows have been transferred from one table to another.<br>
So, you just use do_execsql_test() to test 'SELECT * FROM t2;’.<br>
After all, you may drop tables in the beginning of next test,<br>
since it won’t affect result of last executed statement.<br>
<br>
Moreover, I would add more test cases to verify that xfer<br>
optimization in general works: try to rearrange columns/indexes<br>
order, add different ON CONFLICT clauses etc.<br>
<br></blockquote><div><br></div><div>Currently insertion from the table to another one</div><div>with the same schema using SELECT works wrong.</div><div>The problem lies in xfer optimization which opens cursors for</div><div>all of the indexes and inserts data excessively.</div><div>Now only PRIMARY KEY is used to handle insertion.</div><div>Moreover analyzing xfer optimization I have noticed</div><div>that unnecessary check from sqlite3 were used,</div><div>accordingly excessive code cencerned with it</div><div>was deleted.</div><div><br></div><div>Closes #3307</div><div>---</div><div><br></div><div>Branch: <a href="https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3307-xfer-optimization-issue">https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3307-xfer-optimization-issue</a></div><div>Issue: <a href="https://github.com/tarantool/tarantool/issues/3307">https://github.com/tarantool/tarantool/issues/3307</a></div><div><br></div><div> src/box/sql/insert.c                               |  64 ++++-----</div><div> .../gh-3307-xfer-optimization-issue.test.lua       | 159 +++++++++++++++++++++</div><div> 2 files changed, 184 insertions(+), 39 deletions(-)</div><div> create mode 100755 test/sql-tap/gh-3307-xfer-optimization-issue.test.lua</div><div><br></div><div>diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c</div><div>index ae8dafb..ed134f4 100644</div><div>--- a/src/box/sql/insert.c</div><div>+++ b/src/box/sql/insert.c</div><div>@@ -1711,6 +1711,7 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">       </span>/* Parser context */</div><div> <span style="white-space:pre">        </span>ExprList *pEList;<span style="white-space:pre">    </span>/* The result set of the SELECT */</div><div> <span style="white-space:pre">  </span>Table *pSrc;<span style="white-space:pre">         </span>/* The table in the FROM clause of SELECT */</div><div> <span style="white-space:pre">        </span>Index *pSrcIdx, *pDestIdx;<span style="white-space:pre">   </span>/* Source and destination indices */</div><div>+<span style="white-space:pre"> </span>struct index *src_idx, *dest_idx;<span style="white-space:pre">    </span>/* Source and destination indices */</div><div> <span style="white-space:pre">        </span>struct SrcList_item *pItem;<span style="white-space:pre">  </span>/* An element of pSelect->pSrc */</div><div> <span style="white-space:pre">        </span>int i;<span style="white-space:pre">                       </span>/* Loop counter */</div><div> <span style="white-space:pre">  </span>int iSrc, iDest;<span style="white-space:pre">     </span>/* Cursors from source and destination */</div><div>@@ -1718,9 +1719,9 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">       </span>/* Parser context */</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>Vdbe *v;<span style="white-space:pre">             </span>/* The VDBE we are building */</div><div>-<span style="white-space:pre">       </span>int destHasUniqueIdx = 0;<span style="white-space:pre">    </span>/* True if pDest has a UNIQUE index */</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>struct space *space;<span style="white-space:pre"> </span>/* Space pointer for pDest and pSrc */</div><div> </div><div> <span style="white-space:pre">     </span>if (pSelect == NULL)</div><div> <span style="white-space:pre">                </span>return 0;<span style="white-space:pre">    </span>/* Must be of the form  INSERT INTO ... SELECT ... */</div><div>@@ -1830,9 +1831,6 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">  </span>/* Parser context */</div><div> <span style="white-space:pre">                </span>}</div><div> <span style="white-space:pre">   </span>}</div><div> <span style="white-space:pre">   </span>for (pDestIdx = pDest->pIndex; pDestIdx; pDestIdx = pDestIdx->pNext) {</div><div>-<span style="white-space:pre">         </span>if (index_is_unique(pDestIdx)) {</div><div>-<span style="white-space:pre">                     </span>destHasUniqueIdx = 1;</div><div>-<span style="white-space:pre">                </span>}</div><div> <span style="white-space:pre">           </span>for (pSrcIdx = pSrc->pIndex; pSrcIdx; pSrcIdx = pSrcIdx->pNext) {</div><div> <span style="white-space:pre">                     </span>if (xferCompatibleIndex(pDestIdx, pSrcIdx))</div><div> <span style="white-space:pre">                         </span>break;</div><div>@@ -1875,52 +1873,40 @@ xferOptimization(Parse * pParse,<span style="white-space:pre">        </span>/* Parser context */</div><div> <span style="white-space:pre">        </span>regData = sqlite3GetTempReg(pParse);</div><div> <span style="white-space:pre">        </span>regTupleid = sqlite3GetTempReg(pParse);</div><div> <span style="white-space:pre">     </span>sqlite3OpenTable(pParse, iDest, pDest, OP_OpenWrite);</div><div>-<span style="white-space:pre">        </span>assert(destHasUniqueIdx);</div><div>-<span style="white-space:pre">    </span>if ((pDest->iPKey < 0 && pDest->pIndex != 0)<span style="white-space:pre">        </span>/* (1) */</div><div>-<span style="white-space:pre">    </span>    ||destHasUniqueIdx<span style="white-space:pre">     </span>/* (2) */</div><div>-<span style="white-space:pre">    </span>    || (onError != ON_CONFLICT_ACTION_ABORT</div><div>-<span style="white-space:pre">                </span>&& onError != ON_CONFLICT_ACTION_ROLLBACK)<span style="white-space:pre">   </span>/* (3) */</div><div>-<span style="white-space:pre">    </span>    ) {</div><div>-<span style="white-space:pre">            </span>/* In some circumstances, we are able to run the xfer optimization</div><div>-<span style="white-space:pre">           </span> * only if the destination table is initially empty.</div><div>-<span style="white-space:pre">         </span> * This block generates code to make</div><div>-<span style="white-space:pre">         </span> * that determination.</div><div>-<span style="white-space:pre">               </span> *</div><div>-<span style="white-space:pre">           </span> * Conditions under which the destination must be empty:</div><div>-<span style="white-space:pre">             </span> *</div><div>-<span style="white-space:pre">           </span> * (1) There is no INTEGER PRIMARY KEY but there are indices.</div><div>-<span style="white-space:pre">                </span> *</div><div>-<span style="white-space:pre">           </span> * (2) The destination has a unique index.  (The xfer optimization</div><div>-<span style="white-space:pre">          </span> *     is unable to test uniqueness.)</div><div>-<span style="white-space:pre">             </span> *</div><div>-<span style="white-space:pre">           </span> * (3) onError is something other than ON_CONFLICT_ACTION_ABORT and _ROLLBACK.</div><div>-<span style="white-space:pre">               </span> */</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>-<span style="white-space:pre">               </span>sqlite3VdbeJumpHere(v, addr1);</div><div>-<span style="white-space:pre">       </span>}</div><div> </div><div>-<span style="white-space:pre">   </span>for (pDestIdx = pDest->pIndex; pDestIdx; pDestIdx = pDestIdx->pNext) {</div><div>-<span style="white-space:pre">         </span>for (pSrcIdx = pSrc->pIndex; ALWAYS(pSrcIdx);</div><div>-<span style="white-space:pre">             </span>     pSrcIdx = pSrcIdx->pNext) {</div><div>-<span style="white-space:pre">                       </span>if (xferCompatibleIndex(pDestIdx, pSrcIdx))</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>/* The xfer optimization is unable to test uniqueness</div><div>+<span style="white-space:pre">        </span> * while we have a unique PRIMARY KEY in any existing table.</div><div>+<span style="white-space:pre"> </span> * This is the reason we can only run it if the destination table</div><div>+<span style="white-space:pre">    </span> * is initially empty.</div><div>+<span style="white-space:pre">       </span> * This block generates code to make that determination.</div><div>+<span style="white-space:pre">     </span> */</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>+<span style="white-space:pre">       </span>sqlite3VdbeJumpHere(v, addr1);</div><div>+</div><div>+<span style="white-space:pre">       </span>space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pDest->tnum));</div><div>+<span style="white-space:pre">       </span>dest_idx = space_index(space, 0 /* PK */);</div><div>+<span style="white-space:pre">   </span>space = space_by_id(SQLITE_PAGENO_TO_SPACEID(pSrc->tnum));</div><div>+<span style="white-space:pre">        </span>src_idx = space_index(space, 0 /* PK */);</div><div>+<span style="white-space:pre">    </span>assert(src_idx);</div><div>+<span style="white-space:pre">     </span>assert(dest_idx);</div><div>+<span style="white-space:pre">    </span>pDestIdx = sqlite3PrimaryKeyIndex(pDest);</div><div>+<span style="white-space:pre">    </span>pSrcIdx = sqlite3PrimaryKeyIndex(pSrc);</div><div>+<span style="white-space:pre">      </span>if (xferCompatibleIndex(pDestIdx, pSrcIdx)) {</div><div> <span style="white-space:pre">               </span>assert(pSrcIdx);</div><div> <span style="white-space:pre">            </span>emit_open_cursor(pParse, iSrc, pSrcIdx->tnum);</div><div> <span style="white-space:pre">           </span>sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);</div><div>-<span style="white-space:pre">            </span>VdbeComment((v, "%s", pSrcIdx->zName));</div><div>+<span style="white-space:pre">         </span>VdbeComment((v, "%s", src_idx->def->name));</div><div> <span style="white-space:pre">         </span>emit_open_cursor(pParse, iDest, pDestIdx->tnum);</div><div> <span style="white-space:pre">         </span>sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);</div><div> <span style="white-space:pre">          </span>sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);</div><div>-<span style="white-space:pre">              </span>VdbeComment((v, "%s", pDestIdx->zName));</div><div>+<span style="white-space:pre">                </span>VdbeComment((v, "%s", dest_idx->def->name));</div><div> <span style="white-space:pre">                </span>addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);</div><div> <span style="white-space:pre">           </span>VdbeCoverage(v);</div><div> <span style="white-space:pre">            </span>sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);</div><div> <span style="white-space:pre">            </span>sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);</div><div>-<span style="white-space:pre">          </span>if (pDestIdx->idxType == SQLITE_IDXTYPE_PRIMARYKEY)</div><div>-<span style="white-space:pre">                       </span>sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);</div><div>+<span style="white-space:pre">              </span>sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);</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>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>new file mode 100755</div><div>index 0000000..1049621</div><div>--- /dev/null</div><div>+++ b/test/sql-tap/gh-3307-xfer-optimization-issue.test.lua</div><div>@@ -0,0 +1,159 @@</div><div>+#!/usr/bin/env tarantool</div><div>+test = require("sqltester")</div><div>+test:plan(12)</div><div>+</div><div>+test:do_catchsql_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>+<span style="white-space:pre">            </span>INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);</div><div>+<span style="white-space:pre">                </span>CREATE TABLE t2(a INTEGER PRIMARY KEY, b INTEGER UNIQUE);</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.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>+</div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">      </span>"xfer-oprimization-1.2",</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-oprimization-1.2></div><div>+<span style="white-space:pre">             </span>1, 1, 2, 2, 3, 3</div><div>+<span style="white-space:pre">             </span>-- <xfer-oprimization-1.2></div><div>+<span style="white-space:pre">     </span>})</div><div>+</div><div>+test:do_catchsql_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>+<span style="white-space:pre">               </span>CREATE TABLE t1(id INTEGER PRIMARY KEY, b INTEGER);</div><div>+<span style="white-space:pre">          </span>CREATE TABLE t2(id INTEGER PRIMARY KEY, b INTEGER);</div><div>+<span style="white-space:pre">          </span>CREATE INDEX i1 ON t1(b);</div><div>+<span style="white-space:pre">            </span>CREATE INDEX i2 ON t2(b);</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.3></div><div>+<span style="white-space:pre">             </span>0</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></div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">        </span>"xfer-oprimization-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>+<span style="white-space:pre">                </span>-- <xfer-optimization-1.4></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.4></div><div>+<span style="white-space:pre">     </span>})</div><div>+</div><div>+test:do_catchsql_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>+<span style="white-space:pre">               </span>CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER, c INTEGER);</div><div>+<span style="white-space:pre">                </span>INSERT INTO t1 VALUES (1, 1, 2), (2, 2, 3), (3, 3, 4);</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>+</div><div>+<span style="white-space:pre">     </span>]], {</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.5></div><div>+<span style="white-space:pre">     </span>})</div><div>+<span style="white-space:pre">           </span></div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">        </span>"xfer-oprimization-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-oprimization-1.6></div><div>+</div><div>+<span style="white-space:pre">             </span>-- <xfer-oprimization-1.6></div><div>+<span style="white-space:pre">     </span>})</div><div>+<span style="white-space:pre">           </span></div><div>+test:do_catchsql_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>+<span style="white-space:pre">               </span>CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);</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>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>+</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>0</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></div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">        </span>"xfer-oprimization-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-oprimization-1.6></div><div>+<span style="white-space:pre">             </span>1, 1, 2, 2, 3, 3</div><div>+<span style="white-space:pre">             </span>-- <xfer-oprimization-1.6></div><div>+<span style="white-space:pre">     </span>})</div><div>+</div><div>+test:do_catchsql_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>+<span style="white-space:pre">               </span>CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 2);</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>+</div><div>+<span style="white-space:pre">     </span>]], {</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.9></div><div>+<span style="white-space:pre">     </span>})</div><div>+<span style="white-space:pre">           </span></div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">        </span>"xfer-oprimization-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-oprimization-1.10></div><div>+<span style="white-space:pre">            </span></div><div>+<span style="white-space:pre">             </span>-- <xfer-oprimization-1.10></div><div>+<span style="white-space:pre">    </span>})</div><div>+</div><div>+test:do_catchsql_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>+<span style="white-space:pre">               </span>CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);</div><div>+<span style="white-space:pre">           </span>INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 2);</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>+</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>0</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></div><div>+test:do_execsql_test(</div><div>+<span style="white-space:pre">        </span>"xfer-oprimization-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-oprimization-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-oprimization-1.12></div><div>+<span style="white-space:pre">    </span>})</div><div>+</div><div>+test:finish_test()</div><div>-- </div><div>2.7.4 </div></div></div></div>