/ Check-in [982aa335]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Correctly handle comparing an INTEGER PRIMARY KEY against a floating point number. Ticket #377. (CVS 1045)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 982aa3356bcc217003cd9e6a829619219c334797
User & Date: drh 2003-07-06 17:22:25
Context
2003-07-07
00:10
Update the NULL-handling document to show current behavior of OCELOT. (CVS 1046) check-in: 1d4c92c7 user: drh tags: trunk
2003-07-06
17:22
Correctly handle comparing an INTEGER PRIMARY KEY against a floating point number. Ticket #377. (CVS 1045) check-in: 982aa335 user: drh tags: trunk
2003-07-01
18:13
Make sure indices in ATTACH-ed databases are put into the right hash table. Ticket #354. (CVS 1044) check-in: eb458283 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
....
2263
2264
2265
2266
2267
2268
2269
























2270
2271
2272
2273
2274
2275
2276
....
2290
2291
2292
2293
2294
2295
2296


2297
2298








2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.231 2003/06/29 20:25:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
................................................................................
case OP_AddImm: {
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  Integerify(p, tos);
  aStack[tos].i += pOp->p1;
  break;
}

























/* Opcode: MustBeInt P1 P2 *
** 
** Force the top of the stack to be an integer.  If the top of the
** stack is not an integer and cannot be converted into an integer
** with out data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception.
................................................................................
    if( r!=aStack[tos].r ){
      goto mismatch;
    }
    aStack[tos].i = i;
  }else if( aStack[tos].flags & STK_Str ){
    int v;
    if( !toInt(zStack[tos], &v) ){


      goto mismatch;
    }








    p->aStack[tos].i = v;
  }else{
    goto mismatch;
  }
  Release(p, tos);
  p->aStack[tos].flags = STK_Int;
  break;

mismatch:
  if( pOp->p2==0 ){
    rc = SQLITE_MISMATCH;
    goto abort_due_to_error;
  }else{







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
|
|
>
>
>
>
>
>
>
>
|




|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
....
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
....
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.232 2003/07/06 17:22:25 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
................................................................................
case OP_AddImm: {
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  Integerify(p, tos);
  aStack[tos].i += pOp->p1;
  break;
}

/* Opcode: IsNumeric P1 P2 *
**
** Check the top of the stack to see if it is a numeric value.  A numeric
** value is an integer, a real number, or a string that looks like an 
** integer or a real number.  When P1==0, pop the stack and jump to P2
** if the value is numeric.  Otherwise fall through and leave the stack
** unchanged.  The sense of the test is inverted when P1==1.
*/
case OP_IsNumeric: {
  int tos = p->tos;
  int r;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  r = (aStack[tos].flags & (STK_Int|STK_Real))!=0 
           || (zStack[tos] && sqliteIsNumber(zStack[tos]));
  if( pOp->p1 ){
    r = !r;
  }
  if( r ){
    POPSTACK;
    pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: MustBeInt P1 P2 *
** 
** Force the top of the stack to be an integer.  If the top of the
** stack is not an integer and cannot be converted into an integer
** with out data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception.
................................................................................
    if( r!=aStack[tos].r ){
      goto mismatch;
    }
    aStack[tos].i = i;
  }else if( aStack[tos].flags & STK_Str ){
    int v;
    if( !toInt(zStack[tos], &v) ){
      double r;
      if( !sqliteIsNumber(zStack[tos]) ){
        goto mismatch;
      }
      Realify(p, tos);
      assert( (aStack[tos].flags & STK_Real)!=0 );
      v = aStack[tos].r;
      r = (double)v;
      if( r!=aStack[tos].r ){
        goto mismatch;
      }
    }
    aStack[tos].i = v;
  }else{
    goto mismatch;
  }
  Release(p, tos);
  aStack[tos].flags = STK_Int;
  break;

mismatch:
  if( pOp->p2==0 ){
    rc = SQLITE_MISMATCH;
    goto abort_due_to_error;
  }else{

Changes to src/where.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.79 2003/05/17 17:35:13 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
        assert( aExpr[k].p!=0 );
        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
        if( aExpr[k].idxLeft==iCur ){
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
        }
        sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
        aExpr[k].p = 0;
      }else{
        sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
................................................................................
        assert( aExpr[k].p!=0 );
        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
        if( aExpr[k].idxLeft==iCur ){
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqliteVdbeAddOp(v, OP_MustBeInt, 1, sqliteVdbeCurrentAddr(v)+1);
        pLevel->iMem = pParse->nMem++;
        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          testOp = OP_Ge;
        }else{
          testOp = OP_Gt;
        }







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.80 2003/07/06 17:22:25 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
        assert( aExpr[k].p!=0 );
        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
        if( aExpr[k].idxLeft==iCur ){
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqliteVdbeAddOp(v, OP_IsNumeric, 1, brk);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
        }
        sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
        aExpr[k].p = 0;
      }else{
        sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
................................................................................
        assert( aExpr[k].p!=0 );
        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
        if( aExpr[k].idxLeft==iCur ){
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        /* sqliteVdbeAddOp(v, OP_MustBeInt, 0, sqliteVdbeCurrentAddr(v)+1); */
        pLevel->iMem = pParse->nMem++;
        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          testOp = OP_Ge;
        }else{
          testOp = OP_Gt;
        }

Changes to test/rowid.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
412
413
414
415
416
417
418
419


420




















































421
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the magic ROWID column that is
# found on all tables.
#
# $Id: rowid.test,v 1.11 2003/06/01 01:10:33 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Basic ROWID functionality tests.
#
do_test rowid-1.1 {
................................................................................
  }
} {123 124}
do_test rowid-8.8 {
  execsql {
    SELECT rowid, * FROM t4;
  }
} {1 1 2 133 3 134}
























































finish_test







|







 








>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the magic ROWID column that is
# found on all tables.
#
# $Id: rowid.test,v 1.12 2003/07/06 17:22:25 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Basic ROWID functionality tests.
#
do_test rowid-1.1 {
................................................................................
  }
} {123 124}
do_test rowid-8.8 {
  execsql {
    SELECT rowid, * FROM t4;
  }
} {1 1 2 133 3 134}

# ticket #377: Comparison between integer primiary key and floating point
# values.
#
do_test rowid-9.1 {
  execsql {
    SELECT * FROM t3 WHERE a<123.5
  }
} {123}
do_test rowid-9.2 {
  execsql {
    SELECT * FROM t3 WHERE a<124.5
  }
} {123 124}
do_test rowid-9.3 {
  execsql {
    SELECT * FROM t3 WHERE a>123.5
  }
} {124}
do_test rowid-9.4 {
  execsql {
    SELECT * FROM t3 WHERE a>122.5
  }
} {123 124}
do_test rowid-9.5 {
  execsql {
    SELECT * FROM t3 WHERE a==123.5
  }
} {}
do_test rowid-9.6 {
  execsql {
    SELECT * FROM t3 WHERE a==123.000
  }
} {123}
do_test rowid-9.7 {
  execsql {
    SELECT * FROM t3 WHERE a>100.5 AND a<200.5
  }
} {123 124}
do_test rowid-9.8 {
  execsql {
    SELECT * FROM t3 WHERE a>'xyz';
  }
} {}
do_test rowid-9.9 {
  execsql {
    SELECT * FROM t3 WHERE a<'xyz';
  }
} {123 124}
do_test rowid-9.10 {
  execsql {
    SELECT * FROM t3 WHERE a>=122.9 AND a<=123.1
  }
} {123}


finish_test