]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Work toward handling interleaved RETURNING statements. Trunk does not interleaved-returning
authordrh <>
Thu, 4 Feb 2021 11:14:37 +0000 (11:14 +0000)
committerdrh <>
Thu, 4 Feb 2021 11:14:37 +0000 (11:14 +0000)
handle that case correctly.  This branch is a partial implementation of
ideas that might, however.

FossilOrigin-Name: e1eb62131913fcc4aa58a3f7e634ed2bbecf32763d936067d36ce1c2d2142a75

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
src/trigger.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c

index 512110c1e4dc22486743592da5e1f23d11215005..7d728446bd9e5dab75030d6e007cfafe233ee4bb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -541,12 +541,12 @@ F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
 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
@@ -607,17 +607,17 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 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
@@ -1899,7 +1899,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 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
index a3ab0cdd0d86ad23e70f0797ac30429d05e87294..517b29d52612a8725977873d862b4f2346803b7b 100644 (file)
@@ -1 +1 @@
-32f4d04470bf953b08eea285543f16e03de13d5448c1ebccbba1578ca3b5363e
\ No newline at end of file
+e1eb62131913fcc4aa58a3f7e634ed2bbecf32763d936067d36ce1c2d2142a75
\ No newline at end of file
index 7c3019890c68786f674532a4a8e551c183a13b8a..be5fa74964b43b20971e9115d81fb5d8aded0b67 100644 (file)
@@ -1210,10 +1210,15 @@ static void selectInnerLoop(
       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;
     }
index 3cadb7f53a0638027129b81106fc9f607d15178f..a32f103156dde30476b6ff4733d550e1d4d91e36 100644 (file)
@@ -3201,7 +3201,9 @@ struct Select {
 **                     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
index ef0a90b24fb1c289170de62467e66a0763164ead..f393bc7e1210c5c22f3f0ad10cc2203b776e2fd2 100644 (file)
@@ -943,7 +943,7 @@ static int codeTriggerProgram(
         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);
index 97cd696de318d4c27b67ec37d1070965ec935615..3cb3d9faf45fb76b19ef3a1c3f4a8625a8aebee4 100644 (file)
@@ -1445,6 +1445,60 @@ case OP_IntCopy: {            /* out2 */
   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]
 **
@@ -1477,6 +1531,8 @@ case OP_ChngCntRow: {
 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 );
index 4f8a2edf3709198fb887ca42ec8ed473faacb1a5..51514f74730c4cbd3ef406099ef5c17d88e6c2d2 100644 (file)
@@ -427,6 +427,7 @@ struct Vdbe {
   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() */
index ba3bdf6a5f54614f30f44e35a4dd9a00d5b3171a..6cecfe56489b73ecc05adf310984478b5485a33d 100644 (file)
@@ -634,6 +634,9 @@ static int sqlite3Step(Vdbe *p){
     ** 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);
index 1c77b2ce945e8a2cc00e8583ed2bdd0802892468..80aaf01aa3f4c53772706b8f784fbfa906e4d596 100644 (file)
@@ -2954,7 +2954,7 @@ static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
 
   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;