-C Removed\sthe\sdirect\sbtree\stests\s-\spart\sof\sthe\songoing\seffort\sto\stest\sby\ncalling\sonly\spublic\sinterfaces.\s\sModify\sthe\ssqlite3VdbeRecordCompare\ninterface\sto\sused\sa\spre-parsed\ssecond\skey\s-\sresulting\sin\sa\s13%\nperformance\simprovement\son\sspeed1p.test.\s(CVS\s4911)
-D 2008-03-25T00:22:21
+C Use\sa\svdbe\smemory\scell\sto\sallocate\sthe\sspace\srequired\sfor\svdbe\scursors.\s(CVS\s4912)
+D 2008-03-25T09:47:35
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F sqlite3.def a1be7b9a4b8b51ac41c6ff6e8e44a14ef66b338b
F sqlite3.pc.in 32b8a014799c2028c8e0c9cc5659718262fc493f
F src/alter.c b42d782906fc3b92c331efbe06e9389617b47ce7
-F src/analyze.c a78ac494668581fe7f54ee63700815bb0ea34261
+F src/analyze.c 9ee63497ee720728abe630d169ab91323ac7519c
F src/attach.c bdc75e759ca25a16f4dc7fbdbc6d37ad2561bb24
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
-F src/btree.c 984962aa403be49d79784f01cc9887d16cd841ed
-F src/btree.h ca065a5910e6dd3b91b88ff9d729450a8b8eda1f
+F src/btree.c 5e3f25567d0d7228d151620637c3df9243ab324e
+F src/btree.h e02869e1e7753ad5b3c7cb7852e952c95c2e609a
F src/btreeInt.h c2deca3e778e2a1e6196343b8087a868f4faa19a
-F src/build.c 31ed5af4e8ac40c30bb0f88d7fec75e72cc16e0e
+F src/build.c d0715b3454b140cb405412e3029ec7c0fb434efd
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
-F src/delete.c 217cd5559e00bb135dc626d4ea4ac713604729e8
+F src/delete.c 526b783b71b9885b201d74720d44a386b971dc01
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 8758d120f03f5856b594724732e42497efe00731
+F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88
F src/fault.c c28478c7190daef16be09d261c5461638b4d686c
F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe
F src/hash.c 53655c312280211444bfe23af6490a460aec2980
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 358c80592c20a61a8d5b4a127215b5e25de652f4
+F src/insert.c c491fbd4f852f0ba82e26b4aad279b2611c51e94
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 8267890e6a0a71f13b680794520999c642299081
F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc
F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2
-F src/prepare.c f7fc2eb7418dcaa63e22b66c5ecf478e658ecd8f
+F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
-F src/select.c 35063b078beafe9aa35344a8ce039210920d7fea
+F src/select.c c06849a0d0ad408fbdd8180439176e94aae43e56
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335
F src/tclsqlite.c d42912617d4734b8f9195416badf5b27e512ded2
F src/test1.c 342a2628310fa709074d979e695a28a3bb570834
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
-F src/test3.c 9bf750645412effca0b2567b8b833e1e91377b47
+F src/test3.c 31027a4a190d2f3c1e479ea2d750e696160bbf04
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05
F src/test_func.c 9e9b33ff083b65da91c389cece903bc32de06f01
F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
-F src/test_malloc.c 52d8d7003c0b2183fd67de45c8b64ee7eb2656ea
+F src/test_malloc.c eedcc63c9f3111f2ebf6137b117e5644b3bb4c5d
F src/test_md5.c bca40b727c57462ddb415e57c5323445a1bb1a40
F src/test_onefile.c 2fea6d22f13f5f286356c80c77ffd41f995f2b7a
F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c 13113f94bd1c15dea9e922f08b10f3eee6863474
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
-F src/update.c d2c59643af98f966c2a04d392463089b715ca18f
+F src/update.c 2aefd3c9277792e9fa2414dfe14202119fa49fe7
F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
-F src/vdbe.c d81771c67e67f9a25af1d53e5c22299becef1322
+F src/vdbe.c bdcbf54cf944a99b004e87a523736dd326fa34be
F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f
F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919
F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817
-F src/vdbeaux.c f3ee532bfdf191f0d2a8c4d1a50816cdd1a235d2
-F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d
+F src/vdbeaux.c c071014d81c1d4b2c381247c16a3e86182951e51
+F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
F src/vdbemem.c 67662aac917b627356262f9501591206db2a8845
F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
-F src/where.c 78d6689d7154d8d41c1a913e17bce9a320981653
+F src/where.c f18bac2f87c965811727be1be05deeaf5229fcd0
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/all.test d12210212bada2bde6d5aeb90969b86c1aa977d2
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 1ed695f560a58786f2a8467c601f281c67034fd4
-R 4b7a149e165aca7212e2405c0ae3196c
-U drh
-Z f27434cb523b0af2e9a84163450beba5
+P 0e1d84f2f456e7680bb667266745b629ddf3605f
+R 284330e7bdf139254e19bec086a6e3bc
+U danielk1977
+Z a0d2b0847845caa52b53bf4be4058830
-0e1d84f2f456e7680bb667266745b629ddf3605f
\ No newline at end of file
+047153648155654b0cd70b811935209d2e21776c
\ No newline at end of file
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.41 2008/01/25 15:04:49 drh Exp $
+** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
if( !createStat1 ){
sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
}
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 3);
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb);
sqlite3VdbeChangeP5(v, createStat1);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3);
}
/*
/* Open a cursor to the index to be analyzed
*/
assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
+ nCol = pIdx->nColumn;
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nCol+1);
sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
(char *)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
- nCol = pIdx->nColumn;
regFields = iMem+nCol*2;
regTemp = regRowid = regCol = regFields+3;
regRec = regCol+1;
if( regRec>pParse->nMem ){
pParse->nMem = regRec;
}
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1);
/* Memory cells are used as follows:
**
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.443 2008/03/25 00:22:21 drh Exp $
+** $Id: btree.c,v 1.444 2008/03/25 09:47:35 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** will not work correctly.
*/
static int btreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- struct KeyInfo *pKeyInfo, /* First arg to comparison function */
- BtCursor **ppCur /* Write new cursor here */
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
){
int rc;
- BtCursor *pCur;
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
- *ppCur = 0;
if( wrFlag ){
if( pBt->readOnly ){
return SQLITE_READONLY;
return SQLITE_READONLY;
}
}
- pCur = sqlite3MallocZero( sizeof(*pCur) );
- if( pCur==0 ){
- rc = SQLITE_NOMEM;
- goto create_cursor_exception;
- }
pCur->pgnoRoot = (Pgno)iTable;
if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){
rc = SQLITE_EMPTY;
}
pBt->pCursor = pCur;
pCur->eState = CURSOR_INVALID;
- *ppCur = pCur;
return SQLITE_OK;
create_cursor_exception:
if( pCur ){
releasePage(pCur->pPage);
- sqlite3_free(pCur);
}
unlockBtreeIfUnused(pBt);
return rc;
}
int sqlite3BtreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
- BtCursor **ppCur /* Write new cursor here */
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
+ BtCursor *pCur /* Write new cursor here */
){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, ppCur);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
return rc;
}
+int sqlite3BtreeCursorSize(){
+ return sizeof(BtCursor);
+}
+
/*
** when the last cursor is closed.
*/
int sqlite3BtreeCloseCursor(BtCursor *pCur){
- BtShared *pBt = pCur->pBt;
Btree *pBtree = pCur->pBtree;
-
- sqlite3BtreeEnter(pBtree);
- pBt->db = pBtree->db;
- clearCursorPosition(pCur);
- if( pCur->pPrev ){
- pCur->pPrev->pNext = pCur->pNext;
- }else{
- pBt->pCursor = pCur->pNext;
- }
- if( pCur->pNext ){
- pCur->pNext->pPrev = pCur->pPrev;
+ if( pBtree ){
+ BtShared *pBt = pCur->pBt;
+ sqlite3BtreeEnter(pBtree);
+ pBt->db = pBtree->db;
+ clearCursorPosition(pCur);
+ if( pCur->pPrev ){
+ pCur->pPrev->pNext = pCur->pNext;
+ }else{
+ pBt->pCursor = pCur->pNext;
+ }
+ if( pCur->pNext ){
+ pCur->pNext->pPrev = pCur->pPrev;
+ }
+ releasePage(pCur->pPage);
+ unlockBtreeIfUnused(pBt);
+ invalidateOverflowCache(pCur);
+ /* sqlite3_free(pCur); */
+ sqlite3BtreeLeave(pBtree);
}
- releasePage(pCur->pPage);
- unlockBtreeIfUnused(pBt);
- invalidateOverflowCache(pCur);
- sqlite3_free(pCur);
- sqlite3BtreeLeave(pBtree);
return SQLITE_OK;
}
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.95 2008/03/25 00:22:21 drh Exp $
+** @(#) $Id: btree.h,v 1.96 2008/03/25 09:47:35 danielk1977 Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
void sqlite3BtreeTripAllCursors(Btree*, int);
int sqlite3BtreeCursor(
- Btree*, /* BTree containing table to open */
- int iTable, /* Index of root page */
- int wrFlag, /* 1 for writing. 0 for read-only */
- struct KeyInfo*, /* First argument to compare function */
- BtCursor **ppCursor /* Returned cursor */
+ Btree*, /* BTree containing table to open */
+ int iTable, /* Index of root page */
+ int wrFlag, /* 1 for writing. 0 for read-only */
+ struct KeyInfo*, /* First argument to compare function */
+ BtCursor *pCursor /* Space to write cursor structure */
);
+int sqlite3BtreeCursorSize();
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes);
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.475 2008/03/20 14:03:29 drh Exp $
+** $Id: build.c,v 1.476 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */
sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */
}
/*
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.162 2008/03/19 20:42:14 drh Exp $
+** $Id: delete.c,v 1.163 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
VdbeComment((v, "%s", pTab->zName));
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iCur, pTab->nCol);
}
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( triggers_exist ){
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol);
}
/* Delete every item whose key was written to the list during the
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.356 2008/03/20 16:30:18 drh Exp $
+** $Id: expr.c,v 1.357 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
eType = IN_INDEX_INDEX;
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iTab, pIdx->nColumn);
sqlite3VdbeJumpHere(v, iAddr);
}
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp1(v, OP_OpenEphemeral, pExpr->iTable);
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, pExpr->iTable, 1);
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.232 2008/03/19 20:42:14 drh Exp $
+** $Id: insert.c,v 1.233 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
** back up and execute the SELECT code above.
*/
sqlite3VdbeJumpHere(v, iInitCode);
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, srcTab, nColumn);
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
}else{
/* Open the temp table for FOR EACH ROW triggers
*/
if( triggers_exist ){
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol);
}
/* Initialize the count of rows to be inserted
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.81 2008/03/25 00:22:21 drh Exp $
+** $Id: prepare.c,v 1.82 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
}
return SQLITE_OK;
}
+ curMain = sqlite3MallocZero(sqlite3BtreeCursorSize());
+ if( !curMain ){
+ rc = SQLITE_NOMEM;
+ goto error_out;
+ }
sqlite3BtreeEnter(pDb->pBt);
- rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, &curMain);
+ rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- goto error_out;
+ goto leave_error_out;
}
/* Get the database meta information.
}
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
- sqlite3BtreeCloseCursor(curMain);
- sqlite3BtreeLeave(pDb->pBt);
- goto error_out;
+ goto leave_error_out;
}
}else{
memset(meta, 0, sizeof(meta));
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( meta[4]!=ENC(db) ){
- sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto leave_error_out;
}
}
}else{
pDb->pSchema->file_format = 1;
}
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
- sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto leave_error_out;
}
/* Ticket #2804: When we open a database in the newer file format,
sqlite3AnalysisLoad(db, iDb);
}
#endif
- sqlite3BtreeCloseCursor(curMain);
}
if( db->mallocFailed ){
/* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
}
+
+ /* Jump here for an error that occurs after successfully allocating
+ ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
+ ** before that point, jump to error_out.
+ */
+leave_error_out:
+ sqlite3BtreeCloseCursor(curMain);
+ sqlite3_free(curMain);
sqlite3BtreeLeave(pDb->pBt);
error_out:
int cookie;
int allOk = 1;
- assert( sqlite3_mutex_held(db->mutex) );
- for(iDb=0; allOk && iDb<db->nDb; iDb++){
- Btree *pBt;
- pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) continue;
- rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, &curTemp);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
- if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
- allOk = 0;
+ curTemp = (BtCursor *)sqlite3_malloc(sqlite3BtreeCursorSize());
+ if( curTemp ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(iDb=0; allOk && iDb<db->nDb; iDb++){
+ Btree *pBt;
+ pBt = db->aDb[iDb].pBt;
+ if( pBt==0 ) continue;
+ memset(curTemp, 0, sqlite3BtreeCursorSize());
+ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
+ if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+ allOk = 0;
+ }
+ sqlite3BtreeCloseCursor(curTemp);
+ }
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ db->mallocFailed = 1;
}
- sqlite3BtreeCloseCursor(curTemp);
- }
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- db->mallocFailed = 1;
}
+ sqlite3_free(curTemp);
+ }else{
+ allOk = 0;
+ db->mallocFailed = 1;
}
+
return allOk;
}
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.417 2008/03/22 01:07:18 drh Exp $
+** $Id: select.c,v 1.418 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
iTab = pOrderBy->iECursor;
if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
pseudoTab = pParse->nTab++;
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn);
}
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
codeOffset(v, p, cont);
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
- addrSortingIdx =
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
- sAggInfo.nSortingColumn, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
/* Initialize memory locations used by GROUP BY aggregate processing
*/
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test3.c,v 1.92 2008/03/25 00:22:21 drh Exp $
+** $Id: test3.c,v 1.93 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
pBt = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
+ pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
+ memset(pCur, 0, sqlite3BtreeCursorSize());
sqlite3BtreeEnter(pBt);
- rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, &pCur);
+ rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
sqlite3BtreeLeave(pBt);
if( rc ){
+ ckfree((char *)pCur);
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sqlite3BtreeEnter(pBt);
rc = sqlite3BtreeCloseCursor(pCur);
sqlite3BtreeLeave(pBt);
+ ckfree((char *)pCur);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
-** $Id: test_malloc.c,v 1.18 2008/03/21 14:22:44 danielk1977 Exp $
+** $Id: test_malloc.c,v 1.19 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
return TCL_OK;
}
-#define MALLOC_LOG_FRAMES 5
+#define MALLOC_LOG_FRAMES 10
static Tcl_HashTable aMallocLog;
static int mallocLogEnabled = 0;
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.172 2008/03/19 20:42:14 drh Exp $
+** $Id: update.c,v 1.173 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
/* Create pseudo-tables for NEW and OLD
*/
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, oldIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol);
iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
addr = sqlite3VdbeMakeLabel(v);
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.716 2008/03/25 00:22:21 drh Exp $
+** $Id: vdbe.c,v 1.717 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
** Allocate cursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
-static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
- Cursor *pCx;
+static Cursor *allocateCursor(
+ Vdbe *p,
+ int iCur,
+ Op *pOp,
+ int iDb,
+ int isBtreeCursor
+){
+ /* Find the memory cell that will be used to store the blob of memory
+ ** required for this Cursor structure. It is convenient to use a
+ ** vdbe memory cell to manage the memory allocation required for a
+ ** Cursor structure for the following reasons:
+ **
+ ** * Sometimes cursor numbers are used for a couple of different
+ ** purposes in a vdbe program. The different uses might require
+ ** different sized allocations. Memory cells provide growable
+ ** allocations.
+ **
+ ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can
+ ** be freed lazily via the sqlite3_release_memory() API. This
+ ** minimizes the number of malloc calls made by the system.
+ **
+ ** Memory cells for cursors are allocated at the top of the address
+ ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for
+ ** cursor 1 is managed by memory cell (p->nMem-1), etc.
+ */
+ Mem *pMem = &p->aMem[p->nMem-iCur];
+
+ Cursor *pCx = 0;
+ /* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains
+ ** the number of fields in the records contained in the table or
+ ** index being opened. Use this to reserve space for the
+ ** Cursor.aType[] array.
+ */
+ int nField = 0;
+ if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){
+ nField = pOp->p2;
+ }
+
+
+ int nByte =
+ sizeof(Cursor) +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0) +
+ 2*nField*sizeof(u32);
+
assert( iCur<p->nCursor );
if( p->apCsr[iCur] ){
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
+ p->apCsr[iCur] = 0;
}
- p->apCsr[iCur] = pCx = sqlite3MallocZero( sizeof(Cursor) );
- if( pCx ){
+ if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ p->apCsr[iCur] = pCx = (Cursor *)pMem->z;
+ memset(pMem->z, 0, nByte);
pCx->iDb = iDb;
+ pCx->nField = nField;
+ if( nField ){
+ pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)];
+ }
+ if( isBtreeCursor ){
+ pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)];
+ }
}
return pCx;
}
break;
}
-/* Opcode: SetNumColumns P1 P2 * * *
+/* Opcode: SetNumColumns * P2 * * *
+**
+** This opcode sets the number of columns for the cursor opened by the
+** following instruction to P2.
**
-** Before the OP_Column opcode can be executed on a cursor, this
-** opcode must be called to set the number of fields in the table.
+** An OP_SetNumColumns is only useful if it occurs immediately before
+** one of the following opcodes:
**
-** This opcode sets the number of columns for cursor P1 to P2.
+** OpenRead
+** OpenWrite
+** OpenPseudo
**
-** If OP_KeyAsData is to be applied to cursor P1, it must be executed
-** before this op-code.
+** If the OP_Column opcode is to be executed on a cursor, then
+** this opcode must be present immediately before the opcode that
+** opens the cursor.
*/
case OP_SetNumColumns: {
- Cursor *pC;
- assert( (pOp->p1)<p->nCursor );
- assert( p->apCsr[pOp->p1]!=0 );
- pC = p->apCsr[pOp->p1];
- pC->nField = pOp->p2;
break;
}
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
+ aType = pC->aType;
if( pC->cacheStatus==p->cacheCtr ){
- aType = pC->aType;
aOffset = pC->aOffset;
}else{
u8 *zIdx; /* Index into header */
int szHdrSz; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
- aType = pC->aType;
- if( aType==0 ){
- pC->aType = aType = sqlite3DbMallocRaw(db, 2*nField*sizeof(aType) );
- }
- if( aType==0 ){
- goto no_mem;
- }
+ assert(aType);
pC->aOffset = aOffset = &aType[nField];
pC->payloadSize = payloadSize;
pC->cacheStatus = p->cacheCtr;
assert( p2>=2 );
}
assert( i>=0 );
- pCur = allocateCursor(p, i, iDb);
+ pCur = allocateCursor(p, i, &pOp[-1], iDb, 1);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
- rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, &pCur->pCursor);
+ rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
case SQLITE_EMPTY: {
pCur->isTable = pOp->p4type!=P4_KEYINFO;
pCur->isIndex = !pCur->isTable;
+ pCur->pCursor = 0;
rc = SQLITE_OK;
break;
}
SQLITE_OPEN_TRANSIENT_DB;
assert( i>=0 );
- pCx = allocateCursor(p, i, -1);
+ pCx = allocateCursor(p, i, pOp, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags,
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
- (KeyInfo*)pOp->p4.z, &pCx->pCursor);
+ (KeyInfo*)pOp->p4.z, pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, &pCx->pCursor);
+ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
- pCx->nField = pOp->p2;
pCx->isIndex = !pCx->isTable;
break;
}
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
- pCx = allocateCursor(p, i, -1);
+ pCx = allocateCursor(p, i, &pOp[-1], -1, 0);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
pVtabCursor->pVtab = pVtab;
/* Initialise vdbe cursor object */
- pCur = allocateCursor(p, pOp->p1, -1);
+ pCur = allocateCursor(p, pOp->p1, &pOp[-1], -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
pCur->pModule = pVtabCursor->pVtab->pModule;
*/
p->magic = VDBE_MAGIC_RUN;
+ /* For each cursor required, also allocate a memory cell. Memory
+ ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
+ ** the vdbe program. Instead they are used to allocate space for
+ ** Cursor/BtCursor structures. The blob of memory associated with
+ ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
+ ** stores the blob of memory associated with cursor 1, etc.
+ **
+ ** See also: allocateCursor().
+ */
+ nMem += nCursor;
+
/*
** Allocation space for registers.
*/
}
/*
-** Close a VDBE cursor and release all the resources that cursor happens
-** to hold.
+** Close a VDBE cursor and release all the resources that cursor
+** happens to hold.
*/
void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
if( pCx==0 ){
}
#endif
sqlite3_free(pCx->pData);
- sqlite3_free(pCx->aType);
- sqlite3_free(pCx);
+ memset(pCx, 0, sizeof(Cursor));
+ /* sqlite3_free(pCx->aType); */
+ /* sqlite3_free(pCx); */
}
/*
for(i=1; i<=p->nMem; i++){
MemSetTypeFlag(&p->aMem[i], MEM_Null);
}
+
releaseMemArray(&p->aMem[1], p->nMem);
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
**
** This file contains code used to implement incremental BLOB I/O.
**
-** $Id: vdbeblob.c,v 1.20 2008/01/25 15:04:50 drh Exp $
+** $Id: vdbeblob.c,v 1.21 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
/* One of the following two instructions is replaced by an
** OP_Noop before exection.
*/
- {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
- {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
+ {OP_SetNumColumns, 0, 0, 0}, /* 2: Num cols for cursor */
+ {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
{OP_SetNumColumns, 0, 0, 0}, /* 4: Num cols for cursor */
-
- {OP_Variable, 1, 1, 0}, /* 5: Push the rowid to the stack */
- {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
- {OP_Column, 0, 0, 1}, /* 7 */
- {OP_ResultRow, 1, 0, 0}, /* 8 */
- {OP_Close, 0, 0, 0}, /* 9 */
- {OP_Halt, 0, 0, 0}, /* 10 */
+ {OP_OpenWrite, 0, 0, 0}, /* 5: Open cursor 0 for read/write */
+
+ {OP_Variable, 1, 1, 0}, /* 6: Push the rowid to the stack */
+ {OP_NotExists, 0, 10, 1}, /* 7: Seek the cursor */
+ {OP_Column, 0, 0, 1}, /* 8 */
+ {OP_ResultRow, 1, 0, 0}, /* 9 */
+ {OP_Close, 0, 0, 0}, /* 10 */
+ {OP_Halt, 0, 0, 0}, /* 11 */
};
Vdbe *v = 0;
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum.
*/
- sqlite3VdbeChangeToNoop(v, (flags ? 2 : 3), 1);
- sqlite3VdbeChangeP2(v, (flags ? 3 : 2), pTab->tnum);
- sqlite3VdbeChangeP3(v, (flags ? 3 : 2), iDb);
+ sqlite3VdbeChangeToNoop(v, (flags ? 3 : 5), 1);
+ sqlite3VdbeChangeP2(v, (flags ? 5 : 3), pTab->tnum);
+ sqlite3VdbeChangeP3(v, (flags ? 5 : 3), iDb);
/* Configure the OP_SetNumColumns. Configure the cursor to
** think that the table has one more column than it really
** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
- sqlite3VdbeChangeP2(v, 4, pTab->nCol+1);
+ sqlite3VdbeChangeP2(v, flags ? 4 : 2, pTab->nCol+1);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0);
}
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.290 2008/03/17 17:08:33 drh Exp $
+** $Id: where.c,v 1.291 2008/03/25 09:47:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n);
+ sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-2, n);
assert( n<=pTab->nCol );
}
}else{
if( (pIx = pLevel->pIdx)!=0 ){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
assert( pIx->pSchema==pTab->pSchema );
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIx->nColumn+1);
sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb,
(char*)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIx->zName));
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
}
sqlite3CodeVerifySchema(pParse, iDb);
}