Support for a future ALTER TABLE command to add columns with default values. (CVS 2367)
FossilOrigin-Name: 9d5abc1ddf6da37563c12d5a0401b89bb4e51c59
This commit is contained in:
parent
97ba4c94fc
commit
aee18ef8e2
38
manifest
38
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
|
||||
|
@ -1 +1 @@
|
||||
9b96078763949a2723482328e7b90c939ba8d2d8
|
||||
9d5abc1ddf6da37563c12d5a0401b89bb4e51c59
|
@ -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));
|
||||
|
13
src/expr.c
13
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.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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
39
src/update.c
39
src/update.c
@ -12,10 +12,45 @@
|
||||
** 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);
|
||||
}
|
||||
|
18
src/vdbe.c
18
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.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
|
||||
|
@ -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*, ...);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
145
test/alter2.test
145
test/alter2.test
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {\>} txt
|
||||
regsub -all {<} $txt {\<} 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 {\>} line
|
||||
regsub -all {<} $line {\<} line
|
||||
append Opcode($current_op:text) \n$line
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user