From: drh Date: Thu, 29 Oct 2009 13:48:10 +0000 (+0000) Subject: Reduce the memory required by prepared statements that use the IN operator X-Git-Tag: fts3-refactor~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e05c929b78dad21c2e1dbc64a264dd53609221c9;p=thirdparty%2Fsqlite.git Reduce the memory required by prepared statements that use the IN operator with a list on the right and an INTEGER PRIMARY KEY on the left. FossilOrigin-Name: e7984ad2f7e4be30e7198ebd6609a7f6177513e2 --- diff --git a/manifest b/manifest index 903732e643..3c6bc73c4f 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Minor\supdates\sand\scorrections\sto\scomments\sin\sbtreeInt.h.\s\sNo\schanges\sto\scode. -D 2009-10-27T18:06:10 +C Reduce\sthe\smemory\srequired\sby\sprepared\sstatements\sthat\suse\sthe\sIN\soperator\s\nwith\sa\slist\son\sthe\sright\sand\san\sINTEGER\sPRIMARY\sKEY\son\sthe\sleft. +D 2009-10-29T13:48:11 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a77dfde96ad86aafd3f71651a4333a104debe86a F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -117,7 +117,7 @@ F src/callback.c 10d237171472865f58fb07d515737238c9e06688 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638 F src/delete.c 308e300d599d2d11b838687e2cf7309d42f29a1a -F src/expr.c f14ffa54e4eea3909b1ac8d5f6d25fe053611804 +F src/expr.c 658002e35de61e9a769a3bc438cc457171cbab17 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606 @@ -208,7 +208,7 @@ F src/update.c 8e8535f66c32d946199cb1caad19646a97ead3a7 F src/utf.c 3586a6a2457c5c88b6816f6cda58a54e291883f8 F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35 F src/vacuum.c 48e1282bbd5eac4b461587c51658378658c00770 -F src/vdbe.c f0d6e7dbd4515758c188c9dd7025eb9dfcf021e0 +F src/vdbe.c a435ffcf6bfc7f14eb40998062ccbd7dfa482319 F src/vdbe.h 449323a21c02226790acb6189dae78af17b92b78 F src/vdbeInt.h 97312570b5104c445c45c63cc7d10c361c2a0fe5 F src/vdbeapi.c 44b5f387459d5faa158aa8d3a26967f0c8596efd @@ -764,14 +764,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2eeb6ed818dac240afe761b4e7c11e961255bf33 -R d1cfe6f9c1d4d6dcbf60d0dfcf814d18 +P ad949fa1acb4546fe4f2a448025579cc374dd8dd +R 3bb532253075d93fd9eb68f8cb42f41d U drh -Z 5b3dfb277529d56fb9e1836cd3b92185 +Z db24204c5eebb100574fed36b2374757 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFK5zaVoxKgR168RlERAmxbAJ4jYG7nZBNa+A4Ed1GgYuHDHE8EUwCfdfwx -nxiRyac8DB1G3t81x60tEbQ= -=mppP +iD8DBQFK6Z0eoxKgR168RlERAgR0AJ4oa9XQXZNp40kKyCy8jsoWfXPMEQCfVw3K +6uxwA5vxXmgknZSewTJmSyo= +=dwzc -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 97ef2b73cb..5df4c90a31 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ad949fa1acb4546fe4f2a448025579cc374dd8dd \ No newline at end of file +e7984ad2f7e4be30e7198ebd6609a7f6177513e2 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index f592fc75a9..1ac37e0b7e 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1602,6 +1602,7 @@ void sqlite3CodeSubselect( sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; + int iValToIns; /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure @@ -1614,14 +1615,19 @@ void sqlite3CodeSubselect( } /* Evaluate the expression and insert it into the temp table */ - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - if( isRowid ){ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ + sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); + if( isRowid ){ + sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, + sqlite3VdbeCurrentAddr(v)+2); + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + } } } sqlite3ReleaseTempReg(pParse, r1); @@ -2875,6 +2881,7 @@ static int isAppropriateForFactoring(Expr *p){ static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ + case TK_IN: case TK_REGISTER: { return WRC_Prune; } diff --git a/src/vdbe.c b/src/vdbe.c index 6847b9027e..3e316fc684 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3758,7 +3758,13 @@ case OP_NewRowid: { /* out2-prerelease */ ** This instruction only works on tables. The equivalent instruction ** for indices is OP_IdxInsert. */ -case OP_Insert: { +/* Opcode: InsertInt P1 P2 P3 P4 P5 +** +** This works exactly like OP_Insert except that the key is the +** integer value P3, not the value of the integer stored in register P3. +*/ +case OP_Insert: +case OP_InsertInt: { Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ i64 iKey; /* The integer ROWID or key for the record to be inserted */ @@ -3770,20 +3776,26 @@ case OP_Insert: { int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ pData = &p->aMem[pOp->p2]; - pKey = &p->aMem[pOp->p3]; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); assert( pC->pseudoTableReg==0 ); - assert( pKey->flags & MEM_Int ); assert( pC->isTable ); REGISTER_TRACE(pOp->p2, pData); - REGISTER_TRACE(pOp->p3, pKey); - iKey = pKey->u.i; + if( pOp->opcode==OP_Insert ){ + pKey = &p->aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + REGISTER_TRACE(pOp->p3, pKey); + iKey = pKey->u.i; + }else{ + assert( pOp->opcode==OP_InsertInt ); + iKey = pOp->p3; + } + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey; if( pData->flags & MEM_Null ){ pData->z = 0; pData->n = 0;