Manifest types in indices. At the moment indices use manifest typing, but

some other parts of the SQL engine do not, which can lead to some strange
results. (CVS 1368)

FossilOrigin-Name: 9f2b6d9d3a07e25fcdb7e8290da7a182a65c37b2
This commit is contained in:
danielk1977 2004-05-13 05:16:15 +00:00
parent 6f11bef7d6
commit 452c989fd8
8 changed files with 144 additions and 82 deletions

View File

@ -1,5 +1,5 @@
C Allocate\smore\soverflow\sdata\sonto\soverflow\spages,\sthus\swasting\sless\sdisk\sspace.\s(CVS\s1367)
D 2004-05-13T01:12:57
C Manifest\stypes\sin\sindices.\sAt\sthe\smoment\sindices\suse\smanifest\styping,\sbut\nsome\sother\sparts\sof\sthe\sSQL\sengine\sdo\snot,\swhich\scan\slead\sto\ssome\sstrange\nresults.\s(CVS\s1368)
D 2004-05-13T05:16:16
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -63,9 +63,9 @@ F src/update.c 6ca82fc4a0fb4d7f134e961921c906f6f3c8bc74
F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f
F src/util.c 778a8cd03ad6e52778602d20a3132c7d2d1b0a0c
F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476
F src/vdbe.c 9b82d9ed192729e00581ae08d1cd71a27a698fe0
F src/vdbe.h 71c02a75d506a3ce9f6bdfc78101528d5edf319b
F src/vdbeInt.h 608a0b092a2ab3ab7538384e5e3da09ae512d50c
F src/vdbe.c 773fb49293f0412aa65e2bcbced40bd64464529e
F src/vdbe.h 94457ca73bae972dc61bca33a4dccc2e6e14e2f8
F src/vdbeInt.h 66904cfb0b004de8441e47ce00da8c7d4c498c76
F src/vdbeaux.c c976c7fe334a1d1c102dda410546e880549a6060
F src/where.c 487e55b1f64c8fbf0f46a9a90c2247fc45ae6a9a
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
@ -93,7 +93,7 @@ F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
F test/hook.test 1a67ce0cd64a6455d016962542f2822458dccc49
F test/in.test 0de39b02ceeca90993b096822fb5a884661c5b47
F test/index.test 9295deefbdb6dedbe01be8905f0c448fe5bd4079
F test/insert.test 105e559e024051ea0ba5ccd2a219490028e1ead5
F test/insert.test 6ec324659656f4a86e4abfcf1a1fd2795ba6b603
F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
F test/interrupt.test 9142ce4448605127640eda5e283952f75f67ed91
F test/intpkey.test 9320af48415c594afd4e15f8ef0daa272e05502e
@ -124,9 +124,9 @@ F test/quick.test 25df45ec1f8551279358dc0f0a2388ab59e06a30
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
F test/rowid.test 77f7e8c7ca626a15ff91a536595b695cfce7c845
F test/select1.test 3bfcccd2eadcddbb07f1f5da6550aee8484ea4fb
F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4
F test/select2.test 2115d8f7a34fcb5c0cbe8491f441830bc44d3398
F test/select3.test 445a1a3dde4e2fd32541b311f55da5e2f8079d76
F test/select4.test e7e9a32fa745246cb99fadbeb63af4843a17925b
F test/select4.test 804b48d637aeee5e952333a997cfba316b489a3a
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
F test/select6.test a9e31906e700e7c7592c4d0acfc022808f718baf
F test/sort.test ba07b107c16070208e6aab3cadea66ba079d85ba
@ -191,7 +191,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 64a75c4cd40f79c7b384bb2972922ff0c10212a4
R bb0bf681c9aa31fdafb3dd299e62bb5d
U drh
Z 90888ec7d9d6df77a80907a07724f815
P 1d52a4bb478648ef53a0dbb21865ccb9281dc24a
R 348f622445c9bf52db446021aadee19c
U danielk1977
Z b02892c4dfff10665b81dd53d91883c9

View File

@ -1 +1 @@
1d52a4bb478648ef53a0dbb21865ccb9281dc24a
9f2b6d9d3a07e25fcdb7e8290da7a182a65c37b2

View 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.284 2004/05/12 11:24:03 danielk1977 Exp $
** $Id: vdbe.c,v 1.285 2004/05/13 05:16:16 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -2181,8 +2181,8 @@ case OP_MakeRecord: {
**
** See also: MakeKey, SortMakeKey
*/
case OP_MakeIdxKey:
case OP_MakeKey: {
case OP_MakeIdxKey2:
case OP_MakeKey2: {
char *zNewKey;
int nByte;
int nField;
@ -2280,7 +2280,7 @@ case OP_MakeKey: {
break;
}
/* Opcode: MakeIdxKey3 P1 P2 P3
/* Opcode: MakeIdxKey3 P1 P2 *
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index. In addition, take one additional integer
@ -2290,21 +2290,23 @@ case OP_MakeKey: {
** pushed back. The first P1 entries that are popped are strings and the
** last entry (the lowest on the stack) is an integer record number.
*/
case OP_MakeKey3:
case OP_MakeIdxKey3: {
case OP_MakeKey:
case OP_MakeIdxKey: {
Mem *pRec;
Mem *pData0;
int nField;
u64 rowid;
int nByte = 0;
int addRowid;
int containsNull = 0;
char *zKey; /* The new key */
int offset = 0;
nField = pOp->p1;
pData0 = &pTos[1-nField];
assert( pData0>=p->aStack );
addRowid = (pOp->opcode==OP_MakeIdxKey?1:0);
addRowid = ((pOp->opcode==OP_MakeIdxKey)?1:0);
/* Calculate the number of bytes required for the new index key and
** store that number in nByte. Also set rowid to the record number to
@ -2312,19 +2314,23 @@ case OP_MakeIdxKey3: {
*/
for(pRec=pData0; pRec<=pTos; pRec++){
u64 serial_type = sqlite3VdbeSerialType(pRec);
if( serial_type==0 ){
containsNull = 1;
}
nByte += sqlite3VarintLen(serial_type);
nByte += sqlite3VdbeSerialTypeLen(serial_type);
}
if( addRowid ){
pRec = &pData0[-nField];
pRec = &pTos[0-nField];
assert( pRec>=p->aStack );
Integerify(pRec);
rowid = pRec->i;
nByte += sqlite3VarintLen(rowid);
nByte++;
}
/* Allocate space for the new key */
zKey = sqliteMalloc(nByte);
zKey = (char *)sqliteMalloc(nByte);
if( !zKey ){
rc = SQLITE_NOMEM;
goto abort_due_to_error;
@ -2332,20 +2338,27 @@ case OP_MakeIdxKey3: {
/* Build the key in the buffer pointed to by zKey. */
for(pRec=pData0; pRec<=pTos; pRec++){
zKey += sqlite3PutVarint(zKey, sqlite3VdbeSerialType(pRec));
zKey += sqlite3VdbeSerialPut(zKey, pRec);
offset += sqlite3PutVarint(&zKey[offset], sqlite3VdbeSerialType(pRec));
offset += sqlite3VdbeSerialPut(&zKey[offset], pRec);
}
if( addRowid ){
sqlite3PutVarint(zKey, rowid);
zKey[offset++] = '\0';
offset += sqlite3PutVarint(&zKey[offset], rowid);
}
assert( offset==nByte );
/* Pop the consumed values off the stack and push on the new key. */
popStack(&pTos, nField+addRowid);
if( addRowid||(pOp->p2==0) ){
popStack(&pTos, nField+addRowid);
}
pTos++;
pTos->flags = MEM_Blob|MEM_Dyn;
pTos->flags = MEM_Str|MEM_Dyn; /* TODO: should eventually be MEM_Blob */
pTos->z = zKey;
pTos->n = nByte;
if( pOp->p2 && containsNull ){
pc = pOp->p2 - 1;
}
break;
}
@ -2657,7 +2670,12 @@ case OP_OpenWrite: {
pCur->nullRow = 1;
if( pX==0 ) break;
do{
rc = sqlite3BtreeCursor(pX, p2, wrFlag, 0, 0, &pCur->pCursor);
/* When opening cursors, always supply the comparison function
** sqlite3VdbeKeyCompare(). If the table being opened is of type
** INTKEY, the btree layer won't call the comparison function anyway.
*/
rc = sqlite3BtreeCursor(pX, p2, wrFlag, sqlite3VdbeKeyCompare, 0,
&pCur->pCursor);
switch( rc ){
case SQLITE_BUSY: {
if( db->xBusyCallback==0 ){
@ -2946,7 +2964,7 @@ case OP_IsUnique: {
Mem *pNos = &pTos[-1];
Cursor *pCx;
BtCursor *pCrsr;
int R;
i64 R;
/* Pop the value R off the top of the stack
*/
@ -2959,22 +2977,26 @@ case OP_IsUnique: {
pCrsr = pCx->pCursor;
if( pCrsr!=0 ){
int res, rc;
int v; /* The record number on the P1 entry that matches K */
i64 v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
int nKey; /* Number of bytes in K */
int len; /* Number of bytes in K without the rowid at the end */
/* Make sure K is a string and make zKey point to K
*/
Stringify(pNos);
zKey = pNos->z;
nKey = pNos->n;
assert( nKey >= 4 );
assert( nKey >= 2 );
len = nKey-2;
while( zKey[len] && --len );
/* Search for an entry in P1 where all but the last four bytes match K.
** If there is no such entry, jump immediately to P2.
*/
assert( p->aCsr[i].deferredMoveto==0 );
rc = sqlite3BtreeMoveto(pCrsr, zKey, nKey-4, &res);
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res<0 ){
rc = sqlite3BtreeNext(pCrsr, &res);
@ -2983,8 +3005,7 @@ case OP_IsUnique: {
break;
}
}
/* FIX ME - the sqlite2BtreeKeyCompare() function is a temporary hack */
rc = sqlite2BtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &res);
rc = sqlite3VdbeIdxKeyCompare(pCrsr, len, zKey, 0, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
@ -2992,21 +3013,22 @@ case OP_IsUnique: {
}
/* At this point, pCrsr is pointing to an entry in P1 where all but
** the last for bytes of the key match K. Check to see if the last
** four bytes of the key are different from R. If the last four
** bytes equal R then jump immediately to P2.
** the final varint (the rowid) matches K. Check to see if the
** final varint is different from R. If it equals R then jump
** immediately to P2.
*/
sqlite3BtreeKey(pCrsr, nKey - 4, 4, (char*)&v);
v = keyToInt(v);
rc = sqlite3VdbeIdxRowid(pCrsr, &v);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( v==R ){
pc = pOp->p2 - 1;
break;
}
/* The last four bytes of the key are different from R. Convert the
** last four bytes of the key into an integer and push it onto the
** stack. (These bytes are the record number of an entry that
** violates a UNIQUE constraint.)
/* The final varint of the key is different from R. Push it onto
** the stack. (The record number of an entry that violates a UNIQUE
** constraint.)
*/
pTos++;
pTos->i = v;
@ -3601,17 +3623,21 @@ case OP_IdxPut: {
const char *zKey = pTos->z;
if( pOp->p2 ){
int res;
int len;
u64 n;
assert( nKey >= 4 );
rc = sqlite3BtreeMoveto(pCrsr, zKey, nKey-4, &res);
/* 'len' is the length of the key minus the rowid at the end */
len = nKey-2;
while( zKey[len] && --len );
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
while( res!=0 ){
int c;
sqlite3BtreeKeySize(pCrsr, &n);
if( n==nKey
/* FIX ME - the sqlite2BtreeKeyCompare() function is a temporary hack */
&& sqlite2BtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &c)==SQLITE_OK
&& c==0
if( n==nKey
&& sqlite3VdbeIdxKeyCompare(pCrsr, len, zKey, 0, &c)==SQLITE_OK
&& c==0
){
rc = SQLITE_CONSTRAINT;
if( pOp->p3 && pOp->p3[0] ){
@ -3627,6 +3653,7 @@ case OP_IdxPut: {
}
}
}
assert( p->aCsr[i].intKey==0 );
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( p->aCsr[i].deferredMoveto==0 );
}
@ -3661,10 +3688,9 @@ case OP_IdxDelete: {
/* Opcode: IdxRecno P1 * *
**
** Push onto the stack an integer which is the last 4 bytes of the
** the key to the current entry in index P1. These 4 bytes should
** be the record number of the table entry to which this index entry
** points.
** Push onto the stack an integer which is the varint located at the
** end of the index key pointed to by cursor P1. These integer should be
** the record number of the table entry to which this index entry points.
**
** See also: Recno, MakeIdxKey.
*/
@ -3675,18 +3701,41 @@ case OP_IdxRecno: {
assert( i>=0 && i<p->nCursor );
pTos++;
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
i64 v;
u64 sz;
int len;
char buf[9];
assert( p->aCsr[i].deferredMoveto==0 );
assert( p->aCsr[i].intKey==0 );
/* Read the final 9 bytes of the key into buf[]. If the whole key is
** less than 9 bytes then just load the whole thing. Set len to the
** number of bytes read.
*/
sqlite3BtreeKeySize(pCrsr, &sz);
if( sz<sizeof(i64) ){
len = ((sz>9)?9:sz);
rc = sqlite3BtreeKey(pCrsr, sz-len, len, buf);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
len--;
if( buf[len]&0x80 ){
/* If the last byte read has the 0x80 bit set, then the key does
** not end with a varint. Push a NULL onto the stack instead.
*/
pTos->flags = MEM_Null;
}else{
sqlite3BtreeKey(pCrsr, sz - sizeof(i64), sizeof(i64), (char*)&v);
v = keyToInt(v);
pTos->i = v;
/* Find the start of the varint by searching backwards for a 0x00
** byte. If one does not exists, then intepret the whole 9 bytes as a
** varint.
*/
while( len && buf[len-1] ){
len--;
}
sqlite3GetVarint(&buf[len], &sz);
pTos->flags = MEM_Int;
pTos->i = sz;
}
}else{
pTos->flags = MEM_Null;
@ -3732,8 +3781,7 @@ case OP_IdxGE: {
Stringify(pTos);
assert( p->aCsr[i].deferredMoveto==0 );
/* FIX ME - the sqlite2BtreeKeyCompare() function is a temporary hack */
rc = sqlite2BtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
rc = sqlite3VdbeIdxKeyCompare(pCrsr, pTos->n, pTos->z, 0, &res);
if( rc!=SQLITE_OK ){
break;
}

View 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.74 2004/05/12 11:24:03 danielk1977 Exp $
** $Id: vdbe.h,v 1.75 2004/05/13 05:16:17 danielk1977 Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -108,7 +108,6 @@ void sqlite3VdbeTrace(Vdbe*,FILE*);
void sqlite3VdbeCompressSpace(Vdbe*,int);
int sqlite3VdbeReset(Vdbe*,char **);
int sqliteVdbeSetVariables(Vdbe*,int,const char**);
int sqlite3VdbeKeyCompare(void*,int,const unsigned char*,int,
const unsigned char*);
int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
#endif

View File

@ -322,3 +322,5 @@ int sqlite3VdbeSerialPut(unsigned char *, const Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(BtCursor*, int , const unsigned char*, int, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT statement.
#
# $Id: insert.test,v 1.16 2004/05/11 09:50:02 danielk1977 Exp $
# $Id: insert.test,v 1.17 2004/05/13 05:16:17 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -145,13 +145,17 @@ do_test insert-3.1 {
SELECT * from test2;
}
} {}
# Update for sqlite v3:
# Change the 111 to '111' in the following two test cases, because
# the default value is being inserted as a string. TODO: It shouldn't be.
do_test insert-3.2 {
execsql {INSERT INTO test2(f2,f4) VALUES(-3.33,'hum')}
execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33}
execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
} {111 -3.33 hi hum {}}
do_test insert-3.3 {
execsql {INSERT INTO test2(f1,f2,f5) VALUES(22,-4.44,'wham')}
execsql {SELECT * FROM test2 WHERE f1=111 AND f2=-3.33}
execsql {SELECT * FROM test2 WHERE f1='111' AND f2=-3.33}
} {111 -3.33 hi hum {}}
do_test insert-3.4 {
execsql {SELECT * FROM test2 WHERE f1=22 AND f2=-4.44}

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
# $Id: select2.test,v 1.18 2002/04/02 13:26:11 drh Exp $
# $Id: select2.test,v 1.19 2004/05/13 05:16:17 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -83,24 +83,26 @@ do_test select2-3.1 {
execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
} {500}
# SQLite v3: Change the expressions in the following four test cases
# from 1000=f2 to '1000'=f2. This is because fields read in using
# the COPY command have manifest type TEXT.
do_test select2-3.2a {
execsql {CREATE INDEX idx1 ON tbl2(f2)}
} {}
do_test select2-3.2b {
execsql {SELECT f1 FROM tbl2 WHERE 1000=f2}
execsql {SELECT f1 FROM tbl2 WHERE '1000'=f2}
} {500}
do_test select2-3.2c {
execsql {SELECT f1 FROM tbl2 WHERE f2=1000}
execsql {SELECT f1 FROM tbl2 WHERE f2='1000'}
} {500}
do_test select2-3.2d {
set sqlite_search_count 0
execsql {SELECT * FROM tbl2 WHERE 1000=f2}
execsql {SELECT * FROM tbl2 WHERE '1000'=f2}
set sqlite_search_count
} {3}
do_test select2-3.2e {
set sqlite_search_count 0
execsql {SELECT * FROM tbl2 WHERE f2=1000}
execsql {SELECT * FROM tbl2 WHERE f2='1000'}
set sqlite_search_count
} {3}

View File

@ -12,7 +12,7 @@
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
# $Id: select4.test,v 1.13 2003/02/02 12:41:27 drh Exp $
# $Id: select4.test,v 1.14 2004/05/13 05:16:17 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -196,9 +196,14 @@ do_test select4-4.1.1 {
ORDER BY log;
}
} {5}
# Update for sqlite 3:
# Change the "UNION ALL SELECT 6" in each of the select statements
# for the next three test cases to "UNION ALL SELECT '6'". This is
# to accomadate manifest typing.
do_test select4-4.1.2 {
execsql {
SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
SELECT DISTINCT log FROM t1 UNION ALL SELECT '6'
INTERSECT
SELECT n FROM t1 WHERE log=3
ORDER BY log;
@ -207,7 +212,7 @@ do_test select4-4.1.2 {
do_test select4-4.1.3 {
execsql {
CREATE TABLE t2 AS
SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
SELECT DISTINCT log FROM t1 UNION ALL SELECT '6'
INTERSECT
SELECT n FROM t1 WHERE log=3
ORDER BY log;
@ -218,7 +223,7 @@ execsql {DROP TABLE t2}
do_test select4-4.1.4 {
execsql {
CREATE TABLE t2 AS
SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
SELECT DISTINCT log FROM t1 UNION ALL SELECT '6'
INTERSECT
SELECT n FROM t1 WHERE log=3
ORDER BY log DESC;
@ -469,16 +474,18 @@ do_test select4-7.4 {
# Make sure DISTINCT works appropriately on TEXT and NUMERIC columns.
#
# Update for sqlite v3:
# Insert X+0.0 instead of X to make sure X has manifest type NUMERIC.
do_test select4-8.1 {
execsql {
BEGIN;
CREATE TABLE t3(a text, b float, c text);
INSERT INTO t3 VALUES(1, 1.1, '1.1');
INSERT INTO t3 VALUES(2, 1.10, '1.10');
INSERT INTO t3 VALUES(3, 1.10, '1.1');
INSERT INTO t3 VALUES(4, 1.1, '1.10');
INSERT INTO t3 VALUES(5, 1.2, '1.2');
INSERT INTO t3 VALUES(6, 1.3, '1.3');
INSERT INTO t3 VALUES(1, 1.1 + 0.0, '1.1');
INSERT INTO t3 VALUES(2, 1.10 + 0.0, '1.10');
INSERT INTO t3 VALUES(3, 1.10 + 0.0, '1.1');
INSERT INTO t3 VALUES(4, 1.1 + 0.0, '1.10');
INSERT INTO t3 VALUES(5, 1.2 + 0.0, '1.2');
INSERT INTO t3 VALUES(6, 1.3 + 0.0, '1.3');
COMMIT;
}
execsql {