-C Corrections\sto\sthe\s'filepath_normalize'\stest\ssuite\shelper\sprocedure.
-D 2021-02-03T19:38:40.978
+C Work\stoward\shandling\sinterleaved\sRETURNING\sstatements.\s\sTrunk\sdoes\snot\nhandle\sthat\scase\scorrectly.\s\sThis\sbranch\sis\sa\spartial\simplementation\sof\nideas\sthat\smight,\showever.
+D 2021-02-04T11:14:37.812
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f6761473ea4b51190fc52f8f2121498b78717266e106e7bff12849ea2d52165f
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 738cb746189f721f59972993c13085fa2975c4cbfd04ba26445f3b42c81237dc
+F src/select.c 14d7315897b9654badf01635781ae15113ee88a4e6684d3a60a63242ea3cadd5
F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a0879
F src/sqlite.h.in 8855a19f37ade8dad189a9e48233a2ebe1b46faf469c7eb0906a654e252dcc57
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h 0fda3b2c05b1559135aa2c4ecb8e75bd2085ba4433310bbb5427d97c2d81315d
+F src/sqliteInt.h 9462cda2ddf4f2953c72d87ee041f74f5f395b44b1b943bcad3f8a4a245b478f
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c c64c49d7c2ec4490c2fef1f24350167ba16b03b0c6cee58ad1a1d70a4325d4e9
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
-F src/trigger.c 0a242d65dd9b9822d4e990653eb4ece3557dcda01374934aa3cc1f9718d8dee3
+F src/trigger.c 79d6f7329fc6a8fdad9aa6d4da9703f412ef7977592ea7819dfcb0bac2500f59
F src/update.c 0f5a61f0787199983530a33f6fffe4f52742f35fcdf6ccfad1078b1a8bc17723
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c b3c9a3f9d546d4848a2a8c88a3c40875cd6ba3d248d9b99d01b1eeb38b29c171
+F src/vdbe.c 88ae06e39cbab0d3433b5512bef6921d845460b1ab49ae2040332cec6fd4b024
F src/vdbe.h a71bf43572d3de57923d1928ac01ae8d355cd67e94462ba4f7462265cedbef9a
-F src/vdbeInt.h 3df118924e1711f1bbc8e30c46260d0ab6c3b029b32dd411f789111f76434f3c
-F src/vdbeapi.c 4a43e303ec3354c785f453e881521969378e85628278ab74ba4a9df790c0d93b
-F src/vdbeaux.c 34994221fbde303e362cf11c7d97fe9b115055cfdf716260ca0140811de94aab
+F src/vdbeInt.h b257dd6c6363c5611e37a390b0c479dd20c74dea7f888ebaba2f65f6bfa6fe18
+F src/vdbeapi.c 8e29edeb515656e65345945c8ec17b0dd37abd3bf96d708e49afff95dd1b8856
+F src/vdbeaux.c be48e68e8994af49fff588a1f167a704f6cba61b707156da154440b60d35313e
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6b29e549bb34933bfd0758e31085e65dcc0f75446c478fc775d96cf01c22cf43
-R 85ac248a64299c59878f72d774654f84
-U mistachkin
-Z cd094eb04790b0c848908f94f1895107
+P 32f4d04470bf953b08eea285543f16e03de13d5448c1ebccbba1578ca3b5363e
+R 324119af37eb27d16c017f1cb32c8d09
+T *branch * interleaved-returning
+T *sym-interleaved-returning *
+T -sym-trunk *
+U drh
+Z dd3a22aecc43ba661a828fb24a9b1b1c
-32f4d04470bf953b08eea285543f16e03de13d5448c1ebccbba1578ca3b5363e
\ No newline at end of file
+e1eb62131913fcc4aa58a3f7e634ed2bbecf32763d936067d36ce1c2d2142a75
\ No newline at end of file
if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
- }else if( eDest==SRT_Coroutine ){
- sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
+ }else if( eDest==SRT_Output ){
+ if( pDest->iSDParm>=0 ){
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Returning, regResult, nResultCol);
+ sqlite3VdbeAddOp0(v, OP_CkNesting);
+ }
}else{
- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}
break;
}
** the side-effects of functions.
**
** SRT_Output Generate a row of output (using the OP_ResultRow
-** opcode) for each row in the result set.
+** opcode) for each row in the result set. If iSDParm
+** is negative, then enforce strict nesting order
+** on concurrent statements.
**
** SRT_Mem Only valid if the result is a single column.
** Store the first column of the first result row
Select *pNew;
pSelect->pEList =
sqlite3ExpandReturning(pParse, pList, pParse->pTriggerTab);
- sqlite3SelectDestInit(&sDest, SRT_Output, 0);
+ sqlite3SelectDestInit(&sDest, SRT_Output, -1);
pNew = sqlite3SelectDup(db, pSelect, 0);
if( pNew ){
sqlite3Select(pParse, pNew, &sDest);
break;
}
+/* Opcode: Returning P1 P2 * * *
+** Synopsis: output=r[P1@P2]
+**
+** The registers P1 through P1+P2-1 contain a single row of
+** results. This opcode causes the sqlite3_step() call to terminate
+** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
+** structure to provide access to the r(P1)..r(P1+P2-1) values as
+** the result row.
+**
+** This opcode is like OP_ResultRow with the addition that it enforces
+** nesting order for concurrent prepared statements. This opcode
+** is always followed immediately by an OP_CkNesting opcode which does
+** the actual nesting test. DML statement that have a RETURNING clause
+** use this opcode, rather than OP_ResultRow, to return their results,
+** and thus prevent interleaved DML statements.
+*/
+case OP_Returning: {
+ assert( pOp[1].opcode==OP_CkNesting );
+ if( p->pPrev ){
+ p->pPrev->pNext = p->pNext;
+ if( p->pNext ) p->pNext->pPrev = p->pPrev;
+ p->pPrev = 0;
+ p->pNext = db->pVdbe;
+ db->pVdbe = p;
+ }
+ p->bUsesReturning = 1;
+ goto result_row_opcode_body;
+}
+
+
+/* Opcode: CkNested * * * * *
+**
+** This opcode always follows an OP_Returning opcode. Thus, it is
+** the first opcode to run on the next sqlite3_step() call after
+** receiving the results of a RETURNING clause in a DML statement.
+**
+** This opcode checks to verify that the DML statements are properly
+** nested. If an error occurs, it returns SQLITE_BUSY_NESTING.
+*/
+case OP_CkNesting: {
+ Vdbe *pX;
+ for(pX=db->pVdbe; pX!=p && ALWAYS(pX!=0); pX=pX->pNext){
+ if( pX->bUsesReturning
+ && pX->iVdbeMagic==VDBE_MAGIC_RUN
+ && pX->pc>0
+ ){
+ rc = SQLITE_BUSY;
+ goto vdbe_return;
+ }
+ }
+ break;
+}
+
+
/* Opcode: ChngCntRow P1 P2 * * *
** Synopsis: output=r[P1]
**
case OP_ResultRow: {
Mem *pMem;
int i;
+
+ result_row_opcode_body:
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
+ bft bUsesReturning:1; /* True for DML statements with RETURNING */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
+ if( p->iVDbeMagic==VDBE_MAGIC_ABORT ){
+ return SQLITE_ABORT;
+ }
#ifdef SQLITE_OMIT_AUTORESET
if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
assert( db->nStatement>0 );
- assert( p->iStatement==(db->nStatement+db->nSavepoint) );
+ /* assert( p->iStatement==(db->nStatement+db->nSavepoint) ); */
for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;