/ Check-in [4debc8db]
Login

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

Overview
Comment:Bug fix: bad code was generated for when the first operand of a CASE was NULL. (CVS 598)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:4debc8db929fdc201759ba211acdeadc4e30e8af
User & Date: drh 2002-05-30 02:35:12
Context
2002-05-30
12:27
Once it is opened, leave the checkpoint journal file open for the duration of a transaction, rather than closing it and reopening it for each statement. (Ticket #53) (CVS 599) check-in: 7a24336d user: drh tags: trunk
02:35
Bug fix: bad code was generated for when the first operand of a CASE was NULL. (CVS 598) check-in: 4debc8db user: drh tags: trunk
2002-05-29
23:22
Built-in aggregate functions (MIN, SUM, AVG, etc) should ignore NULL entires. (CVS 597) check-in: 19ae12be user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
...
976
977
978
979
980
981
982

983
984
985
986
987
988
989
....
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.64 2002/05/26 20:54:33 drh Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
      sqliteExprCode(pParse, pExpr->pLeft);
      break;
    }
    case TK_CASE: {
      int expr_end_label;
      int null_result_label;
      int jumpInst;

      int addr;
      int nExpr;
      int i;

      assert(pExpr->pList);
      assert((pExpr->pList->nExpr % 2) == 0);
      assert(pExpr->pList->nExpr > 0);
      nExpr = pExpr->pList->nExpr;
      expr_end_label = sqliteVdbeMakeLabel(v);
      null_result_label = sqliteVdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqliteExprCode(pParse, pExpr->pLeft);
        sqliteVdbeAddOp(v, OP_IsNull, -1, expr_end_label);
      }
      for(i=0; i<nExpr; i=i+2){
        sqliteExprCode(pParse, pExpr->pList->a[i].pExpr);
        sqliteVdbeAddOp(v, OP_IsNull, -1, null_result_label);
        if( pExpr->pLeft ){
          sqliteVdbeAddOp(v, OP_Dup, 1, 1);
          jumpInst = sqliteVdbeAddOp(v, OP_Ne, 0, 0);
................................................................................
      }else{
        sqliteVdbeAddOp(v, OP_String, 0, 0);
      }
      sqliteVdbeResolveLabel(v, expr_end_label);
      if( pExpr->pLeft ){
        sqliteVdbeAddOp(v, OP_Pull, 1, 0);
        sqliteVdbeAddOp(v, OP_Pop, 1, 0);

      }
    }
    break;
  }
}

/*
................................................................................
      sqliteVdbeAddOp(v, OP_Goto, 0, dest);
      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
      sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);
      break;
    }
    default: {
      sqliteExprCode(pParse, pExpr);
      sqliteVdbeAddOp(v, OP_Not, 0, 0);
      sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest);
      break;
    }
  }
}

/*
** Do a deep comparison of two expression trees.  Return TRUE (non-zero)







|







 







>












|







 







>







 







|
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
....
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.65 2002/05/30 02:35:12 drh Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
      sqliteExprCode(pParse, pExpr->pLeft);
      break;
    }
    case TK_CASE: {
      int expr_end_label;
      int null_result_label;
      int jumpInst;
      int nullBypassInst;
      int addr;
      int nExpr;
      int i;

      assert(pExpr->pList);
      assert((pExpr->pList->nExpr % 2) == 0);
      assert(pExpr->pList->nExpr > 0);
      nExpr = pExpr->pList->nExpr;
      expr_end_label = sqliteVdbeMakeLabel(v);
      null_result_label = sqliteVdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqliteExprCode(pParse, pExpr->pLeft);
        nullBypassInst = sqliteVdbeAddOp(v, OP_IsNull, -1, 0);
      }
      for(i=0; i<nExpr; i=i+2){
        sqliteExprCode(pParse, pExpr->pList->a[i].pExpr);
        sqliteVdbeAddOp(v, OP_IsNull, -1, null_result_label);
        if( pExpr->pLeft ){
          sqliteVdbeAddOp(v, OP_Dup, 1, 1);
          jumpInst = sqliteVdbeAddOp(v, OP_Ne, 0, 0);
................................................................................
      }else{
        sqliteVdbeAddOp(v, OP_String, 0, 0);
      }
      sqliteVdbeResolveLabel(v, expr_end_label);
      if( pExpr->pLeft ){
        sqliteVdbeAddOp(v, OP_Pull, 1, 0);
        sqliteVdbeAddOp(v, OP_Pop, 1, 0);
        sqliteVdbeChangeP2(v, nullBypassInst, sqliteVdbeCurrentAddr(v));
      }
    }
    break;
  }
}

/*
................................................................................
      sqliteVdbeAddOp(v, OP_Goto, 0, dest);
      sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
      sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);
      break;
    }
    default: {
      sqliteExprCode(pParse, pExpr);
      sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest);

      break;
    }
  }
}

/*
** Do a deep comparison of two expression trees.  Return TRUE (non-zero)

Changes to test/expr.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
348
349
350
351
352
353
354
355


356
357
358
359
360
361
362
#    May you find forgiveness for yourself and forgive others.
#    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 expressions.
#
# $Id: expr.test,v 1.21 2002/05/27 01:04:51 drh Exp $

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

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
................................................................................
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} {{}}
test_expr expr-case.8 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} {{}}
test_expr expr-case.9 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error
test_expr expr-case.10 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}}
test_expr expr-case.11 {i1=7} \


	{ CASE WHEN i1 < 5 THEN 'low' 
	       WHEN i1 < 10 THEN 'medium' 
               WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium


# The sqliteExprIfFalse and sqliteExprIfTrue routines are only
# executed as part of a WHERE clause.  Create a table suitable







|







 







|
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#    May you find forgiveness for yourself and forgive others.
#    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 expressions.
#
# $Id: expr.test,v 1.22 2002/05/30 02:35:12 drh Exp $

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

# Create a table to work with.
#
execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
................................................................................
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} {{}}
test_expr expr-case.8 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN NULL THEN 'two' ELSE 'error' END} {{}}
test_expr expr-case.9 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error
test_expr expr-case.10 {i1=3} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}}
test_expr expr-case.11 {i1=null} \
	{CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 3 END} {{}}
test_expr expr-case.12 {i1=7} \
	{ CASE WHEN i1 < 5 THEN 'low' 
	       WHEN i1 < 10 THEN 'medium' 
               WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium


# The sqliteExprIfFalse and sqliteExprIfTrue routines are only
# executed as part of a WHERE clause.  Create a table suitable