-C Change\sthe\sname\sof\sthe\ssanity_check\sPRAGMA\sto\s"integrity_check"\sand\smake\nit\savailable\son\sall\scompiles.\s(CVS\s381)
-D 2002-02-19T13:39:21
+C Optimize\ssimple\smin()\sand\smax()\squeries.\s(CVS\s382)
+D 2002-02-19T15:00:07
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360
F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
-F src/btree.c 715209d8fff117d2e3024134c5b626f440fb0395
-F src/btree.h 9fd16f33b9f2efe733fecff7ca000d2950a74d9f
+F src/btree.c 8256ea416850fbd2af0ae50779b1a4b604de13c2
+F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
F src/build.c 088acf87a92b00edda1206ccafac3518660b1b3b
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
F src/expr.c 7aff65ea0732b07d36925087ad611019103ad69a
F src/parse.y b82278917959eefd05bd08c90e07a4fa5917ea51
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
-F src/select.c d2bbaf4cba97b4c40503d0dc47e8b729e7088e0b
+F src/select.c 6dadbd3ba1e86334c9af321b48f6e3df1992f602
F src/shell.c c102dfe388c7618a668c944ff157c49cb48f28e3
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
F src/tokenize.c 9e98f94469694a763992860596137e78dbae0cc0
F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
F src/util.c f31f3d6198a0d1296a16f5a6ceec423a932cbbf6
-F src/vdbe.c 3c788341b581c9381ab2ecd4868041ed57ff27ad
-F src/vdbe.h 20a662572485329cb0a6b648bf7c8cb6baec401d
+F src/vdbe.c 2b03a7d39f05321e5570373cb2f3734c3cf86b70
+F src/vdbe.h b4d35e159fbb80a74728b4a96e5b789fffce6f57
F src/where.c f79bc3179379b46b131a67ab10713779368dceee
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 72c5a92aa6e3ae712af152cff8d1dc5b997b538e
-R 50515068ff6057399f03cf57fa91cbb8
+P c6e9048e66c8d8e2d5f6c62aa724eef3e9d9f572
+R 41f437c3e65a91e5a2a52b6609362036
U drh
-Z 763c5eb79aff590e79bd0703f9429a9c
+Z ee034e966e6d17b9655294654ff0765f
-c6e9048e66c8d8e2d5f6c62aa724eef3e9d9f572
\ No newline at end of file
+cc5abfe392bdb8c3ed00e0610bc2b41851bfc9d7
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.53 2002/02/19 13:39:22 drh Exp $
+** $Id: btree.c,v 1.54 2002/02/19 15:00:07 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
return rc;
}
+/* Move the cursor to the last entry in the table. Return SQLITE_OK
+** on success. Set *pRes to 0 if the cursor actually points to something
+** or set *pRes to 1 if the table is empty and there is no first element.
+*/
+int sqliteBtreeLast(BtCursor *pCur, int *pRes){
+ int rc;
+ Pgno pgno;
+ if( pCur->pPage==0 ) return SQLITE_ABORT;
+ rc = moveToRoot(pCur);
+ if( rc ) return rc;
+ if( pCur->pPage->nCell==0 ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ *pRes = 0;
+ while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
+ rc = moveToChild(pCur, pgno);
+ if( rc ) return rc;
+ }
+ pCur->idx = pCur->pPage->nCell-1;
+ pCur->bSkipNext = 0;
+ return rc;
+}
+
/* Move the cursor so that it points to an entry near pKey.
** Return a success code.
**
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.23 2002/02/19 13:39:22 drh Exp $
+** @(#) $Id: btree.h,v 1.24 2002/02/19 15:00:08 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int sqliteBtreeFirst(BtCursor*, int *pRes);
+int sqliteBtreeLast(BtCursor*, int *pRes);
int sqliteBtreeNext(BtCursor*, int *pRes);
int sqliteBtreeKeySize(BtCursor*, int *pSize);
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.61 2002/02/18 03:21:46 drh Exp $
+** $Id: select.c,v 1.62 2002/02/19 15:00:08 drh Exp $
*/
#include "sqliteInt.h"
return 0;
}
+/*
+** Analyze the SELECT statement passed in as an argument to see if it
+** is a simple min() or max() query. If it is and this query can be
+** satisfied using a single seek to the beginning or end of an index,
+** then generate the code for this SELECT return 1. If this is not a
+** simple min() or max() query, then return 0;
+**
+** A simply min() or max() query looks like this:
+**
+** SELECT min(a) FROM table;
+** SELECT max(a) FROM table;
+**
+** The query may have only a single table in its FROM argument. There
+** can be no GROUP BY or HAVING or WHERE clauses. The result set must
+** be the min() or max() of a single column of the table. The column
+** in the min() or max() function must be indexed.
+**
+** The parameters to this routine are the same as for sqliteSelect().
+** See the header comment on that routine for additional information.
+*/
+static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
+ Expr *pExpr;
+ int iCol;
+ Table *pTab;
+ Index *pIdx;
+ int base;
+ Vdbe *v;
+ int openOp;
+ int seekOp;
+ int cont;
+ ExprList eList;
+ struct ExprList_item eListItem;
+
+ /* Check to see if this query is a simple min() or max() query. Return
+ ** zero if it is not.
+ */
+ if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
+ if( p->pSrc->nId!=1 ) return 0;
+ if( p->pEList->nExpr!=1 ) return 0;
+ pExpr = p->pEList->a[0].pExpr;
+ if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
+ if( pExpr->pList==0 || pExpr->pList->nExpr!=1 ) return 0;
+ if( pExpr->iColumn!=FN_Min && pExpr->iColumn!=FN_Max ) return 0;
+ seekOp = pExpr->iColumn==FN_Min ? OP_Rewind : OP_Last;
+ pExpr = pExpr->pList->a[0].pExpr;
+ if( pExpr->op!=TK_COLUMN ) return 0;
+ iCol = pExpr->iColumn;
+ pTab = p->pSrc->a[0].pTab;
+
+ /* If we get to here, it means the query is of the correct form.
+ ** Check to make sure we have an index.
+ */
+ if( iCol<0 ){
+ pIdx = 0;
+ }else{
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pIdx->nColumn>=1 );
+ if( pIdx->aiColumn[0]==iCol ) break;
+ }
+ if( pIdx==0 ) return 0;
+ }
+
+ /* Identify column names if we will be using in the callback. This
+ ** step is skipped if the output is going to a table or a memory cell.
+ */
+ v = sqliteGetVdbe(pParse);
+ if( v==0 ) return 0;
+ if( eDest==SRT_Callback ){
+ generateColumnNames(pParse, p->pSrc, p->pEList);
+ }
+
+ /* Begin generating code
+ */
+ base = pParse->nTab;
+ eList.nExpr = 1;
+ memset(&eListItem, 0, sizeof(eListItem));
+ eList.a = &eListItem;
+ eList.a[0].pExpr = pExpr;
+ openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
+ sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
+ if( pIdx==0 ){
+ sqliteVdbeAddOp(v, seekOp, base, 0);
+ }else{
+ sqliteVdbeAddOp(v, openOp, base+1, pIdx->tnum);
+ sqliteVdbeAddOp(v, seekOp, base+1, 0);
+ sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
+ sqliteVdbeAddOp(v, OP_Close, base+1, 0);
+ sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
+ }
+ cont = sqliteVdbeMakeLabel(v);
+ selectInnerLoop(pParse, &eList, base, 1, 0, -1, eDest, iParm, cont, cont);
+ sqliteVdbeResolveLabel(v, cont);
+ sqliteVdbeAddOp(v, OP_Close, base, 0);
+ return 1;
+}
+
/*
** Generate code for the given SELECT statement.
**
}
}
+ /* Check for the special case of a min() or max() function by itself
+ ** in the result set.
+ */
+ if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
+ goto select_end;
+ }
+
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.118 2002/02/19 13:39:23 drh Exp $
+** $Id: vdbe.c,v 1.119 2002/02/19 15:00:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
"Close", "MoveTo", "NewRecno", "PutIntKey",
"PutStrKey", "Distinct", "Found", "NotFound",
"IsUnique", "NotExists", "Delete", "Column",
- "KeyAsData", "Recno", "FullKey", "Rewind",
- "Next", "Destroy", "Clear", "CreateIndex",
- "CreateTable", "IntegrityCk", "IdxPut", "IdxDelete",
- "IdxRecno", "IdxGT", "IdxGE", "MemLoad",
- "MemStore", "ListWrite", "ListRewind", "ListRead",
- "ListReset", "SortPut", "SortMakeRec", "SortMakeKey",
- "Sort", "SortNext", "SortCallback", "SortReset",
- "FileOpen", "FileRead", "FileColumn", "AggReset",
- "AggFocus", "AggIncr", "AggNext", "AggSet",
- "AggGet", "SetInsert", "SetFound", "SetNotFound",
- "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey",
- "Goto", "If", "Halt", "ColumnCount",
- "ColumnName", "Callback", "NullCallback", "Integer",
- "String", "Pop", "Dup", "Pull",
- "Push", "MustBeInt", "Add", "AddImm",
- "Subtract", "Multiply", "Divide", "Remainder",
- "BitAnd", "BitOr", "BitNot", "ShiftLeft",
- "ShiftRight", "AbsValue", "Precision", "Min",
- "Max", "Like", "Glob", "Eq",
- "Ne", "Lt", "Le", "Gt",
- "Ge", "IsNull", "NotNull", "Negative",
- "And", "Or", "Not", "Concat",
- "Noop", "Strlen", "Substr", "Limit",
+ "KeyAsData", "Recno", "FullKey", "Last",
+ "Rewind", "Next", "Destroy", "Clear",
+ "CreateIndex", "CreateTable", "IntegrityCk", "IdxPut",
+ "IdxDelete", "IdxRecno", "IdxGT", "IdxGE",
+ "MemLoad", "MemStore", "ListWrite", "ListRewind",
+ "ListRead", "ListReset", "SortPut", "SortMakeRec",
+ "SortMakeKey", "Sort", "SortNext", "SortCallback",
+ "SortReset", "FileOpen", "FileRead", "FileColumn",
+ "AggReset", "AggFocus", "AggIncr", "AggNext",
+ "AggSet", "AggGet", "SetInsert", "SetFound",
+ "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey",
+ "IncrKey", "Goto", "If", "Halt",
+ "ColumnCount", "ColumnName", "Callback", "NullCallback",
+ "Integer", "String", "Pop", "Dup",
+ "Pull", "Push", "MustBeInt", "Add",
+ "AddImm", "Subtract", "Multiply", "Divide",
+ "Remainder", "BitAnd", "BitOr", "BitNot",
+ "ShiftLeft", "ShiftRight", "AbsValue", "Precision",
+ "Min", "Max", "Like", "Glob",
+ "Eq", "Ne", "Lt", "Le",
+ "Gt", "Ge", "IsNull", "NotNull",
+ "Negative", "And", "Or", "Not",
+ "Concat", "Noop", "Strlen", "Substr",
+ "Limit",
};
/*
/* Figure out how many bytes in the column data and where the column
** data begins.
*/
- if( payloadSize<256 ){
+ if( payloadSize==0 ){
+ aStack[tos].flags = STK_Null;
+ p->tos = tos;
+ break;
+ }else if( payloadSize<256 ){
idxWidth = 1;
}else if( payloadSize<65536 ){
idxWidth = 2;
break;
}
+/* Opcode: Last P1 P2 *
+**
+** The next use of the Recno or Column or Next instruction for P1
+** will refer to the last entry in the database table or index.
+** If the table or index is empty and P2>0, then jump immediately to P2.
+** If P2 is 0 or if the table or index is not empty, fall through
+** to the following instruction.
+*/
+case OP_Last: {
+ int i = pOp->p1;
+ BtCursor *pCrsr;
+
+ if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ int res;
+ sqliteBtreeLast(pCrsr, &res);
+ p->aCsr[i].atFirst = res==0;
+ if( res && pOp->p2>0 ){
+ pc = pOp->p2 - 1;
+ }
+ }
+ break;
+}
+
/* Opcode: Rewind P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.42 2002/02/19 13:39:23 drh Exp $
+** $Id: vdbe.h,v 1.43 2002/02/19 15:00:08 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#define OP_KeyAsData 25
#define OP_Recno 26
#define OP_FullKey 27
-#define OP_Rewind 28
-#define OP_Next 29
-
-#define OP_Destroy 30
-#define OP_Clear 31
-#define OP_CreateIndex 32
-#define OP_CreateTable 33
-#define OP_IntegrityCk 34
-
-#define OP_IdxPut 35
-#define OP_IdxDelete 36
-#define OP_IdxRecno 37
-#define OP_IdxGT 38
-#define OP_IdxGE 39
-
-#define OP_MemLoad 40
-#define OP_MemStore 41
-
-#define OP_ListWrite 42
-#define OP_ListRewind 43
-#define OP_ListRead 44
-#define OP_ListReset 45
-
-#define OP_SortPut 46
-#define OP_SortMakeRec 47
-#define OP_SortMakeKey 48
-#define OP_Sort 49
-#define OP_SortNext 50
-#define OP_SortCallback 51
-#define OP_SortReset 52
-
-#define OP_FileOpen 53
-#define OP_FileRead 54
-#define OP_FileColumn 55
-
-#define OP_AggReset 56
-#define OP_AggFocus 57
-#define OP_AggIncr 58
-#define OP_AggNext 59
-#define OP_AggSet 60
-#define OP_AggGet 61
-
-#define OP_SetInsert 62
-#define OP_SetFound 63
-#define OP_SetNotFound 64
-
-#define OP_MakeRecord 65
-#define OP_MakeKey 66
-#define OP_MakeIdxKey 67
-#define OP_IncrKey 68
-
-#define OP_Goto 69
-#define OP_If 70
-#define OP_Halt 71
-
-#define OP_ColumnCount 72
-#define OP_ColumnName 73
-#define OP_Callback 74
-#define OP_NullCallback 75
-
-#define OP_Integer 76
-#define OP_String 77
-#define OP_Pop 78
-#define OP_Dup 79
-#define OP_Pull 80
-#define OP_Push 81
-#define OP_MustBeInt 82
-
-#define OP_Add 83
-#define OP_AddImm 84
-#define OP_Subtract 85
-#define OP_Multiply 86
-#define OP_Divide 87
-#define OP_Remainder 88
-#define OP_BitAnd 89
-#define OP_BitOr 90
-#define OP_BitNot 91
-#define OP_ShiftLeft 92
-#define OP_ShiftRight 93
-#define OP_AbsValue 94
-#define OP_Precision 95
-#define OP_Min 96
-#define OP_Max 97
-#define OP_Like 98
-#define OP_Glob 99
-#define OP_Eq 100
-#define OP_Ne 101
-#define OP_Lt 102
-#define OP_Le 103
-#define OP_Gt 104
-#define OP_Ge 105
-#define OP_IsNull 106
-#define OP_NotNull 107
-#define OP_Negative 108
-#define OP_And 109
-#define OP_Or 110
-#define OP_Not 111
-#define OP_Concat 112
-#define OP_Noop 113
-
-#define OP_Strlen 114
-#define OP_Substr 115
-
-#define OP_Limit 116
-
-#define OP_MAX 116
+#define OP_Last 28
+#define OP_Rewind 29
+#define OP_Next 30
+
+#define OP_Destroy 31
+#define OP_Clear 32
+#define OP_CreateIndex 33
+#define OP_CreateTable 34
+#define OP_IntegrityCk 35
+
+#define OP_IdxPut 36
+#define OP_IdxDelete 37
+#define OP_IdxRecno 38
+#define OP_IdxGT 39
+#define OP_IdxGE 40
+
+#define OP_MemLoad 41
+#define OP_MemStore 42
+
+#define OP_ListWrite 43
+#define OP_ListRewind 44
+#define OP_ListRead 45
+#define OP_ListReset 46
+
+#define OP_SortPut 47
+#define OP_SortMakeRec 48
+#define OP_SortMakeKey 49
+#define OP_Sort 50
+#define OP_SortNext 51
+#define OP_SortCallback 52
+#define OP_SortReset 53
+
+#define OP_FileOpen 54
+#define OP_FileRead 55
+#define OP_FileColumn 56
+
+#define OP_AggReset 57
+#define OP_AggFocus 58
+#define OP_AggIncr 59
+#define OP_AggNext 60
+#define OP_AggSet 61
+#define OP_AggGet 62
+
+#define OP_SetInsert 63
+#define OP_SetFound 64
+#define OP_SetNotFound 65
+
+#define OP_MakeRecord 66
+#define OP_MakeKey 67
+#define OP_MakeIdxKey 68
+#define OP_IncrKey 69
+
+#define OP_Goto 70
+#define OP_If 71
+#define OP_Halt 72
+
+#define OP_ColumnCount 73
+#define OP_ColumnName 74
+#define OP_Callback 75
+#define OP_NullCallback 76
+
+#define OP_Integer 77
+#define OP_String 78
+#define OP_Pop 79
+#define OP_Dup 80
+#define OP_Pull 81
+#define OP_Push 82
+#define OP_MustBeInt 83
+
+#define OP_Add 84
+#define OP_AddImm 85
+#define OP_Subtract 86
+#define OP_Multiply 87
+#define OP_Divide 88
+#define OP_Remainder 89
+#define OP_BitAnd 90
+#define OP_BitOr 91
+#define OP_BitNot 92
+#define OP_ShiftLeft 93
+#define OP_ShiftRight 94
+#define OP_AbsValue 95
+#define OP_Precision 96
+#define OP_Min 97
+#define OP_Max 98
+#define OP_Like 99
+#define OP_Glob 100
+#define OP_Eq 101
+#define OP_Ne 102
+#define OP_Lt 103
+#define OP_Le 104
+#define OP_Gt 105
+#define OP_Ge 106
+#define OP_IsNull 107
+#define OP_NotNull 108
+#define OP_Negative 109
+#define OP_And 110
+#define OP_Or 111
+#define OP_Not 112
+#define OP_Concat 113
+#define OP_Noop 114
+
+#define OP_Strlen 115
+#define OP_Substr 116
+
+#define OP_Limit 117
+
+#define OP_MAX 117
/*
** Prototypes for the VDBE interface. See comments on the implementation