From: drh Date: Mon, 31 Dec 2018 16:36:42 +0000 (+0000) Subject: Fix the OP_OpenEphemeral opcode in the bytecode engine so that if it is called X-Git-Tag: version-3.27.0~226 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4afdfa195b0ae5fe3b8638c722c937792d3cfd0c;p=thirdparty%2Fsqlite.git Fix the OP_OpenEphemeral opcode in the bytecode engine so that if it is called a second or subsequent time, it merely clears the existing table rather than creating a new one. Proposed fix for ticket [d0866b26f83e9c55e30de0821f5d]. FossilOrigin-Name: 4678cb1044f0b4dc813e48f3bd0f85240a66e2ecf8763280d66726cc031c93a7 --- diff --git a/manifest b/manifest index ea6a1973e7..aaef2f2dde 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Additional\ssmall\sperformance\sincrease\sand\ssize\sreduction\sto\sthe\nsqlite3VdbeMakeLabel()\smechanism. -D 2018-12-29T14:23:22.316 +C Fix\sthe\sOP_OpenEphemeral\sopcode\sin\sthe\sbytecode\sengine\sso\sthat\sif\sit\sis\scalled\na\ssecond\sor\ssubsequent\stime,\sit\smerely\sclears\sthe\sexisting\stable\srather\sthan\ncreating\sa\snew\sone.\s\sProposed\sfix\sfor\sticket\s[d0866b26f83e9c55e30de0821f5d]. +D 2018-12-31T16:36:42.338 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in d8b254f8bb81bab43c340d70d17dc3babab40fcc8a348c8255881f780a45fee6 @@ -581,7 +581,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 3ffe64ecfc94b7528c5d7bdb1c3a19d72fec63f2aa846e3b90f8de5dbbddf5aa -F src/vdbe.c 8869a60f4b910c0f6d4ae0f0e23b7a835cae7ed67aa0ce2053d1bbe3e9facc53 +F src/vdbe.c 0321eb484160353d48accd3e67e06191173c6caa5f9995314021159017a5678b F src/vdbe.h b61a6f4f23ca4f5e789f4fc9d55acd4570d50d3288457651e501d839f5167c1f F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4 @@ -1666,7 +1666,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test a96a80bd6c5cc0e4bacbd3948223604e4b2745e37909a70d09c05f5ef6f84266 +F test/window1.test 148552f6331a1b9fbdc034ee1b46233cf52b58b98936ca2e74c9d5eba653b2ba F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 @@ -1795,7 +1795,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4a0929ac76d8aa5dd65eac3b83d6bbf41e505e01d175ca0fb2b19ba02d439415 -R 03e098302f2e99c4f7d3aaa87549bd2b +P 1bdee199a71e0a6c247b85e72de9e3a3099b7179c33288735721facef3b96459 +R 2a9dff6dec1fd031ba98ddeee634566f U drh -Z c77cecf32a6a6d57b97fc21a20b9218b +Z f80234c4b191a7b9e8e4e0c806044597 diff --git a/manifest.uuid b/manifest.uuid index d26f72ee27..7213643de2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1bdee199a71e0a6c247b85e72de9e3a3099b7179c33288735721facef3b96459 \ No newline at end of file +4678cb1044f0b4dc813e48f3bd0f85240a66e2ecf8763280d66726cc031c93a7 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 26382bcd4d..1f4d569aec 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3628,6 +3628,9 @@ case OP_OpenDup: { ** the main database is read-only. The ephemeral ** table is deleted automatically when the cursor is closed. ** +** If the cursor P1 is already opened on an ephermal table, the table +** is cleared (all content is erased). +** ** P2 is the number of columns in the ephemeral table. ** The cursor points to a BTree table if P4==0 and to a BTree index ** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure @@ -3659,6 +3662,14 @@ case OP_OpenEphemeral: { SQLITE_OPEN_TRANSIENT_DB; assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); + pCx = p->apCsr[pOp->p1]; + if( pCx ){ + /* If the ephermeral table is already open, erase all existing content + ** so that the table is empty again, rather than creating a new table. */ + rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + if( rc ) goto abort_due_to_error; + break; + } pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; @@ -3675,18 +3686,19 @@ case OP_OpenEphemeral: { ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ - int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); + rc = sqlite3BtreeCreateTable(pCx->pBtx, (int*)&pCx->pgnoRoot, + BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ - assert( pgno==MASTER_ROOT+1 ); + assert( pCx->pgnoRoot==MASTER_ROOT+1 ); assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); - rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR, pKeyInfo, pCx->uc.pCursor); } pCx->isTable = 0; }else{ + pCx->pgnoRoot = MASTER_ROOT; rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR, 0, pCx->uc.pCursor); pCx->isTable = 1; diff --git a/test/window1.test b/test/window1.test index 87829fdfbb..3b8b1d05ad 100644 --- a/test/window1.test +++ b/test/window1.test @@ -620,4 +620,49 @@ do_execsql_test 14.1 { ); } {1 2 3} +# 2018-12-31 +# https://www.sqlite.org/src/info/d0866b26f83e9c55 +# Window function in correlated subquery causes assertion fault +# +do_catchsql_test 15.0 { + WITH t(id, parent) AS ( + SELECT CAST(1 AS INT), CAST(NULL AS INT) + UNION ALL + SELECT 2, NULL + UNION ALL + SELECT 3, 1 + UNION ALL + SELECT 4, 1 + UNION ALL + SELECT 5, 2 + UNION ALL + SELECT 6, 2 + ), q AS ( + SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn + FROM t + WHERE parent IS NULL + UNION ALL + SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn + FROM q + JOIN t + ON t.parent = q.id + ) + SELECT * + FROM q; +} {1 {cannot use window functions in recursive queries}} +do_execsql_test 15.1 { + DROP TABLE IF EXISTS t1; + DROP TABLE IF EXISTS t2; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES('a'), ('b'), ('c'); + CREATE TABLE t2(a, b); + INSERT INTO t2 VALUES('X', 1), ('X', 2), ('Y', 2), ('Y', 3); + SELECT x, ( + SELECT sum(b) + OVER (PARTITION BY a ROWS BETWEEN UNBOUNDED PRECEDING + AND UNBOUNDED FOLLOWING) + FROM t2 WHERE b