When extracting values from a record to use in an UPDATEd version of that record, apply OP_RealAffinity if required. Fix for #3992. (CVS 6945)

FossilOrigin-Name: 3616766a6f5c8179cc55444c29ecf29cc69f88ce
This commit is contained in:
danielk1977 2009-07-27 10:05:04 +00:00
parent a53c704fec
commit c7538b5f63
7 changed files with 112 additions and 26 deletions

View File

@ -1,5 +1,5 @@
C The\snoReadlock\sproperty\son\sa\spager\sobject\simplies\sthe\sreadOnly\sproperty.\nUse\sthis\sfact\sto\ssimplify\sthe\slogic\sin\ssqlite3PagerSharedLock().\s(CVS\s6944)
D 2009-07-25T22:13:35
C When\sextracting\svalues\sfrom\sa\srecord\sto\suse\sin\san\sUPDATEd\sversion\sof\sthat\srecord,\sapply\sOP_RealAffinity\sif\srequired.\sFix\sfor\s#3992.\s(CVS\s6945)
D 2009-07-27T10:05:05
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in df9359da7a726ccb67a45db905c5447d5c00c6ef
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -113,8 +113,8 @@ F src/build.c a15de7c5d020a778b641fca0b2510126843f4b30
F src/callback.c cb68b21b0d4ae7d11ae0e487933bce3323784dcf
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
F src/delete.c 6f0192ecf2ae97dbbf4cccfa32639b504da70d4a
F src/expr.c f6f21604c1367354b28d03c983a83279071a2948
F src/delete.c fb2dfdd9696dfc4ef232c806ccecf307f94ea277
F src/expr.c d069ba1e060f296ea4f18fb85198fafefd00b22f
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/func.c 9856373f5315f6b8690d7f07f7191aa9f279ca87
F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
@ -163,7 +163,7 @@ F src/select.c 71748b8e244112cf73df9446c4246c192276c30d
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
F src/sqlite.h.in 5672d9a6e19f80c1c7f1276dbe10e7d51c8fd97b
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 11d239cc658823c719a3077ea2c7691795002c34
F src/sqliteInt.h 1199395d32e77658835bf6e976208d59f792f7ed
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@ -200,7 +200,7 @@ F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
F src/tokenize.c af8a56e6a50c5042fc305bfa796275e9bf26ff2b
F src/trigger.c c07c5157c58fcdb704f65d5f5e4775276e45bb8b
F src/update.c 7570d90842f0d9338906eeea443193358869ca97
F src/update.c 245a652c0c1b1affd7ccf2a1970a465977e7bfa2
F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff
F src/util.c 861d5b5c58be4921f0a254489ea94cb15f550ef8
F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0
@ -657,6 +657,7 @@ F test/tkt3918.test e6cdf6bfcfe9ba939d86a4238a9dc55d6eec5d42
F test/tkt3922.test 022ace32c049e3964f68492c12eb803e8e4856d8
F test/tkt3929.test 6a4c3baefb4e75127356b7d675b5df42c35c00d1
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
F test/tkt3992.test c193b9643b1c25d020c503a986d5e4089e65c530
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/trace.test 19ffbc09885c3321d56358a5738feae8587fb377
F test/trans.test d887cb07630dc39879a322d958ad8b006137485c
@ -738,7 +739,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
P f0024b3189245d608a0cb57fa7e472c6daa1406f
R 25fcba4dba5a24b6461a64df15761046
U drh
Z 68027e399a7581e7ca33dd0037ba76d1
P 886e665f6cf780464b280c286b03c9fb5c1a6b2a
R 899fdca0f993aff7c16e3dca0f2bd4bf
U danielk1977
Z 8a5d8493499fa3d337872f4bdb3cfbf7

View File

@ -1 +1 @@
886e665f6cf780464b280c286b03c9fb5c1a6b2a
3616766a6f5c8179cc55444c29ecf29cc69f88ce

View 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.205 2009/07/24 17:58:53 danielk1977 Exp $
** $Id: delete.c,v 1.206 2009/07/27 10:05:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -617,7 +617,7 @@ int sqlite3GenerateIndexKey(
sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
}else{
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
sqlite3ColumnDefault(v, pTab, idx);
sqlite3ColumnDefault(v, pTab, idx, -1);
}
}
if( doMakeRec ){

View 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.447 2009/07/16 12:41:06 drh Exp $
** $Id: expr.c,v 1.448 2009/07/27 10:05:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -1924,12 +1924,7 @@ int sqlite3ExprCodeGetColumn(
}else if( ALWAYS(pTab!=0) ){
int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
sqlite3ColumnDefault(v, pTab, iColumn);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
sqlite3ColumnDefault(v, pTab, iColumn, iReg);
}
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
return iReg;

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.894 2009/07/24 17:58:53 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.895 2009/07/27 10:05:05 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -2801,7 +2801,7 @@ void sqlite3SelectPrep(Parse*, Select*, NameContext*);
int sqlite3ResolveExprNames(NameContext*, Expr*);
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
void sqlite3ColumnDefault(Vdbe *, Table *, int);
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char*);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.205 2009/07/24 17:58:53 danielk1977 Exp $
** $Id: update.c,v 1.206 2009/07/27 10:05:06 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -53,8 +53,13 @@ static void updateVirtualTable(
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite3_value objects.
**
** If parameter iReg is not negative, code an OP_RealAffinity instruction
** on register iReg. This is used when an equivalent integer value is
** stored in place of an 8-byte floating point value in order to save
** space.
*/
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
assert( pTab!=0 );
if( !pTab->pSelect ){
sqlite3_value *pValue;
@ -67,6 +72,11 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
if( pValue ){
sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
}
}
@ -451,7 +461,7 @@ void sqlite3Update(
if( (i<32 && (new_col_mask&((u32)1<<i))!=0) || new_col_mask==0xffffffff ){
if( j<0 ){
sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regCols+i);
sqlite3ColumnDefault(v, pTab, i);
sqlite3ColumnDefault(v, pTab, i, -1);
}else{
sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr, regCols+i);
}
@ -502,7 +512,7 @@ void sqlite3Update(
j = aXRef[i];
if( j<0 ){
sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regData+i);
sqlite3ColumnDefault(v, pTab, i);
sqlite3ColumnDefault(v, pTab, i, regData+i);
}else{
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regData+i);
}

80
test/tkt3992.test Normal file
View File

@ -0,0 +1,80 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: tkt3992.test,v 1.1 2009/07/27 10:05:06 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test tkt3992-1.1 {
execsql {
CREATE TABLE parameters1(
mountcnt INT NOT NULL CHECK (typeof(mountcnt) == 'integer'),
version REAL NOT NULL
);
INSERT INTO parameters1(mountcnt, version) VALUES(1, 1.0);
CREATE TABLE parameters2(
mountcnt INT NOT NULL CHECK (typeof(mountcnt) == 'integer'),
version REAL CHECK (typeof(version) == 'real')
);
INSERT INTO parameters2(mountcnt, version) VALUES(1, 1.0);
}
} {}
do_test tkt3992-1.2 {
execsql {
UPDATE parameters1 SET mountcnt = mountcnt + 1;
SELECT * FROM parameters1;
}
} {2 1.0}
do_test tkt3992-1.3 {
execsql {
UPDATE parameters2 SET mountcnt = mountcnt + 1;
SELECT * FROM parameters2;
}
} {2 1.0}
do_test tkt3992-2.1 {
execsql {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
ALTER TABLE t1 ADD COLUMN c DEFAULT 3;
SELECT * FROM t1;
}
} {1 2 3}
do_test tkt3992-2.2 {
execsql {
UPDATE t1 SET a = 'one';
SELECT * FROM t1;
}
} {one 2 3}
db function tcl eval
do_test tkt3992-2.3 {
execsql {
CREATE TABLE t2(a REAL, b REAL, c REAL);
INSERT INTO t2 VALUES(1, 2, 3);
CREATE TRIGGER tr2 BEFORE UPDATE ON t2 BEGIN
SELECT tcl('set res', typeof(new.c));
END;
UPDATE t2 SET a = 'I';
}
set res
} {real}
explain {
UPDATE t2 SET a = 'I';
}
finish_test