]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Support for a future ALTER TABLE command to add columns with default values. (CVS...
authordanielk1977 <danielk1977@noemail.net>
Wed, 9 Mar 2005 12:26:50 +0000 (12:26 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 9 Mar 2005 12:26:50 +0000 (12:26 +0000)
FossilOrigin-Name: 9d5abc1ddf6da37563c12d5a0401b89bb4e51c59

15 files changed:
manifest
manifest.uuid
src/delete.c
src/expr.c
src/main.c
src/parse.y
src/sqliteInt.h
src/update.c
src/vdbe.c
src/vdbe.h
src/vdbeaux.c
src/vdbemem.c
test/alter2.test
test/capi3.test
www/opcode.tcl

index 3f8b7dbd20ee67dc8f616d953fbb6fe388c7d4d1..54518d47b248f9ab7e1e632532904203d5b9987b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Print\san\serror\smessage\sand\squit\sif\sthe\sregression\stests\sare\srun\sas\sroot.\nTicket\s#1153.\s(CVS\s2366)
-D 2005-03-02T05:18:57
+C Support\sfor\sa\sfuture\sALTER\sTABLE\scommand\sto\sadd\scolumns\swith\sdefault\svalues.\s(CVS\s2367)
+D 2005-03-09T12:26:51
 F Makefile.in 76443a83549d1539105e12d13bd0054a05ab2214
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -34,15 +34,15 @@ F src/btree.c 2a9c2c8a9f5a2762f0c770bc9c3f69c689d79d81
 F src/btree.h 2e2cc923224649337d7217df0dd32b06673ca180
 F src/build.c a8792b2f866c1ccc32f4977f4ff61d787d60ddfb
 F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f
-F src/delete.c 4b94395b52a8f7785acd71135c2ce54f3f5550b3
+F src/delete.c ebd18402d5c4dcc410043dacc831fe3e1ad8480a
 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
-F src/expr.c e160aabb59ff3c02e8e00ca4b30d00b94664c519
+F src/expr.c 8901081a1207ce7fc038bdc1d97ec4f102a7bfd9
 F src/func.c ff0673a25ec6216934e664bf9f480ae8b2c66936
 F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
 F src/insert.c 0456649d4d48396f918e7ea1fecbf3d66ed90816
 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
-F src/main.c 9f0716fcee245c275a04b42c778c921483dcf868
+F src/main.c 90cb84bbb85aa89442af41ad4323b136af6527b7
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
 F src/os.h ae44064dc118b20d39450cb331409a775e8bb1c6
 F src/os_common.h 0e7f428ba0a6c40a61bc56c4e96f493231301b73
@@ -54,14 +54,14 @@ F src/os_win.c bddeae1c3299be0fbe47077dd4e98b786a067f71
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 835028769569971c7dbd63d11d3517392f1cdae0
 F src/pager.h 70d496f372163abb6340f474288c4bb9ea962cf7
-F src/parse.y 450fc9c4d5a737be6fdba6e4b2e3de5800d4d750
+F src/parse.y 0b6135268a7a29db35335d5b71b5a8791e02f91e
 F src/pragma.c 4b20dbc0f4b97f412dc511853d3d0c2e0d4adedc
 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c 69e6093d52e871a243477e9746f820456538dd03
 F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26
 F src/sqlite.h.in c85f6bad9ca7de29f505fe886646cfff7df4c55e
-F src/sqliteInt.h f95cc4becd7b27293aae8f8c4ed2f6ef44830fbb
+F src/sqliteInt.h b59243adc43f0326ca7d8ce0b7ebd3cc70bd670d
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
 F src/tclsqlite.c 29e56ecdb94c4066dbe6b088d12cc2404bc9597e
 F src/test1.c 7b11aafae2d2b5850799200f4b9f8465a69a0c9d
@@ -71,21 +71,21 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
 F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
 F src/tokenize.c 103cbaa932c790f540f8eceb63cd3010e117bdff
 F src/trigger.c 038c8e128d4551cd016426cd11bbf5c478816481
-F src/update.c b6f4668c11059f86b71581187d09197fa28ec4be
+F src/update.c 42823d00865c9fe4f01b3c62647858726345a28e
 F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 F src/util.c 1b7b9a127b66743ab6cba8d44597aeb570723c99
 F src/vacuum.c 5cf598003191bd91c17a64742bad8e46241698a8
-F src/vdbe.c 26b085c3a64a8d7a50f9a4ef116481b6afce80b9
-F src/vdbe.h bb9186484f749a839c6c43953e79a6530253f7cd
+F src/vdbe.c 1bf34fb915afffd9b865a81770dc8cb99b3a04ac
+F src/vdbe.h 7e307333d74e134eff237bb9d45fe764e544ad6a
 F src/vdbeInt.h e80721cd8ff611789e20743eec43363a9fb5a48e
 F src/vdbeapi.c 467caa6e6fb9247528b1c7ab9132ae1b4748e8ac
-F src/vdbeaux.c 8d8cc8992cb78cab35e034fa81ad0c1a771c39f1
-F src/vdbemem.c 62fe89471b656a922e9879be005abf690509ead3
+F src/vdbeaux.c 30a9a6f6c80c7862e23c741a99c27e75149b39f5
+F src/vdbemem.c 4e853ce3151eaf7906150da85a1b3ce1fe5e8da8
 F src/where.c 80a2a9d24f868fc5744ba2838701c46934c7e09f
 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
 F test/alter.test 3a20ce14c3989f7e2e75da50797065c2e56f838b
-F test/alter2.test 8536631ea9cd97480dd548894b361795bf33e9cf
+F test/alter2.test 10277f9d5290951ab389c2fc92f3b1a78bbfe2af
 F test/attach.test 3c951c822047854fd6c2f1f6ad7c0ad82c7aa90b
 F test/attach2.test 6f3a3a3a7f5be40388dd4d805e0e0712718dca9d
 F test/attach3.test c05c70b933afbde0901dab9da3e66ee842c09f38
@@ -106,7 +106,7 @@ F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
 F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f
 F test/capi2.test 2bd71f573b32e3ac5b97441a55873eae14eeab0d
-F test/capi3.test 39143488ac6aeddb35fa76557d0a25f54081cebc
+F test/capi3.test 7c1c91895239fef05427ceb628a193cb4f61031f
 F test/capi3b.test 5b6a66f9f295f79f443b5d3f33187fa5ef6cf336
 F test/collate1.test f79736d2ebf5492167ee4d1f4ab4c09dda776b03
 F test/collate2.test 224a632ba04907c049804b08162efd234aa7871f
@@ -263,7 +263,7 @@ F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
 F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
 F www/oldnews.tcl 1e4c67ca29b4d9621fca846e75702dd9ae9c9868
 F www/omitted.tcl 9f332aea97b47ec53234f4cd9aa4b4a6da8641ec
-F www/opcode.tcl dafa030a5a3cc24a2f9fd4cfbfb7d7323d2151b0
+F www/opcode.tcl 5bd68059416b223515a680d410a9f7cb6736485f
 F www/optimizing.tcl f0b2538988d1bbad16cbfe63ec6e8f48c9eb04e5
 F www/pragma.tcl 3b7d88d6545e9b8ea4a3661e0be5e0f0e9817466
 F www/quickstart.tcl 6f6f694b6139be2d967b1492eb9a6bdf7058aa60
@@ -274,7 +274,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
-P 0c4d2b11c922b41d0e03bfbd885dfdf52ce7ccab
-R 6a309e6f1333a571f2b08c8b0dcd5d4b
-U drh
-Z 03a22f6b6cd85be716988d11a4912ae8
+P 9b96078763949a2723482328e7b90c939ba8d2d8
+R addb8e4a99b565c64d053b41daed1503
+U danielk1977
+Z 96056e2906d91fc33a19b0bf81dd2822
index 0d68003e13670f0e29deb636280a5620ed81bc80..dcd0b347fd4b3a6abd281228a5c14da343afce60 100644 (file)
@@ -1 +1 @@
-9b96078763949a2723482328e7b90c939ba8d2d8
\ No newline at end of file
+9d5abc1ddf6da37563c12d5a0401b89bb4e51c59
\ No newline at end of file
index b160bdaba258763b9802986970882a15a2bcf22d..43445ff5519aba84810e126e465cb243249fbbd8 100644 (file)
@@ -12,7 +12,7 @@
 ** 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.100 2005/01/29 08:32:45 danielk1977 Exp $
+** $Id: delete.c,v 1.101 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -436,6 +436,7 @@ void sqlite3GenerateIndexKey(
       sqlite3VdbeAddOp(v, OP_Dup, j, 0);
     }else{
       sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
+      sqlite3ColumnDefault(v, pTab, idx);
     }
   }
   sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
index f27bed5c240fda710f3361fb3e8ff4df96a56a7a..1723e60c7dc074f3ed0312e4e7591453e51fa3fd 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.194 2005/02/12 08:59:57 danielk1977 Exp $
+** $Id: expr.c,v 1.195 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -403,6 +403,7 @@ Expr *sqlite3ExprDup(Expr *p){
   pNew->pRight = sqlite3ExprDup(p->pRight);
   pNew->pList = sqlite3ExprListDup(p->pList);
   pNew->pSelect = sqlite3SelectDup(p->pSelect);
+  pNew->pTab = p->pTab;
   return pNew;
 }
 void sqlite3TokenCopy(Token *pTo, Token *pFrom){
@@ -847,6 +848,7 @@ static int lookupName(
             pExpr->iColumn = j==pTab->iPKey ? -1 : j;
             pExpr->affinity = pTab->aCol[j].affinity;
             pExpr->pColl = pTab->aCol[j].pColl;
+            pExpr->pTab = pTab;
             break;
           }
         }
@@ -958,6 +960,9 @@ static int lookupName(
   if( cnt==1 ){
     assert( pNC!=0 );
     sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
+    if( pMatch && !pMatch->pSelect ){
+      pExpr->pTab = pMatch->pTab;
+    }
   }
   return cnt!=1;
 }
@@ -1385,11 +1390,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
         sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
       }else if( pExpr->iColumn>=0 ){
         sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
-#ifndef NDEBUG
-        if( pExpr->span.z && pExpr->span.n>0 && pExpr->span.n<100 ){
-          VdbeComment((v, "# %T", &pExpr->span));
-        }
-#endif
+        sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);
       }else{
         sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
       }
index 5a3f26cf06ecf54d4e5aec22bc3f4305f311df82..8e7ca89a5a80c4f90b660cefadefaf02bfce969f 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.281 2005/02/19 08:18:06 danielk1977 Exp $
+** $Id: main.c,v 1.282 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -258,7 +258,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
       db->file_format = 1;
     }
 
-    if( db->file_format==2 ){
+    if( db->file_format==2 || db->file_format==3 ){
       /* File format 2 is treated exactly as file format 1. New 
       ** databases are created with file format 1.
       */ 
@@ -269,11 +269,13 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   /*
   ** file_format==1    Version 3.0.0.
   ** file_format==2    Version 3.1.3.
+  ** file_format==3    Version 3.1.4.
   **
   ** Version 3.0 can only use files with file_format==1. Version 3.1.3
   ** can read and write files with file_format==1 or file_format==2.
+  ** Version 3.1.4 can read and write file formats 1, 2 and 3.
   */
-  if( meta[1]>2 ){
+  if( meta[1]>3 ){
     sqlite3BtreeCloseCursor(curMain);
     sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
     return SQLITE_ERROR;
index 2ad78de3174cd71b80f0642c3ad9d6b1d1ad332a..f8b89793b04cda5f3016bef0f243226eb602792e 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.166 2005/02/14 06:38:40 danielk1977 Exp $
+** @(#) $Id: parse.y,v 1.167 2005/03/09 12:26:51 danielk1977 Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -603,7 +603,7 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
 term(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
 term(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
 term(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
-expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
 expr(A) ::= REGISTER(X).     {A = sqlite3RegisterExpr(pParse, &X);}
 expr(A) ::= VARIABLE(X).     {
   Token *pToken = &X;
index 8bc5a606d3ec0cb9fe78215a1d7a05a05645a88f..174c0d2a8620e84ae88882590010ead0b1c846cf 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.371 2005/02/15 21:36:18 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.372 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -805,6 +805,10 @@ struct Token {
 ** be the right operand of an IN operator.  Or, if a scalar SELECT appears
 ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
 ** operand.
+**
+** If the Expr is of type OP_Column, and the table it is selecting from
+** is a disk table or the "old.*" pseudo-table, then pTab points to the
+** corresponding table definition.
 */
 struct Expr {
   u8 op;                 /* Operation performed by this node */
@@ -824,6 +828,7 @@ struct Expr {
   int iAggCtx;           /* The value to pass as P1 of OP_AggGet. */
   Select *pSelect;       /* When the expression is a sub-select.  Also the
                          ** right side of "<expr> IN (<select>)" */
+  Table *pTab;           /* Table for OP_Column expressions. */
 };
 
 /*
@@ -1536,6 +1541,8 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*));
 void sqlite3ValueFree(sqlite3_value*);
 sqlite3_value *sqlite3ValueNew();
 sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
+int sqlite3ValueFromExpr(Expr *, u8, u8, sqlite3_value **);
+void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
 extern const unsigned char sqlite3UpperToLower[];
 void sqlite3RootPageMoved(Db*, int, int);
 void sqlite3Reindex(Parse*, Token*, Token*);
@@ -1546,5 +1553,6 @@ void sqlite3NestedParse(Parse*, const char*, ...);
 void sqlite3ExpirePreparedStatements(sqlite3*);
 void sqlite3CodeSubselect(Parse *, Expr *);
 int sqlite3SelectResolve(Parse *, Select *, NameContext *);
+void sqlite3ColumnDefault(Vdbe *, Table *, int);
 
 #endif
index 81e5db951f2988d43c20d2806eacd9bb6fd6d04e..5b528169657155c8f152299964ca3142e45554c0 100644 (file)
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.104 2005/01/29 08:32:45 danielk1977 Exp $
+** $Id: update.c,v 1.105 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
+/*
+** The most recently coded instruction was an OP_Column to retrieve column
+** 'i' of table pTab. This routine sets the P3 parameter of the 
+** OP_Column to the default value, if any.
+**
+** The default value of a column is specified by a DEFAULT clause in the 
+** column definition. This was either supplied by the user when the table
+** was created, or added later to the table definition by an ALTER TABLE
+** command. If the latter, then the row-records in the table btree on disk
+** may not contain a value for the column and the default value, taken
+** from the P3 parameter of the OP_Column instruction, is returned instead.
+** If the former, then all row-records are guaranteed to include a value
+** for the column and the P3 value is not required.
+**
+** Column definitions created by an ALTER TABLE command may only have 
+** literal default values specified: a number, null or a string. (If a more
+** complicated default expression value was provided, it is evaluated 
+** when the ALTER TABLE is executed and one of the literal values written
+** into the sqlite_master table.)
+**
+** Therefore, the P3 parameter is only required if the default value for
+** the column is a literal number, string or null. The sqlite3ValueFromExpr()
+** function is capable of transforming these types of expressions into
+** sqlite3_value objects.
+*/
+void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
+  if( pTab && !pTab->pSelect ){
+    sqlite3_value *pValue;
+    u8 enc = sqlite3VdbeDb(v)->enc;
+    Column *pCol = &pTab->aCol[i];
+    sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
+    sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
+  }
+}
+
 /*
 ** Process an UPDATE statement.
 **
@@ -294,6 +329,7 @@ void sqlite3Update(
       j = aXRef[i];
       if( j<0 ){
         sqlite3VdbeAddOp(v, OP_Column, iCur, i);
+        sqlite3ColumnDefault(v, pTab, i);
       }else{
         sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
       }
@@ -378,6 +414,7 @@ void sqlite3Update(
       j = aXRef[i];
       if( j<0 ){
         sqlite3VdbeAddOp(v, OP_Column, iCur, i);
+        sqlite3ColumnDefault(v, pTab, i);
       }else{
         sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
       }
index 6b52ff79f180acadcdde36260fc6cf330fbb8e94..cfb941aaf06a446d93b364bf62e5539c2bcbdde0 100644 (file)
@@ -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.456 2005/02/19 08:18:06 danielk1977 Exp $
+** $Id: vdbe.c,v 1.457 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -303,6 +303,14 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
   }
 }
 
+/*
+** Exported version of applyAffinity(). This one works on sqlite3_value*, 
+** not the internal Mem* type.
+*/
+void sqlite3ValueApplyAffinity(sqlite3_value *pVal, u8 affinity, u8 enc){
+  applyAffinity((Mem *)pVal, affinity, enc);
+}
+
 #ifdef SQLITE_DEBUG
 /*
 ** Write a nice string representation of the contents of cell pMem
@@ -1677,7 +1685,7 @@ case OP_SetNumColumns: {
   break;
 }
 
-/* Opcode: Column P1 P2 *
+/* Opcode: Column P1 P2 P3
 **
 ** Interpret the data that cursor P1 points to as a structure built using
 ** the MakeRecord instruction.  (See the MakeRecord opcode for additional
@@ -1911,7 +1919,11 @@ case OP_Column: {
     sqlite3VdbeSerialGet(zData, aType[p2], pTos);
     pTos->enc = db->enc;
   }else{
-    pTos->flags = MEM_Null;
+    if( pOp->p3 ){
+      sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
+    }else{
+      pTos->flags = MEM_Null;
+    }
   }
 
   /* If we dynamically allocated space to hold the data (in the
index d0e9fb188ace3c891c898cffcc3d2f365f582297..37882f251b015004904856a32bd6c56f2197e4ae 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.92 2005/01/29 08:32:45 danielk1977 Exp $
+** $Id: vdbe.h,v 1.93 2005/03/09 12:26:51 danielk1977 Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -69,6 +69,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define P3_FUNCDEF  (-5)  /* P3 is a pointer to a FuncDef structure */
 #define P3_KEYINFO  (-6)  /* P3 is a pointer to a KeyInfo structure */
 #define P3_VDBEFUNC (-7)  /* P3 is a pointer to a VdbeFunc structure */
+#define P3_MEM      (-8)  /* P3 is a pointer to a Mem*    structure */
 
 /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
 ** is made.  That copy is freed when the Vdbe is finalized.  But if the
@@ -120,6 +121,7 @@ int sqliteVdbeSetVariables(Vdbe*,int,const char**);
 void sqlite3VdbeSetNumCols(Vdbe*,int);
 int sqlite3VdbeSetColName(Vdbe*, int, const char *, int);
 void sqlite3VdbeCountChanges(Vdbe*);
+sqlite3 *sqlite3VdbeDb(Vdbe*);
 
 #ifndef NDEBUG
   void sqlite3VdbeComment(Vdbe*, const char*, ...);
index 6d77d725f41335dc8c998c1e3ed26f5ab700e029..e422add952a7eb7b1d3aeeca59c1c00eba388175 100644 (file)
@@ -1420,6 +1420,9 @@ void sqlite3VdbeDelete(Vdbe *p){
         sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
         sqliteFree(pVdbeFunc);
       }
+      if( pOp->p3type==P3_MEM ){
+        sqlite3ValueFree((sqlite3_value*)pOp->p3);
+      }
     }
     sqliteFree(p->aOp);
   }
@@ -1847,3 +1850,10 @@ void sqlite3ExpirePreparedStatements(sqlite3 *db){
     p->expired = 1;
   }
 }
+
+/*
+** Return the database associated with the Vdbe.
+*/
+sqlite3 *sqlite3VdbeDb(Vdbe *v){
+  return v->db;
+}
index 23da9ced9e518fea94db8a3e7988b2e6789bf8ba..49b874e1ffee3d5ae6fbfdd61769b9e47648ac3d 100644 (file)
@@ -700,6 +700,72 @@ sqlite3_value* sqlite3ValueNew(){
   return p;
 }
 
+/*
+** Create a new sqlite3_value object, containing the value of pExpr.
+**
+** This only works for very simple expressions that consist of one constant
+** token (i.e. "5", "5.1", "NULL", "'a string'"). If the expression can
+** be converted directly into a value, then the value is allocated and
+** a pointer written to *ppVal. The caller is responsible for deallocating
+** the value by passing it to sqlite3ValueFree() later on. If the expression
+** cannot be converted to a value, then *ppVal is set to NULL.
+*/
+int sqlite3ValueFromExpr(
+  Expr *pExpr, 
+  u8 enc, 
+  u8 affinity,
+  sqlite3_value **ppVal
+){
+  int op;
+  char *zVal = 0;
+  sqlite3_value *pVal = 0;
+
+  if( !pExpr ){
+    *ppVal = 0;
+    return SQLITE_OK;
+  }
+  op = pExpr->op;
+
+  if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
+    zVal = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
+    pVal = sqlite3ValueNew();
+    if( !zVal || !pVal ) goto no_mem;
+    sqlite3Dequote(zVal);
+    sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3FreeX);
+    if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
+      sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
+    }else{
+      sqlite3ValueApplyAffinity(pVal, affinity, enc);
+    }
+  }else if( op==TK_UMINUS ) {
+    if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){
+      pVal->i = -1 * pVal->i;
+      pVal->r = -1.0 * pVal->r;
+    }
+  }
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+  else if( op==TK_BLOB ){
+    int nVal;
+    pVal = sqlite3ValueNew();
+    zVal = sqliteStrNDup(pExpr->token.z+1, pExpr->token.n-1);
+    if( !zVal || !pVal ) goto no_mem;
+    sqlite3Dequote(zVal);
+    nVal = strlen(zVal)/2;
+    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(zVal), nVal, 0, sqlite3FreeX);
+    sqliteFree(zVal);
+  }
+#endif
+
+  *ppVal = pVal;
+  return SQLITE_OK;
+
+no_mem:
+  sqliteFree(zVal);
+  sqlite3ValueFree(pVal);
+  *ppVal = 0;
+  return SQLITE_NOMEM;
+}
+
 /*
 ** Change the string value of an sqlite3_value object
 */
index 57918c25ee9de79d93dfdee1e42420579d58ada8..6834e77026cdfe7c35ac1809e8f3c53be1f8bb6d 100644 (file)
@@ -13,7 +13,7 @@
 # file format change that may be used in the future to implement
 # "ALTER TABLE ... ADD COLUMN".
 #
-# $Id: alter2.test,v 1.2 2005/02/26 18:10:45 drh Exp $
+# $Id: alter2.test,v 1.3 2005/03/09 12:26:51 danielk1977 Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -57,9 +57,11 @@ proc get_file_format {{fname test.db}} {
 }
 
 # This procedure sets the SQL statement stored for table $tbl in the
-# sqlite_master table of file 'test.db' to $sql.
+# sqlite_master table of file 'test.db' to $sql. Also set the file format
+# to the supplied value. This is 2 if the added column has a default that is
+# NULL, or 3 otherwise. 
 #
-proc alter_table {tbl sql} {
+proc alter_table {tbl sql {file_format 2}} {
   sqlite3 dbat test.db
   dbat eval {
     PRAGMA writable_schema = 1;
@@ -222,12 +224,12 @@ ifcapable trigger {
 
 #---------------------------------------------------------------------
 # Check that an error occurs if the database is upgraded to a file
-# format that SQLite does not support (in this case 3). Note: The 
+# format that SQLite does not support (in this case 4). Note: The 
 # file format is checked each time the schema is read, so changing the
 # file format requires incrementing the schema cookie.
 #
 do_test alter2-4.1 {
-  set_file_format 3
+  set_file_format 4
 } {}
 do_test alter2-4.2 {
   catchsql {
@@ -291,4 +293,137 @@ do_test alter2-6.3 {
   get_file_format 
 } {2}
 
+#---------------------------------------------------------------------
+# Test that types and values for columns added with default values 
+# other than NULL work with SELECT statements.
+#
+do_test alter2-7.1 {
+  execsql {
+    DROP TABLE t1;
+    CREATE TABLE t1(a);
+    INSERT INTO t1 VALUES(1);
+    INSERT INTO t1 VALUES(2);
+    INSERT INTO t1 VALUES(3);
+    INSERT INTO t1 VALUES(4);
+    SELECT * FROM t1;
+  }
+} {1 2 3 4}
+do_test alter2-7.2 {
+  set sql {CREATE TABLE t1(a, b DEFAULT '123', c INTEGER DEFAULT '123')}
+  alter_table t1 $sql 3
+  execsql {
+    SELECT * FROM t1 LIMIT 1;
+  }
+} {1 123 123}
+do_test alter2-7.3 {
+  execsql {
+    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
+  }
+} {1 integer 123 text 123 integer}
+do_test alter2-7.4 {
+  execsql {
+    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
+  }
+} {1 integer 123 text 123 integer}
+do_test alter2-7.5 {
+  set sql {CREATE TABLE t1(a, b DEFAULT -123.0, c VARCHAR(10) default 5)}
+  alter_table t1 $sql 3
+  execsql {
+    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
+  }
+} {1 integer -123.0 real 5 text}
+
+#-----------------------------------------------------------------------
+# Test that UPDATE trigger tables work with default values, and that when
+# a row is updated the default values are correctly transfered to the 
+# new row.
+# 
+ifcapable trigger {
+db function set_val {set ::val}
+  do_test alter2-8.1 {
+    execsql {
+      CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
+      SELECT set_val(
+          old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)||' '||
+          new.b||' '||typeof(new.b)||' '||new.c||' '||typeof(new.c) 
+      );
+      END;
+    }
+    list
+  } {}
+}
+do_test alter2-8.2 {
+  execsql {
+    UPDATE t1 SET c = 10 WHERE a = 1;
+    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
+  }
+} {1 integer -123.0 real 10 text}
+ifcapable trigger {
+  do_test alter2-8.3 {
+    set ::val
+  } {-123 real 5 text -123 real 10 text}
+}
+
+#-----------------------------------------------------------------------
+# Test that DELETE trigger tables work with default values, and that when
+# a row is updated the default values are correctly transfered to the 
+# new row.
+# 
+ifcapable trigger {
+  do_test alter2-9.1 {
+    execsql {
+      CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN
+      SELECT set_val(
+          old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)
+      );
+      END;
+    }
+    list
+  } {}
+  do_test alter2-9.2 {
+    execsql {
+      DELETE FROM t1 WHERE a = 2;
+    }
+    set ::val
+  } {-123 real 5 text}
+}
+
+#-----------------------------------------------------------------------
+# Test creating an index on a column added with a default value. 
+#
+do_test alter2-10.1 {
+  execsql {
+    CREATE TABLE t2(a);
+    INSERT INTO t2 VALUES('a');
+    INSERT INTO t2 VALUES('b');
+    INSERT INTO t2 VALUES('c');
+    INSERT INTO t2 VALUES('d');
+  }
+  alter_table t2 {CREATE TABLE t2(a, b DEFAULT X'ABCD', c DEFAULT NULL);} 3
+  catchsql {
+    SELECT * FROM sqlite_master;
+  }
+  execsql {
+    SELECT quote(a), quote(b), quote(c) FROM t2 LIMIT 1;
+  }
+} {'a' X'ABCD' NULL}
+do_test alter2-10.2 {
+  execsql {
+    CREATE INDEX i1 ON t2(b);
+    SELECT a FROM t2 WHERE b = X'ABCD';
+  }
+} {a b c d}
+do_test alter2-10.3 {
+  execsql {
+    DELETE FROM t2 WHERE a = 'c';
+    SELECT a FROM t2 WHERE b = X'ABCD';
+  }
+} {a b d}
+do_test alter2-10.4 {
+  execsql {
+    SELECT count(b) FROM t2 WHERE b = X'ABCD';
+  }
+} {3}
+
 finish_test
+
index 4aef3e66dd085e6337a424b7a970c45995bed7c5..d573eda3cb55d11f624cbf548048291e296d8d08 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script testing the callback-free C/C++ API.
 #
-# $Id: capi3.test,v 1.30 2005/02/19 08:18:06 danielk1977 Exp $
+# $Id: capi3.test,v 1.31 2005/03/09 12:26:51 danielk1977 Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -487,7 +487,7 @@ if {![sqlite3 -has-codec]} {
     set ::bt [btree_open test.db 10 0]
     btree_begin_transaction $::bt
     set meta [btree_get_meta $::bt]
-    lset meta 2 3
+    lset meta 2 4
     eval [concat btree_update_meta $::bt [lrange $meta 0 end]]
     btree_commit $::bt
     btree_close $::bt
index 77dfa5c8f7e7311a58911c8ae8dc5086b4b9a484..f28534fb5cf9e98064d03aec931fd0a572b3d0f5 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: opcode.tcl,v 1.14 2004/10/10 17:24:55 drh Exp $}
+set rcsid {$Id: opcode.tcl,v 1.15 2005/03/09 12:26:51 danielk1977 Exp $}
 source common.tcl
 header {SQLite Virtual Machine Opcodes}
 puts {
@@ -20,7 +20,10 @@ foreach line [split $file \n] {
   }
   if {[regexp {^/\* Opcode: } $line]} {
     set current_op [lindex $line 2]
-    set Opcode($current_op:args) [lrange $line 3 end]
+    set txt [lrange $line 3 end]
+    regsub -all {>} $txt {\&gt;} txt
+    regsub -all {<} $txt {\&lt;} txt
+    set Opcode($current_op:args) $txt
     lappend OpcodeList $current_op
     continue
   }
@@ -33,6 +36,8 @@ foreach line [split $file \n] {
   if {$line==""} {
     append Opcode($current_op:text) \n<p>
   } else {
+    regsub -all {>} $line {\&gt;} line
+    regsub -all {<} $line {\&lt;} line
     append Opcode($current_op:text) \n$line
   }
 }