diff options
author | drh <drh@noemail.net> | 2004-10-04 13:19:23 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2004-10-04 13:19:23 +0000 |
commit | f2bc013c7011580ae976e5d7a978863b3f84a52d (patch) | |
tree | 8fdf6922f04914830682242910be66e9d5a58b26 | |
parent | 9c105bb990007c678ca28e63b764f8d0b557d5f9 (diff) | |
download | sqlite-f2bc013c7011580ae976e5d7a978863b3f84a52d.tar.gz sqlite-f2bc013c7011580ae976e5d7a978863b3f84a52d.zip |
Save about 800 bytes of code space by aligning TK_ and OP_ constants so that
we do not have to translate between them. (CVS 1998)
FossilOrigin-Name: 4c817e3f293a9c1365e632f7dc13ae440263332a
-rw-r--r-- | Makefile.in | 12 | ||||
-rw-r--r-- | main.mk | 12 | ||||
-rw-r--r-- | manifest | 23 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | mkopcodeh.awk | 45 | ||||
-rw-r--r-- | src/expr.c | 137 | ||||
-rw-r--r-- | src/parse.y | 12 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/vdbe.c | 90 |
9 files changed, 193 insertions, 144 deletions
diff --git a/Makefile.in b/Makefile.in index 75e8b0205..acb93b99e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -286,18 +286,16 @@ pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h opcodes.lo: opcodes.c $(LTCOMPILE) -c opcodes.c -opcodes.c: $(TOP)/src/vdbe.c +opcodes.c: opcodes.h echo '/* Automatically generated file. Do not edit */' >opcodes.c echo 'char *sqlite3OpcodeNames[] = { "???", ' >>opcodes.c - grep '^case OP_' $(TOP)/src/vdbe.c | \ - sed -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c + grep OP_ opcodes.h | sort -n +2 | \ + sed -e 's/^.*OP_/ "/' -e 's/ [ 0-9]*$$/", /' >>opcodes.c echo '};' >>opcodes.c -opcodes.h: $(TOP)/src/vdbe.h +opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk echo '/* Automatically generated file. Do not edit */' >opcodes.h - grep '^case OP_' $(TOP)/src/vdbe.c | \ - sed -e 's/://' | \ - awk '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h + cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >>opcodes.h os_mac.lo: $(TOP)/src/os_mac.c $(HDR) $(LTCOMPILE) $(THREADSAFE) -c $(TOP)/src/os_mac.c @@ -255,18 +255,16 @@ pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h opcodes.o: opcodes.c $(TCCX) -c opcodes.c -opcodes.c: $(TOP)/src/vdbe.c +opcodes.c: opcodes.h echo '/* Automatically generated file. Do not edit */' >opcodes.c echo 'char *sqlite3OpcodeNames[] = { "???", ' >>opcodes.c - grep '^case OP_' $(TOP)/src/vdbe.c | \ - sed -e 's/^.*OP_/ "/' -e 's/:.*$$/", /' >>opcodes.c + grep OP_ opcodes.h | sort -n +2 | \ + sed -e 's/^.*OP_/ "/' -e 's/ [ 0-9]*$$/", /' >>opcodes.c echo '};' >>opcodes.c -opcodes.h: $(TOP)/src/vdbe.h +opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk echo '/* Automatically generated file. Do not edit */' >opcodes.h - grep '^case OP_' $(TOP)/src/vdbe.c | \ - sed -e 's/://' | \ - awk '{printf "#define %-30s %3d\n", $$2, ++cnt}' >>opcodes.h + cat parse.h $(TOP)/src/vdbe.c | awk -f $(TOP)/mkopcodeh.awk >>opcodes.h os_mac.o: $(TOP)/src/os_mac.c $(HDR) $(TCCX) -c $(TOP)/src/os_mac.c @@ -1,6 +1,6 @@ -C Fixes\sto\sthe\sOsUnlock()\sinterface.\s\sCorrectly\sleave\sa\sSHARED\slock\sbehind\nwhen\srequested.\s\sHonor\sthe\serror\scode\sthat\sOsUnlock()\sreturns.\nTicket\s#913\sand\s#938.\s(CVS\s1997) -D 2004-10-02T20:38:28 -F Makefile.in abdeb5bd9d017822691884935c320037c33f6ee6 +C Save\sabout\s800\sbytes\sof\scode\sspace\sby\saligning\sTK_\sand\sOP_\sconstants\sso\sthat\nwe\sdo\snot\shave\sto\stranslate\sbetween\sthem.\s(CVS\s1998) +D 2004-10-04T13:19:24 +F Makefile.in 78ddc9fca09ab6e3b75a79ecf8d490e34cd0519c F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F VERSION 0aeddfe96f008f6cbe2c7167a782f3133e118d8d @@ -17,8 +17,9 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 -F main.mk fbe4b06ed4d32c529f1514595defe73a424a357e +F main.mk cabfd4a3e786840e8924689b04751a8c48dc4a42 F mkdll.sh 468d4f41d3ea98221371df4825cfbffbaac4d7e4 +F mkopcodeh.awk a80e53c2f41cd89b1355c2e3d9389e3f6f8e017d F mkso.sh 7b67da1d63070875ba948e749aee9ef50ce36e3d F publish.sh 72bde067dda3fc2d33e92f20253b924e3b97da30 F spec.template b2f6c4e488cbc3b993a57deba22cbc36203c4da3 @@ -33,7 +34,7 @@ F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029 F src/build.c 2ed6d9c26ad736142012bc99898869db17337121 F src/date.c 93927e2d1ffbd833fc220644896cfdc8f8d4af34 F src/delete.c d862b383a9abc0b79f4588783c2619fe52d74ea7 -F src/expr.c f255c5c56c0371cb2955cbc2733621051e4f79f8 +F src/expr.c 2f492bf532d700bd2c38e16caa49048535e8ed27 F src/func.c 1fbc5256639586573fd0e70814d6dcd8bc10afc1 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 @@ -53,14 +54,14 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c d3688828d314135ef0cd87b4d892805136c4168f F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 -F src/parse.y 968231351dd13ef6ee544336295db54708c22faf +F src/parse.y eb4920f637b4e44e038220e67dac07854bfd6325 F src/pragma.c 45978cc82fdf91f00d024a8e875c2b679fbce488 F src/printf.c 40770e1f553612d13dfc86d236086e69baa62fe1 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 96b1489111abe9b584be2f2cce26ad6f2d425b4e F src/shell.c 0856973c2b94e22664bc43f398ba3fc22d5e080c F src/sqlite.h.in 9bb76ff9e79ee72e6d529ff6ab1c252d513c3864 -F src/sqliteInt.h 5c406ebc830c5129748b77539283c0e20f978887 +F src/sqliteInt.h bfb12f1da75b2a8f5c88c9c3050343571def65b9 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008 F src/test1.c 3d78e5d827bf5d037f697c233c5934d45af46cb5 @@ -74,7 +75,7 @@ F src/update.c 7157084216c4b02a23cdb23eb6d246aa9034fa4d F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed F src/util.c f4ab796b9def353feed2191d7ce8e39a0f5059cd F src/vacuum.c 257de36230cb988842f66eb08dc6c0250b8e05f3 -F src/vdbe.c 0542852785220807feb02b9dee1150ac2e592c8d +F src/vdbe.c 49d4bda66884b1017e11962c7fb7eaf15b436be8 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b F src/vdbeapi.c 81ab9e84c55f5762f552904e6e5d309269b02017 @@ -248,7 +249,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 4493e287809874fabeddf5ca9045065a30790f2f -R ebf4aac4c1a61ea57872e563bbdb1393 +P c4697503d0ad080290b91e96dfc9a1a63f2df7e6 +R 7fe455a514dce92e3703ce1da8317d3a U drh -Z 44aded0ba9c92340348fe0ad36d9356d +Z 28445a4252d9b9c0f55f4514219ea5c1 diff --git a/manifest.uuid b/manifest.uuid index 1525b3ca0..40870d193 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4697503d0ad080290b91e96dfc9a1a63f2df7e6
\ No newline at end of file +4c817e3f293a9c1365e632f7dc13ae440263332a
\ No newline at end of file diff --git a/mkopcodeh.awk b/mkopcodeh.awk new file mode 100644 index 000000000..49e2498b3 --- /dev/null +++ b/mkopcodeh.awk @@ -0,0 +1,45 @@ +#!/usr/bin/awk -f +# +# This AWK script scans a concatenation of the parse.h output file from the +# parser and the vdbe.c source file in order to generate the opcodes numbers +# for all opcodes. +# +# The lines of the vdbe.c that we are interested in are of the form: +# +# case OP_aaaa: /* same as TK_bbbbb */ +# +# The TK_ comment is optional. If it is present, then the value assigned to +# the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned +# a small integer that is different from every other OP_ value. +# + +# Remember the TK_ values from the parse.h file +/^#define TK_/ { + tk[$2] = $3 +} + +# Scan for "case OP_aaaa:" lines in the vdbe.c file +/^case OP_/ { + name = $2 + gsub(/:/,"",name) + op[name] = -1 + for(i=3; i<NF-2; i++){ + if($i=="same" && $(i+1)=="as"){ + op[name] = tk[$(i+2)] + used[op[name]] = 1 + } + } +} + +# Assign numbers to all opcodes and output the result. +END { + cnt = 0 + for(name in op){ + if( op[name]<0 ){ + cnt++ + while( used[cnt] ) cnt++ + op[name] = cnt + } + printf "#define %-30s %d\n", name, op[name] + } +} diff --git a/src/expr.c b/src/expr.c index a07fdcd00..75167579b 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.165 2004/09/25 13:12:15 drh Exp $ +** $Id: expr.c,v 1.166 2004/10/04 13:19:24 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1180,41 +1180,19 @@ static void codeInteger(Vdbe *v, const char *z, int n){ /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. */ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_PLUS: op = OP_Add; break; - case TK_MINUS: op = OP_Subtract; break; - case TK_STAR: op = OP_Multiply; break; - case TK_SLASH: op = OP_Divide; break; - case TK_AND: op = OP_And; break; - case TK_OR: op = OP_Or; break; - case TK_LT: op = OP_Lt; break; - case TK_LE: op = OP_Le; break; - case TK_GT: op = OP_Gt; break; - case TK_GE: op = OP_Ge; break; - case TK_NE: op = OP_Ne; break; - case TK_EQ: op = OP_Eq; break; - case TK_ISNULL: op = OP_IsNull; break; - case TK_NOTNULL: op = OP_NotNull; break; - case TK_NOT: op = OP_Not; break; - case TK_UMINUS: op = OP_Negative; break; - case TK_BITAND: op = OP_BitAnd; break; - case TK_BITOR: op = OP_BitOr; break; - case TK_BITNOT: op = OP_BitNot; break; - case TK_LSHIFT: op = OP_ShiftLeft; break; - case TK_RSHIFT: op = OP_ShiftRight; break; - case TK_REM: op = OP_Remainder; break; - case TK_FLOAT: op = OP_Real; break; - case TK_STRING: op = OP_String8; break; - case TK_BLOB: op = OP_HexBlob; break; - case TK_CONCAT: op = OP_Concat; break; - default: op = 0; break; - } - switch( pExpr->op ){ + op = pExpr->op; + switch( op ){ case TK_COLUMN: { if( pParse->useAgg ){ sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); @@ -1236,11 +1214,14 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ } case TK_FLOAT: case TK_STRING: { + assert( TK_FLOAT==OP_Real ); + assert( TK_STRING==OP_String8 ); sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); break; } case TK_BLOB: { + assert( TK_BLOB==OP_HexBlob ); sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1); sqlite3VdbeDequoteP3(v, -1); break; @@ -1262,6 +1243,12 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_GE: case TK_NE: case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); @@ -1279,6 +1266,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_LSHIFT: case TK_RSHIFT: case TK_CONCAT: { + assert( TK_AND==OP_And ); + assert( TK_OR==OP_Or ); + assert( TK_PLUS==OP_Add ); + assert( TK_MINUS==OP_Subtract ); + assert( TK_REM==OP_Remainder ); + assert( TK_BITAND==OP_BitAnd ); + assert( TK_BITOR==OP_BitOr ); + assert( TK_SLASH==OP_Divide ); + assert( TK_LSHIFT==OP_ShiftLeft ); + assert( TK_RSHIFT==OP_ShiftRight ); + assert( TK_CONCAT==OP_Concat ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, 0, 0); @@ -1303,6 +1301,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ } case TK_BITNOT: case TK_NOT: { + assert( TK_BITNOT==OP_BitNot ); + assert( TK_NOT==OP_Not ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 0, 0); break; @@ -1310,13 +1310,15 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_ISNULL: case TK_NOTNULL: { int dest; + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3ExprCode(pParse, pExpr->pLeft); dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); + break; } - break; case TK_AGG_FUNCTION: { sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); break; @@ -1503,23 +1505,19 @@ int sqlite3ExprCodeExprList( ** ** If the expression evaluates to NULL (neither true nor false), then ** take the jump if the jumpIfNull flag is true. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. */ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_LT: op = OP_Lt; break; - case TK_LE: op = OP_Le; break; - case TK_GT: op = OP_Gt; break; - case TK_GE: op = OP_Ge; break; - case TK_NE: op = OP_Ne; break; - case TK_EQ: op = OP_Eq; break; - case TK_ISNULL: op = OP_IsNull; break; - case TK_NOTNULL: op = OP_NotNull; break; - default: break; - } - switch( pExpr->op ){ + op = pExpr->op; + switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); @@ -1542,6 +1540,12 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_GE: case TK_NE: case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); @@ -1549,6 +1553,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ } case TK_ISNULL: case TK_NOTNULL: { + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 1, dest); break; @@ -1597,17 +1603,38 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; - switch( pExpr->op ){ - case TK_LT: op = OP_Ge; break; - case TK_LE: op = OP_Gt; break; - case TK_GT: op = OP_Le; break; - case TK_GE: op = OP_Lt; break; - case TK_NE: op = OP_Eq; break; - case TK_EQ: op = OP_Ne; break; - case TK_ISNULL: op = OP_NotNull; break; - case TK_NOTNULL: op = OP_IsNull; break; - default: break; - } + + /* The value of pExpr->op and op are related as follows: + ** + ** pExpr->op op + ** --------- ---------- + ** TK_ISNULL OP_NotNull + ** TK_NOTNULL OP_IsNull + ** TK_NE OP_Eq + ** TK_EQ OP_Ne + ** TK_GT OP_Le + ** TK_LE OP_Gt + ** TK_GE OP_Lt + ** TK_LT OP_Ge + ** + ** For other values of pExpr->op, op is undefined and unused. + ** The value of TK_ and OP_ constants are arranged such that we + ** can compute the mapping above using the following expression. + ** Assert()s verify that the computation is correct. + */ + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); + + /* Verify correct alignment of TK_ and OP_ constants + */ + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); + assert( pExpr->op!=TK_NE || op==OP_Eq ); + assert( pExpr->op!=TK_EQ || op==OP_Ne ); + assert( pExpr->op!=TK_LT || op==OP_Ge ); + assert( pExpr->op!=TK_LE || op==OP_Gt ); + assert( pExpr->op!=TK_GT || op==OP_Le ); + assert( pExpr->op!=TK_GE || op==OP_Lt ); + switch( pExpr->op ){ case TK_AND: { sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); diff --git a/src/parse.y b/src/parse.y index 8d42dfd47..5999e2146 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.139 2004/09/30 14:22:47 drh Exp $ +** @(#) $Id: parse.y,v 1.140 2004/10/04 13:19:24 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -137,11 +137,17 @@ id(A) ::= ID(X). {A = X;} // causes them to be assigned integer values that are close together, // which keeps parser tables smaller. // +// The token values assigned to these symbols is determined by the order +// in which lemon first sees them. It must be the case that ISNULL/NOTNULL, +// NE/EQ, GT/LE, and GE/LT are separated by only a single value. See +// the sqlite3ExprIfFalse() routine for additional information on this +// constraint. +// %left OR. %left AND. %right NOT. -%left ISNULL NOTNULL IS LIKE GLOB BETWEEN IN NE EQ. -%left GT GE LT LE. +%left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ. +%left GT LE GE LT. %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. %left STAR SLASH REM. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e8946f256..7b4c4fc0e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.325 2004/10/01 02:00:31 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.326 2004/10/04 13:19:24 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -767,9 +767,9 @@ struct Token { struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - CollSeq *pColl; /* The collation type of the column or 0 */ u8 iDb; /* Database referenced by this expression */ u8 flags; /* Various flags. See below */ + CollSeq *pColl; /* The collation type of the column or 0 */ Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in "<expr> IN (<expr-list)" */ diff --git a/src/vdbe.c b/src/vdbe.c index 5ec829464..327460ca2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** 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.415 2004/09/19 00:50:21 drh Exp $ +** $Id: vdbe.c,v 1.416 2004/10/04 13:19:24 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -184,32 +184,6 @@ static int AggInsert(Agg *p, char *zKey, int nKey){ } /* -** Store a pointer to the AggElem currently in focus in *ppElem. Return -** SQLITE_OK if successful, otherwise an error-code. -*/ -static int AggInFocus(Agg *p, AggElem **ppElem){ - int rc; - int res; - - if( p->pCurrent ){ - *ppElem = p->pCurrent; - return SQLITE_OK; - } - - rc = sqlite3BtreeFirst(p->pCsr, &res); - if( rc!=SQLITE_OK ){ - return rc; - } - if( res!=0 ){ - rc = AggInsert(p,"",1); - *ppElem = p->pCurrent; - }else{ - rc = sqlite3BtreeData(p->pCsr, 0, 4, (char *)ppElem); - } - return rc; -} - -/* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ @@ -559,7 +533,9 @@ int sqlite3VdbeExec( ** file looking for lines that begin with "case OP_". The opcodes.h files ** will be filled with #defines that give unique integer values to each ** opcode and the opcodes.c file is filled with an array of strings where -** each string is the symbolic name for the corresponding opcode. +** each string is the symbolic name for the corresponding opcode. If the +** case statement is followed by a comment of the form "/# same as ... #/" +** that comment is used to determine the particular value of the opcode. ** ** Documentation about VDBE opcodes is generated by scanning this file ** for lines of that contain "Opcode:". That line and all subsequent @@ -677,7 +653,7 @@ case OP_Integer: { ** ** The string value P3 is converted to a real and pushed on to the stack. */ -case OP_Real: { +case OP_Real: { /* same as TK_FLOAT */ pTos++; pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; @@ -694,7 +670,7 @@ case OP_Real: { ** P3 points to a nul terminated UTF-8 string. This opcode is transformed ** into an OP_String before it is executed for the first time. */ -case OP_String8: { +case OP_String8: { /* same as TK_STRING */ pOp->opcode = OP_String; if( db->enc!=SQLITE_UTF8 && pOp->p3 ){ @@ -745,7 +721,7 @@ case OP_String: { ** The first time this instruction executes, in transforms itself into a ** 'Blob' opcode with a binary blob as P3. */ -case OP_HexBlob: { +case OP_HexBlob: { /* same as TK_BLOB */ pOp->opcode = OP_Blob; pOp->p1 = strlen(pOp->p3)/2; if( pOp->p1 ){ @@ -922,7 +898,7 @@ case OP_Callback: { ** When P1==1, this routine makes a copy of the top stack element ** into memory obtained from sqliteMalloc(). */ -case OP_Concat: { +case OP_Concat: { /* same as TK_CONCAT */ char *zNew; int nByte; int nField; @@ -1030,11 +1006,11 @@ case OP_Concat: { ** function before the division. Division by zero returns NULL. ** If either operand is NULL, the result is NULL. */ -case OP_Add: -case OP_Subtract: -case OP_Multiply: -case OP_Divide: -case OP_Remainder: { +case OP_Add: /* same as TK_PLUS */ +case OP_Subtract: /* same as TK_MINUS */ +case OP_Multiply: /* same as TK_STAR */ +case OP_Divide: /* same as TK_SLASH */ +case OP_Remainder: { /* same as TK_REM */ Mem *pNos = &pTos[-1]; assert( pNos>=p->aStack ); if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){ @@ -1233,10 +1209,10 @@ case OP_Function: { ** right by N bits where N is the top element on the stack. ** If either operand is NULL, the result is NULL. */ -case OP_BitAnd: -case OP_BitOr: -case OP_ShiftLeft: -case OP_ShiftRight: { +case OP_BitAnd: /* same as TK_BITAND */ +case OP_BitOr: /* same as TK_BITOR */ +case OP_ShiftLeft: /* same as TK_LSHIFT */ +case OP_ShiftRight: { /* same as TK_RSHIFT */ Mem *pNos = &pTos[-1]; int a, b; @@ -1398,12 +1374,12 @@ case OP_MustBeInt: { ** the 2nd element down on the stack is greater than or equal to the ** top of the stack. See the Eq opcode for additional information. */ -case OP_Eq: -case OP_Ne: -case OP_Lt: -case OP_Le: -case OP_Gt: -case OP_Ge: { +case OP_Eq: /* same as TK_EQ */ +case OP_Ne: /* same as TK_NE */ +case OP_Lt: /* same as TK_LT */ +case OP_Le: /* same as TK_LE */ +case OP_Gt: /* same as TK_GT */ +case OP_Ge: { /* same as TK_GE */ Mem *pNos; int flags; int res; @@ -1469,8 +1445,8 @@ case OP_Ge: { ** two values and push the resulting boolean value back onto the ** stack. */ -case OP_And: -case OP_Or: { +case OP_And: /* same as TK_AND */ +case OP_Or: { /* same as TK_OR */ Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ @@ -1517,7 +1493,7 @@ case OP_Or: { ** with its absolute value. If the top of the stack is NULL ** its value is unchanged. */ -case OP_Negative: +case OP_Negative: /* same as TK_UMINUS */ case OP_AbsValue: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Real ){ @@ -1550,7 +1526,7 @@ case OP_AbsValue: { ** with its complement. If the top of the stack is NULL its value ** is unchanged. */ -case OP_Not: { +case OP_Not: { /* same as TK_NOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); @@ -1566,7 +1542,7 @@ case OP_Not: { ** with its ones-complement. If the top of the stack is NULL its ** value is unchanged. */ -case OP_BitNot: { +case OP_BitNot: { /* same as TK_BITNOT */ assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); @@ -1627,7 +1603,7 @@ case OP_IfNot: { ** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack ** unchanged. */ -case OP_IsNull: { +case OP_IsNull: { /* same as TK_ISNULL */ int i, cnt; Mem *pTerm; cnt = pOp->p1; @@ -1650,7 +1626,7 @@ case OP_IsNull: { ** stack if P1 times if P1 is greater than zero. If P1 is less than ** zero then leave the stack unchanged. */ -case OP_NotNull: { +case OP_NotNull: { /* same as TK_NOTNULL */ int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; @@ -4241,8 +4217,7 @@ case OP_AggFocus: { case OP_AggSet: { AggElem *pFocus; int i = pOp->p2; - rc = AggInFocus(&p->agg, &pFocus); - if( rc!=SQLITE_OK ) goto abort_due_to_error; + pFocus = p->agg.pCurrent; assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->agg.nMem ); @@ -4260,8 +4235,7 @@ case OP_AggSet: { case OP_AggGet: { AggElem *pFocus; int i = pOp->p2; - rc = AggInFocus(&p->agg, &pFocus); - if( rc!=SQLITE_OK ) goto abort_due_to_error; + pFocus = p->agg.pCurrent; if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->agg.nMem ); pTos++; |