]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
2.0.3 (CVS 287)
authordrh <drh@noemail.net>
Sat, 13 Oct 2001 02:59:08 +0000 (02:59 +0000)
committerdrh <drh@noemail.net>
Sat, 13 Oct 2001 02:59:08 +0000 (02:59 +0000)
FossilOrigin-Name: 75e90cf09b64ee1fcb39a711fc9ac6d3d2b849a5

15 files changed:
VERSION
manifest
manifest.uuid
src/build.c
src/expr.c
src/parse.y
src/sqliteInt.h
src/tokenize.c
src/vdbe.c
src/vdbe.h
test/expr.test
test/func.test
test/main.test
www/changes.tcl
www/lang.tcl

diff --git a/VERSION b/VERSION
index e9307ca5751b252b31c533d41f61df140d3f7537..50ffc5aa7f69fa0ffc74a36d81ac05273e116308 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.2
+2.0.3
index f31877d9b73480877f5b069e4d74a4467b27b87f..d796cc303da75e58a502fb254588dc7e73295fea 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Remove\sthe\sP3\sand\slabel\sarguments\sfrom\sthe\sinternal\ssqliteVdbeAddOp()\nfunction.\s\sThis\smakes\sthe\scode\seasier\sto\sread\sand\sperhaps\ssmaller\sas\nwell.\s(CVS\s286)
-D 2001-10-13T01:06:48
+C 2.0.3\s(CVS\s287)
+D 2001-10-13T02:59:09
 F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
 F Makefile.template 582916b263aa40a70521dfb3d99d574028abd47b
 F README 93d2977cc5c6595c448de16bdefc312b9d401533
-F VERSION 73e5f5e088b67ed1629b08ca531b81c778ab8695
+F VERSION f993f873300343a57c72ba514c06e41d922e43c1
 F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
 F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
@@ -21,9 +21,9 @@ F publish.sh badcd69b8e3a8bc69b162c4c9d7c209b2a0b119e
 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
 F src/btree.c 7e9c33a714ed1630562f89ad19847f5f28bd6d4d
 F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7
-F src/build.c 191f9ec9dd53d7b7767e6fe36d84c524eca9b731
+F src/build.c 9c3e3634b20c358e538f33f5ae125667e65447b2
 F src/delete.c bed54503368e0976aa2e8487d8914e7b7fb63aae
-F src/expr.c 5aa5db4d426e71b7a51edcef5d75969bc377d8f6
+F src/expr.c c1381b8229a5573b0928ede962e45c1c49d067af
 F src/hash.c b7ced0735287c142a3b2db46c3cae3e6826afb75
 F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
 F src/insert.c ae283e85a301bb3cd6af955f62bde1ca4ba4b56d
@@ -33,24 +33,24 @@ F src/os.c cece4ac6cabc9d377ef0a4ab4c16f6f0f6c84377
 F src/os.h bed702c9e3b768bc3cb1b12c90b83d099c1546be
 F src/pager.c e2e189a15e230c60e811f5e2ab25e68ae41c90be
 F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
-F src/parse.y 2275a832b544e8b57c422880a0d9badd4976d042
+F src/parse.y 148e4cd134d3cbd816dcb0df50e49e498faa6ba4
 F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
 F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
 F src/select.c ff4dc2271bb6de7a94f22e651be4d29b4f24ff3f
 F src/shell.c cb8c41f1b2173efd212dab3f35f1fc6bf32ead76
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in b95c161abf1d58bceb05290fa3f657d8f388fc11
-F src/sqliteInt.h 141b57b9eee7e8c937ac603f6cb7ecca77c1dd77
+F src/sqliteInt.h 5d6a79c70bdd9f993958c9c4a7970079fda495dd
 F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac
 F src/tclsqlite.c 765599686c19ed777ac379928d732c8bfc63ebac
 F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49
 F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
 F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
-F src/tokenize.c 15d349b68d9dc5722956bd7549752ace62034787
+F src/tokenize.c c3fcb76a41a22803b6060bddb5fbadc80bbe309c
 F src/update.c 0b287faf0cc1d2bfa437f8a54061dd12ae6df91d
 F src/util.c 4da3be37d0fd3c640d2d3033503768afdc8e5387
-F src/vdbe.c e26521af3d0f12426bd8567f4236d6b61eed2a00
-F src/vdbe.h 21e4aede55ccc9d81c88cae4772310c6debbe6df
+F src/vdbe.c dd65cd51bd5540edd8126723701f6ede6cb5f90c
+F src/vdbe.h 86fc2ef42f48024c9a2e1b7fb01eda22b65a5295
 F src/where.c 22fe910c7c8e2736eb37e9861343e90c0b513c86
 F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd
 F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0
@@ -58,15 +58,15 @@ F test/btree.test 47952c7a0c22660566264c68c0664592b7da85ce
 F test/btree2.test 20ce47ab804f15b6563736528bdd38aabe5193dc
 F test/copy.test 768e6f1701a07d08090e1ca7f7dcce0a7a72b43e
 F test/delete.test 5ebb114582457428b3e0e30b21b477fedcb85609
-F test/expr.test b3475005ea19d53bf8c4573fb6e4a4498be5b434
-F test/func.test dfee65686b8ba06071c2f007243a25c96ce82cf2
+F test/expr.test b4171c84b767f7b7e94dbce4824ba8e981a1c72f
+F test/func.test fb0f44de6d8487359a4455accbae120bde267772
 F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
 F test/index.test 6076f29d09a4f26a2efa38b03b8cc338b8662f0e
 F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
 F test/insert2.test 252d7130d8cc20f649b31a4f503cd87e660abda8
 F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
 F test/lock.test 19593689260c419efe7ced55b1418653a4b7bcd1
-F test/main.test 085ece17913a487caacbc0a392638c958c83a75d
+F test/main.test 1626345b5f630c5398eede500d9354813b76b0fd
 F test/malloc.test f1400a8d002eb96f1ca0a34abe56d2ab3e324740
 F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6
 F test/pager.test 59bbc4e3d489529ed33db6e15595789e51056077
@@ -102,19 +102,19 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
 F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb
 F www/c_interface.tcl a59ee0835d1b33fcddab7d4fd65cf9e50f7d2dc7
-F www/changes.tcl 4c722e1271b9c25477f2483dad1a96681ce73380
+F www/changes.tcl 7078c2b8a93c723babef5883e29ae629924d9378
 F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
 F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60
 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
 F www/index.tcl 68c815d64b35b2dcc4d4f6845827df71c6869f9f
-F www/lang.tcl 3a7900e3f80cab50f322d925e573bd9f0acd57e1
+F www/lang.tcl 8cf5de0e7b5d038506cd0b8fd26567ba43777b16
 F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
 F www/opcode.tcl 4365ad9798872491dbd7d3071510ebe461785ac3
 F www/speed.tcl ab7d6d3bc898472bd94320a5d3c63de928d4804b
 F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
 F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
 F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44
-P 0a7848b6190981cb7eb673bbe68cb217694daf2e
-R d882e44ee7d8a71c7c53e113bfd46069
+P 288ef1247b94c6c933451d120cdc78e471efc14e
+R 8da9c9836a4f886cd81b2c8f2ff58fcd
 U drh
-Z dbd2803044813be5011e55726d60bdc8
+Z ed5e48602a3cb4f7e24daba213a3911c
index 5b86e2fd5aeed38a39a70a379ab3f4a7691c9ba1..b8fe62d2892bee583430ade5043a2c82a02cddd1 100644 (file)
@@ -1 +1 @@
-288ef1247b94c6c933451d120cdc78e471efc14e
\ No newline at end of file
+75e90cf09b64ee1fcb39a711fc9ac6d3d2b849a5
\ No newline at end of file
index 8d428865cfdc7ca6f6d4e5af30fc0928cd238e5c..8f87dd4717dd2155f6acb1c84ff5a6a0f0b7a5cf 100644 (file)
@@ -25,7 +25,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.48 2001/10/13 01:06:48 drh Exp $
+** $Id: build.c,v 1.49 2001/10/13 02:59:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1081,12 +1081,14 @@ ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
       return pList;
     }
   }
-  i = pList->nExpr++;
-  pList->a[i].pExpr = pExpr;
-  pList->a[i].zName = 0;
-  if( pName ){
-    sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
-    sqliteDequote(pList->a[i].zName);
+  if( pExpr ){
+    i = pList->nExpr++;
+    pList->a[i].pExpr = pExpr;
+    pList->a[i].zName = 0;
+    if( pName ){
+      sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
+      sqliteDequote(pList->a[i].zName);
+    }
   }
   return pList;
 }
index 5ace17836ecdf762ec10b987dad76a2ab19d02b6..fdb45dc4f7887e1018082ef9dedb00ac12c7d5a8 100644 (file)
@@ -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.30 2001/10/13 01:06:48 drh Exp $
+** $Id: expr.c,v 1.31 2001/10/13 02:59:09 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -335,14 +335,16 @@ int sqliteFuncId(Token *pToken){
      int len;
      int id;
   } aFunc[] = {
-     { "count",  5, FN_Count },
-     { "min",    3, FN_Min   },
-     { "max",    3, FN_Max   },
-     { "sum",    3, FN_Sum   },
-     { "avg",    3, FN_Avg   },
-     { "fcnt",   4, FN_Fcnt  },  /* Used for testing only */
-     { "length", 6, FN_Length},
-     { "substr", 6, FN_Substr},
+     { "count",  5, FN_Count  },
+     { "min",    3, FN_Min    },
+     { "max",    3, FN_Max    },
+     { "sum",    3, FN_Sum    },
+     { "avg",    3, FN_Avg    },
+     { "fcnt",   4, FN_Fcnt   },  /* Used for testing only */
+     { "length", 6, FN_Length },
+     { "substr", 6, FN_Substr },
+     { "abs",    3, FN_Abs    },
+     { "round",  5, FN_Round  },
   };
   int i;
   for(i=0; i<ArraySize(aFunc); i++){
@@ -401,17 +403,23 @@ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
           is_agg = 1;
           break;
         }
+        case FN_Abs:
         case FN_Length: {
           too_few_args = n<1;
           too_many_args = n>1;
           break;
         }
+        case FN_Round: {
+          too_few_args = n<1;
+          too_many_args = n>2;
+          break;
+        }
         case FN_Substr: {
           too_few_args = n<3;
           too_many_args = n>3;
           break;
         }
-        /* The "fcnt(*)" function always returns the number of fetch
+        /* The "fcnt(*)" function always returns the number of OP_MoveTo
         ** operations that have occurred so far while processing the
         ** SQL statement.  This information can be used by test procedures
         ** to verify that indices are being used properly to minimize
@@ -496,6 +504,12 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
     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;
     default: break;
   }
   switch( pExpr->op ){
@@ -534,12 +548,22 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
     case TK_PLUS:
     case TK_STAR:
     case TK_MINUS:
+    case TK_REM:
+    case TK_BITAND:
+    case TK_BITOR:
     case TK_SLASH: {
       sqliteExprCode(pParse, pExpr->pLeft);
       sqliteExprCode(pParse, pExpr->pRight);
       sqliteVdbeAddOp(v, op, 0, 0);
       break;
     }
+    case TK_LSHIFT:
+    case TK_RSHIFT: {
+      sqliteExprCode(pParse, pExpr->pRight);
+      sqliteExprCode(pParse, pExpr->pLeft);
+      sqliteVdbeAddOp(v, op, 0, 0);
+      break;
+    }
     case TK_CONCAT: {
       sqliteExprCode(pParse, pExpr->pLeft);
       sqliteExprCode(pParse, pExpr->pRight);
@@ -580,6 +604,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
       }
       /* Fall through into TK_NOT */
     }
+    case TK_BITNOT:
     case TK_NOT: {
       sqliteExprCode(pParse, pExpr->pLeft);
       sqliteVdbeAddOp(v, op, 0, 0);
@@ -625,6 +650,21 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
           }
           break;
         }
+        case FN_Abs: {
+          sqliteExprCode(pParse, pList->a[0].pExpr);
+          sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
+          break;
+        }
+        case FN_Round: {
+          if( pList->nExpr==2 ){
+            sqliteExprCode(pParse, pList->a[1].pExpr);
+          }else{
+            sqliteVdbeAddOp(v, OP_Integer, 0, 0);
+          }
+          sqliteExprCode(pParse, pList->a[0].pExpr);
+          sqliteVdbeAddOp(v, OP_Precision, 0, 0);
+          break;
+        }
         case FN_Length: {
           sqliteExprCode(pParse, pList->a[0].pExpr);
           sqliteVdbeAddOp(v, OP_Strlen, 0, 0);
index 065cdfb4c80de80e6afe5ea5e467363ce619e6e0..1180ff1782c6d93c0c6fadde7e1b6b0560977141 100644 (file)
@@ -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.36 2001/10/12 17:30:05 drh Exp $
+** @(#) $Id: parse.y,v 1.37 2001/10/13 02:59:09 drh Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -331,7 +331,7 @@ inscollist(A) ::= ids(Y).                     {A = sqliteIdListAppend(0,&Y);}
 %left GT GE LT LE.
 %left BITAND BITOR LSHIFT RSHIFT.
 %left PLUS MINUS.
-%left STAR SLASH MOD.
+%left STAR SLASH REM.
 %left CONCAT.
 %right UMINUS BITNOT.
 
@@ -385,7 +385,7 @@ expr(A) ::= expr(X) PLUS expr(Y).  {A = sqliteExpr(TK_PLUS, X, Y, 0);}
 expr(A) ::= expr(X) MINUS expr(Y). {A = sqliteExpr(TK_MINUS, X, Y, 0);}
 expr(A) ::= expr(X) STAR expr(Y).  {A = sqliteExpr(TK_STAR, X, Y, 0);}
 expr(A) ::= expr(X) SLASH expr(Y). {A = sqliteExpr(TK_SLASH, X, Y, 0);}
-expr(A) ::= expr(X) MOD expr(Y).   {A = sqliteExpr(TK_MOD, X, Y, 0);}
+expr(A) ::= expr(X) REM expr(Y).   {A = sqliteExpr(TK_REM, X, Y, 0);}
 expr(A) ::= expr(X) CONCAT expr(Y). {A = sqliteExpr(TK_CONCAT, X, Y, 0);}
 expr(A) ::= expr(X) ISNULL(E). {
   A = sqliteExpr(TK_ISNULL, X, 0, 0);
index 781b415edad2ee6f03ce910380402b4c40a20612..e23e2b1dcefb001955ea0f78679010d61f24d4ca 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.60 2001/10/12 17:30:05 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.61 2001/10/13 02:59:09 drh Exp $
 */
 #include "sqlite.h"
 #include "hash.h"
@@ -117,21 +117,8 @@ extern int sqlite_iMallocFail;   /* Fail sqliteMalloc() after this many calls */
 #define FN_Fcnt       6
 #define FN_Length     7
 #define FN_Substr     8
-#if 0
 #define FN_Abs        9
-#define FN_Ceil       10
-#define FN_Floor      11
-#define FN_Frac       12
-#define FN_Sin        13
-#define FN_Cos        14
-#define FN_Tan        15
-#define FN_Asin       16
-#define FN_Acos       17
-#define FN_Atan       18
-#define FN_Exp        19
-#define FN_Ln         20
-#define FN_Pow        21
-#endif
+#define FN_Round      10
 
 /*
 ** Forward references to structures
index 673a6c8e1e183c21496f7c9ff122698bfc2776ba..52b23b210bdf7c9684967adbe467124cc655ab60 100644 (file)
@@ -15,7 +15,7 @@
 ** individual tokens and sends those tokens one-by-one over to the
 ** parser for analysis.
 **
-** $Id: tokenize.c,v 1.26 2001/10/09 04:19:47 drh Exp $
+** $Id: tokenize.c,v 1.27 2001/10/13 02:59:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -185,6 +185,10 @@ int sqliteGetToken(const char *z, int *tokenType){
       *tokenType = TK_SLASH;
       return 1;
     }
+    case '%': {
+      *tokenType = TK_REM;
+      return 1;
+    }
     case '=': {
       *tokenType = TK_EQ;
       return 1 + (z[1]=='=');
@@ -196,6 +200,9 @@ int sqliteGetToken(const char *z, int *tokenType){
       }else if( z[1]=='>' ){
         *tokenType = TK_NE;
         return 2;
+      }else if( z[1]=='<' ){
+        *tokenType = TK_LSHIFT;
+        return 2;
       }else{
         *tokenType = TK_LT;
         return 1;
@@ -205,6 +212,9 @@ int sqliteGetToken(const char *z, int *tokenType){
       if( z[1]=='=' ){
         *tokenType = TK_GE;
         return 2;
+      }else if( z[1]=='>' ){
+        *tokenType = TK_RSHIFT;
+        return 2;
       }else{
         *tokenType = TK_GT;
         return 1;
@@ -221,7 +231,7 @@ int sqliteGetToken(const char *z, int *tokenType){
     }
     case '|': {
       if( z[1]!='|' ){
-        *tokenType = TK_ILLEGAL;
+        *tokenType = TK_BITOR;
         return 1;
       }else{
         *tokenType = TK_CONCAT;
@@ -232,6 +242,14 @@ int sqliteGetToken(const char *z, int *tokenType){
       *tokenType = TK_COMMA;
       return 1;
     }
+    case '&': {
+      *tokenType = TK_BITAND;
+      return 1;
+    }
+    case '~': {
+      *tokenType = TK_BITNOT;
+      return 1;
+    }
     case '\'': case '"': {
       int delim = z[0];
       for(i=1; z[i]; i++){
index 2cace34e85dc2ae28b6642e707b7ee0a70b4bf93..9b7af239d31b8071f17753ea8afc16156b5b51c5 100644 (file)
@@ -30,7 +30,7 @@
 ** But other routines are also provided to help in building up
 ** a program instruction by instruction.
 **
-** $Id: vdbe.c,v 1.83 2001/10/13 01:06:48 drh Exp $
+** $Id: vdbe.c,v 1.84 2001/10/13 02:59:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -814,7 +814,9 @@ static char *zOpName[] = { 0,
   "ColumnName",        "Callback",          "Integer",           "String",
   "Null",              "Pop",               "Dup",               "Pull",
   "Add",               "AddImm",            "Subtract",          "Multiply",
-  "Divide",            "Min",               "Max",               "Like",
+  "Divide",            "Remainder",         "BitAnd",            "BitOr",
+  "BitNot",            "ShiftLeft",         "ShiftRight",        "AbsValue",
+  "Precision",         "Min",               "Max",               "Like",
   "Glob",              "Eq",                "Ne",                "Lt",
   "Le",                "Gt",                "Ge",                "IsNull",
   "NotNull",           "Negative",          "And",               "Or",
@@ -1322,10 +1324,20 @@ case OP_Concat: {
 ** is a string then it is converted to a double using the atof()
 ** function before the division.  Division by zero returns NULL.
 */
+/* Opcode: Remainder * * *
+**
+** Pop the top two elements from the stack, divide the
+** first (what was on top of the stack) from the second (the
+** next on stack)
+** and push the remainder after division onto the stack.  If either element
+** is a string then it is converted to a double using the atof()
+** function before the division.  Division by zero returns NULL.
+*/
 case OP_Add:
 case OP_Subtract:
 case OP_Multiply:
-case OP_Divide: {
+case OP_Divide:
+case OP_Remainder: {
   int tos = p->tos;
   int nos = tos - 1;
   VERIFY( if( nos<0 ) goto not_enough_stack; )
@@ -1337,11 +1349,16 @@ case OP_Divide: {
       case OP_Add:         b += a;       break;
       case OP_Subtract:    b -= a;       break;
       case OP_Multiply:    b *= a;       break;
-      default: {
+      case OP_Divide: {
         if( a==0 ) goto divide_by_zero;
         b /= a;
         break;
       }
+      default: {
+        if( a==0 ) goto divide_by_zero;
+        b %= a;
+        break;
+      }
     }
     POPSTACK;
     Release(p, nos);
@@ -1357,11 +1374,18 @@ case OP_Divide: {
       case OP_Add:         b += a;       break;
       case OP_Subtract:    b -= a;       break;
       case OP_Multiply:    b *= a;       break;
-      default: {
+      case OP_Divide: {
         if( a==0.0 ) goto divide_by_zero;
         b /= a;
         break;
       }
+      default: {
+        int ia = a;
+        int ib = b;
+        if( ia==0.0 ) goto divide_by_zero;
+        b = ib % ia;
+        break;
+      }
     }
     POPSTACK;
     Release(p, nos);
@@ -1377,6 +1401,37 @@ divide_by_zero:
   break;
 }
 
+/*
+** Opcode: Precision * * *
+**
+** The top of stack is a floating-point number and the next on stack is
+** an integer.  Truncate the floating-point number to a number of digits
+** specified by the integer and push the floating-point number back onto
+** the stack. 
+*/
+case OP_Precision: {
+  int tos = p->tos;
+  int nos = tos - 1;
+  int nDigit;
+  double v;
+  char zBuf[100];
+
+  VERIFY( if( nos<0 ) goto not_enough_stack; )
+  Realify(p, tos);
+  Integerify(p, nos);
+  nDigit = aStack[nos].i;
+  if( nDigit<0 ) nDigit = 0;
+  if( nDigit>30 ) nDigit = 30;
+  v = aStack[tos].r;
+  sprintf(zBuf, "%.*f", nDigit, v);
+  POPSTACK;
+  Release(p, nos);
+  zStack[nos] = sqliteStrDup(zBuf);
+  aStack[nos].n = strlen(zStack[tos]) + 1;
+  aStack[nos].flags = STK_Str | STK_Dyn;
+  break;
+}
+
 /* Opcode: Max * * *
 **
 ** Pop the top two elements from the stack then push back the
@@ -1455,6 +1510,56 @@ case OP_Min: {
   break;
 }
 
+/* Opcode: BitAnd * * *
+**
+** Pop the top two elements from the stack.  Convert both elements
+** to integers.  Push back onto the stack the bit-wise AND of the
+** two elements.
+*/
+/* Opcode: BitOr * * *
+**
+** Pop the top two elements from the stack.  Convert both elements
+** to integers.  Push back onto the stack the bit-wise OR of the
+** two elements.
+*/
+/* Opcode: ShiftLeft * * *
+**
+** Pop the top two elements from the stack.  Convert both elements
+** to integers.  Push back onto the stack the top element shifted
+** left by N bits where N is the second element on the stack.
+*/
+/* Opcode: ShiftRight * * *
+**
+** Pop the top two elements from the stack.  Convert both elements
+** to integers.  Push back onto the stack the top element shifted
+** right by N bits where N is the second element on the stack.
+*/
+case OP_BitAnd:
+case OP_BitOr:
+case OP_ShiftLeft:
+case OP_ShiftRight: {
+  int tos = p->tos;
+  int nos = tos - 1;
+  int a, b;
+  VERIFY( if( nos<0 ) goto not_enough_stack; )
+  Integerify(p, tos);
+  Integerify(p, nos);
+  a = aStack[tos].i;
+  b = aStack[nos].i;
+  switch( pOp->opcode ){
+    case OP_BitAnd:      a &= b;     break;
+    case OP_BitOr:       a |= b;     break;
+    case OP_ShiftLeft:   a <<= b;    break;
+    case OP_ShiftRight:  a >>= b;    break;
+    default:   /* CANT HAPPEN */     break;
+  }
+  POPSTACK;
+  Release(p, nos);
+  aStack[nos].i = a;
+  aStack[nos].flags = STK_Int;
+  break;
+}
+
 /* Opcode: AddImm  P1 * *
 ** 
 ** Add the value P1 to whatever is on top of the stack.
@@ -1633,21 +1738,33 @@ case OP_Or: {
 ** Treat the top of the stack as a numeric quantity.  Replace it
 ** with its additive inverse.
 */
-case OP_Negative: {
+/* Opcode: AbsValue * * *
+**
+** Treat the top of the stack as a numeric quantity.  Replace it
+** with its absolute value.
+*/
+case OP_Negative:
+case OP_AbsValue: {
   int tos = p->tos;
   VERIFY( if( tos<0 ) goto not_enough_stack; )
   if( aStack[tos].flags & STK_Real ){
     Release(p, tos);
-    aStack[tos].r = -aStack[tos].r;
+    if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
+      aStack[tos].r = -aStack[tos].r;
+    }
     aStack[tos].flags = STK_Real;
   }else if( aStack[tos].flags & STK_Int ){
     Release(p, tos);
-    aStack[tos].i = -aStack[tos].i;
+    if( pOp->opcode==OP_Negative ||  aStack[tos].i<0 ){
+      aStack[tos].i = -aStack[tos].i;
+    }
     aStack[tos].flags = STK_Int;
   }else{
     Realify(p, tos);
     Release(p, tos);
-    aStack[tos].r = -aStack[tos].r;
+    if( pOp->opcode==OP_Negative ||  aStack[tos].r<0.0 ){
+      aStack[tos].r = -aStack[tos].r;
+    }
     aStack[tos].flags = STK_Real;
   }
   break;
@@ -1668,6 +1785,21 @@ case OP_Not: {
   break;
 }
 
+/* Opcode:  * * *
+**
+** Interpret the top of the stack as an value.  Replace it
+** with its ones-complement.
+*/
+case OP_BitNot: {
+  int tos = p->tos;
+  VERIFY( if( p->tos<0 ) goto not_enough_stack; )
+  Integerify(p, tos);
+  Release(p, tos);
+  aStack[tos].i = ~aStack[tos].i;
+  aStack[tos].flags = STK_Int;
+  break;
+}
+
 /* Opcode: Noop * * *
 **
 ** Do nothing.  This instruction is often useful as a jump
index 69a1eaa11306ed53545e636c27ba94b5d3dc6ea9..4a60fb68ee06a8d86793d4c83509f26712815739 100644 (file)
@@ -15,7 +15,7 @@
 ** 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.28 2001/10/13 01:06:49 drh Exp $
+** $Id: vdbe.h,v 1.29 2001/10/13 02:59:09 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -168,38 +168,37 @@ typedef struct VdbeOp VdbeOp;
 #define OP_Subtract           83
 #define OP_Multiply           84
 #define OP_Divide             85
-#define OP_Remainder
-#define OP_BitAnd
-#define OP_BitOr
-#define OP_BitNot
-#define OP_ShiftLeft
-#define OP_ShiftRight
-#define OP_Power
-#define OP_Exp
-#define OP_Log
-#define OP_Min                86
-#define OP_Max                87
-#define OP_Like               88
-#define OP_Glob               89
-#define OP_Eq                 90
-#define OP_Ne                 91
-#define OP_Lt                 92
-#define OP_Le                 93
-#define OP_Gt                 94
-#define OP_Ge                 95
-#define OP_IsNull             96
-#define OP_NotNull            97
-#define OP_Negative           98
-#define OP_And                99
-#define OP_Or                100
-#define OP_Not               101
-#define OP_Concat            102
-#define OP_Noop              103
-
-#define OP_Strlen            104
-#define OP_Substr            105
-
-#define OP_MAX               105
+#define OP_Remainder          86
+#define OP_BitAnd             87
+#define OP_BitOr              88
+#define OP_BitNot             89
+#define OP_ShiftLeft          90
+#define OP_ShiftRight         91
+#define OP_AbsValue           92
+#define OP_Precision          93
+#define OP_Min                94
+#define OP_Max                95
+#define OP_Like               96
+#define OP_Glob               97
+#define OP_Eq                 98
+#define OP_Ne                 99
+#define OP_Lt                100
+#define OP_Le                101
+#define OP_Gt                102
+#define OP_Ge                103
+#define OP_IsNull            104
+#define OP_NotNull           105
+#define OP_Negative          106
+#define OP_And               107
+#define OP_Or                108
+#define OP_Not               109
+#define OP_Concat            110
+#define OP_Noop              111
+
+#define OP_Strlen            112
+#define OP_Substr            113
+
+#define OP_MAX               113
 
 /*
 ** Prototypes for the VDBE interface.  See comments on the implementation
index bc30a660afd2dc247c3e8c5980382c45e4ce002f..c275e4a4d99ad213a2d3765047d072b7e5b4922d 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing expressions.
 #
-# $Id: expr.test,v 1.15 2001/09/16 00:13:28 drh Exp $
+# $Id: expr.test,v 1.16 2001/10/13 02:59:09 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -68,6 +68,11 @@ test_expr expr-1.38 {i1=1} {-i1} {-1}
 test_expr expr-1.39 {i1=1} {+i1} {1}
 test_expr expr-1.40 {i1=1, i2=2} {+(i2+i1)} {3}
 test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3}
+test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3}
+test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
+test_expr expr-1.44 {i1=1} {~i1} {-2}
+test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
+test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
 
 test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
 test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
index f83b3697c0efbb9f5d2c7c9cc9e549d242dcaf25..12d7e3927f824deec60c7fc9c6fbafe7912aca91 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing built-in functions.
 #
-# $Id: func.test,v 1.4 2001/09/16 00:13:28 drh Exp $
+# $Id: func.test,v 1.5 2001/10/13 02:59:09 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -121,4 +121,44 @@ do_test func-3.10 {
 
 } ;# End [sqlite -encoding]==UTF-8 and \u1234!=u1234
 
+# Test the abs() and round() functions.
+#
+do_test func-4.1 {
+  execsql {
+    CREATE TABLE t1(a,b,c);
+    INSERT INTO t1 VALUES(1,2,3);
+    INSERT INTO t1 VALUES(2,1.2345678901234,-12345.67890);
+    INSERT INTO t1 VALUES(3,-2,-5);
+  }
+  catchsql {SELECT abs(a,b) FROM t1}
+} {1 {too many arguments to function abs()}}
+do_test func-4.2 {
+  catchsql {SELECT abs() FROM t1}
+} {1 {too few arguments to function abs()}}
+do_test func-4.3 {
+  catchsql {SELECT abs(b) FROM t1 ORDER BY a}
+} {0 {2 1.2345678901234 2}}
+do_test func-4.4 {
+  catchsql {SELECT abs(c) FROM t1 ORDER BY a}
+} {0 {3 12345.6789 5}}
+
+do_test func-4.5 {
+  catchsql {SELECT round(a,b,c) FROM t1}
+} {1 {too many arguments to function round()}}
+do_test func-4.6 {
+  catchsql {SELECT round(b,2) FROM t1}
+} {0 {2.00 1.23 -2.00}}
+do_test func-4.7 {
+  catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
+} {0 {2 1 -2}}
+do_test func-4.8 {
+  catchsql {SELECT round(c) FROM t1 ORDER BY a}
+} {0 {3 -12346 -5}}
+do_test func-4.9 {
+  catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
+} {0 {3.0 -12345.68 -5.000}}
+do_test func-4.10 {
+  catchsql {SELECT round() FROM t1 ORDER BY a}
+} {1 {too few arguments to function round()}}
+
 finish_test
index 5dbcf592126fa18c1770c19ab4857436b9289f1c..daee82c9fc4049e9de0f061e2a2361c170b5a59d 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is exercising the code in main.c.
 #
-# $Id: main.test,v 1.8 2001/09/16 00:13:28 drh Exp $
+# $Id: main.test,v 1.9 2001/10/13 02:59:09 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -98,17 +98,9 @@ do_test main-3.2 {
   foreach f [glob -nocomplain testdb/*] {file delete -force $f}
   file delete -force testdb
   sqlite db testdb
-  set v [catch {execsql {SELECT * from T1 where ~x}} msg]
+  set v [catch {execsql {SELECT * from T1 where @x}} msg]
   lappend v $msg
-} {1 {unrecognized token: "~"}}
-do_test main-3.3 {
-  catch {db close}
-  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
-  file delete -force testdb
-  sqlite db testdb
-  set v [catch {execsql {SELECT a|b from T1 where x}} msg]
-  lappend v $msg
-} {1 {unrecognized token: "|"}}
+} {1 {unrecognized token: "@"}}
 
 do_test main-3.3 {
   catch {db close}
index 47fdcc3831ec7280596fe1cbac5a8d3092d65847..155a979e5a3aa415cd02e7267d34116b34ed5c12 100644 (file)
@@ -17,12 +17,16 @@ proc chng {date desc} {
   puts "<DD><P><UL>$desc</UL></P></DD>"
 }
 
-chng {2001 Oct ? (2.0.3)} {
+chng {2001 Oct 13 (2.0.3)} {
 <li>Bug fix: the <b>sqlite_busy_timeout()</b> function was delaying 1000
     times too long before failing.</li>
 <li>Bug fix: an assertion was failing if the disk holding the database
     file became full or stopped accepting writes for some other reason.
     New tests were added to detect similar problems in the future.</li>
+<li>Added new operators: <b>&amp;</b> (bitwise-and)
+    <b>|</b> (bitwise-or), <b>~</b> (ones-complement),
+    <b>&lt;&lt;</b> (shift left), <b>&gt;&gt;</b> (shift right).</li>
+<li>Added new functions: <b>round()</b> and <b>abs()</b>.</li>
 }
 
 chng {2001 Oct 9 (2.0.2)} {
index 2c1dbb70d169029e3498fea91aa842da3169ce41..8f622598056b65949dfdf3b3c26965deb6b4af9b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: lang.tcl,v 1.11 2001/10/08 13:22:33 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.12 2001/10/13 02:59:10 drh Exp $}
 
 puts {<html>
 <head>
@@ -357,14 +357,21 @@ subcomponent of most other commands.</p>
 highest to lowest precedence:</p>
 
 <blockquote><pre>
-<font color="#2c2cf0"><big>*    /
+<font color="#2c2cf0"><big>*    /    %
 +    -
+&lt;&lt;   &gt;&gt;   &amp;    |
 &lt;    &lt;=   &gt;    &gt;=
 =    ==   !=   &lt;&gt;   </big>IN
 AND
 OR</font>
 </pre></blockquote>
 
+<p>Supported unary operaters are these:</p>
+
+<blockquote><pre>
+<font color="#2c2cf0"><big>-    +    !    ~</big></font>
+</pre></blockquote>
+
 <p>Any SQLite value can be used as part of an expression.  
 For arithmetic operations, integers are treated as integers.
 Strings are first converted to real numbers using <b>atof()</b>.
@@ -437,7 +444,7 @@ functions:</p>
 
 <blockquote><pre>
 <font color="#2c2cf0"><big>count    min       max       sum
-avg      length    substr</big></font>
+avg      length    substr    abs       round</big></font>
 </pre></blockquote>
 
 <p>
@@ -445,12 +452,20 @@ The functions <b>count</b>, <b>sum</b>, and <b>avg</b> and the functions
 <b>min</b> and <b>max</b> used with only one argument are all aggregate
 functions.  This means that they are computed across all rows of the result.
 The functions <b>min</b> and <b>max</b>
-with two or more arguments and the 
-functions <b>length</b> and <b>substr</b>
+with two or more arguments and all other functions
 are non-aggregates.  Non-aggregate functions
 are computed separately for each row of the result.
 </p>
 
+<p>
+The <b>round</b> function can take either 1 or 2 arguments.  The
+first argument is the floating point value that is rounded.  The
+second argument is the number of digits to the right of the
+decimal point to preserve.  If the second argument is omitted,
+zero is assumed.  So round(1.23456,2) is 1.23 and
+round(12.34,0) and round(12.34) both evaluate to 12.
+</p>
+
 <p>
 The "<b>count(*)</b>" syntax is supported but
 "<b>count(distinct</b> <i>COLUMN-NAME</i><b>)</b>" is not.