SQLite

Check-in [5aaa2939ba]
Login

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

Overview
Comment:Make sure a LIMIT clause on a SELECT cleans up the vdbe stack so that if it occurs inside a trigger, it won't cause a stack overflow. Ticket #640. (CVS 1282)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5aaa2939baa972231def086ed5f9d9ba63302532
User & Date: drh 2004-03-02 18:37:41.000
Context
2004-03-03
01:51
A vdbe stack element might have a string value even after a call to Integerify(). Ticket #641. (CVS 1283) (check-in: 3cac4b7b52 user: drh tags: trunk)
2004-03-02
18:37
Make sure a LIMIT clause on a SELECT cleans up the vdbe stack so that if it occurs inside a trigger, it won't cause a stack overflow. Ticket #640. (CVS 1282) (check-in: 5aaa2939ba user: drh tags: trunk)
2004-02-29
15:18
Updated aclocal.m4 and configure. (CVS 1281) (check-in: 76d42921a4 user: a.rottmann tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.159 2004/02/25 13:47:33 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.160 2004/03/02 18:37:41 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
static void generateSortTail(
  Select *p,       /* The SELECT statement */
  Vdbe *v,         /* Generate code into this VDBE */
  int nColumn,     /* Number of columns of data */
  int eDest,       /* Write the sorted results here */
  int iParm        /* Optional parameter associated with eDest */
){
  int end = sqliteVdbeMakeLabel(v);

  int addr;
  if( eDest==SRT_Sorter ) return;
  sqliteVdbeAddOp(v, OP_Sort, 0, 0);
  addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
  if( p->iOffset>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  }
  if( p->iLimit>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end);
  }
  switch( eDest ){
    case SRT_Callback: {
      sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
      break;
    }
    case SRT_Table:







|
>



|






|







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
static void generateSortTail(
  Select *p,       /* The SELECT statement */
  Vdbe *v,         /* Generate code into this VDBE */
  int nColumn,     /* Number of columns of data */
  int eDest,       /* Write the sorted results here */
  int iParm        /* Optional parameter associated with eDest */
){
  int end1 = sqliteVdbeMakeLabel(v);
  int end2 = sqliteVdbeMakeLabel(v);
  int addr;
  if( eDest==SRT_Sorter ) return;
  sqliteVdbeAddOp(v, OP_Sort, 0, 0);
  addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
  if( p->iOffset>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  }
  if( p->iLimit>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
  }
  switch( eDest ){
    case SRT_Callback: {
      sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
      break;
    }
    case SRT_Table:
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622


623
624
625
626
627
628
629
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
      sqliteVdbeAddOp(v, OP_Goto, 0, end);
      break;
    }
    case SRT_Subroutine: {
      int i;
      for(i=0; i<nColumn; i++){
        sqliteVdbeAddOp(v, OP_Column, -1-i, i);
      }
      sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
    default: {
      /* Do nothing */
      break;
    }
  }
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeResolveLabel(v, end);


  sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
}

/*
** Generate code that will tell the VDBE the datatypes of
** columns in the result set.
**







|

















|
>
>







598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
      sqliteVdbeAddOp(v, OP_Goto, 0, end1);
      break;
    }
    case SRT_Subroutine: {
      int i;
      for(i=0; i<nColumn; i++){
        sqliteVdbeAddOp(v, OP_Column, -1-i, i);
      }
      sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
      sqliteVdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
    default: {
      /* Do nothing */
      break;
    }
  }
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeResolveLabel(v, end2);
  sqliteVdbeAddOp(v, OP_Pop, 1, 0);
  sqliteVdbeResolveLabel(v, end1);
  sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
}

/*
** Generate code that will tell the VDBE the datatypes of
** columns in the result set.
**
Changes to test/misc3.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc3.test,v 1.8 2004/02/24 01:04:12 drh Exp $

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

# Ticket #529.  Make sure an ABORT does not damage the in-memory cache
# that will be used by subsequent statements in the same transaction.
#







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc3.test,v 1.9 2004/03/02 18:37:42 drh Exp $

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

# Ticket #529.  Make sure an ABORT does not damage the in-memory cache
# that will be used by subsequent statements in the same transaction.
#
246
247
248
249
250
251
252
253




































254
  execsql {EXPLAIN COMMIT}
  catchsql {COMMIT}
} {0 {}}
do_test misc3-6.3 {
  execsql {BEGIN; EXPLAIN ROLLBACK}
  catchsql {ROLLBACK}
} {0 {}}





































finish_test








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

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  execsql {EXPLAIN COMMIT}
  catchsql {COMMIT}
} {0 {}}
do_test misc3-6.3 {
  execsql {BEGIN; EXPLAIN ROLLBACK}
  catchsql {ROLLBACK}
} {0 {}}

# Ticket #640:  vdbe stack overflow with a LIMIT clause on a SELECT inside
# of a trigger.
#
do_test misc3-7.1 {
  execsql {
    BEGIN;
    CREATE TABLE y1(a);
    CREATE TABLE y2(b);
    CREATE TABLE y3(c);
    CREATE TRIGGER r1 AFTER DELETE ON y1 FOR EACH ROW BEGIN
      INSERT INTO y3(c) SELECT b FROM y2 ORDER BY b LIMIT 1;
    END;
    INSERT INTO y1 VALUES(1);
    INSERT INTO y1 VALUES(2);
    INSERT INTO y1 SELECT a+2 FROM y1;
    INSERT INTO y1 SELECT a+4 FROM y1;
    INSERT INTO y1 SELECT a+8 FROM y1;
    INSERT INTO y1 SELECT a+16 FROM y1;
    INSERT INTO y2 SELECT a FROM y1;
    COMMIT;
    SELECT count(*) FROM y1;
  }
} 32
do_test misc3-7.2 {
  execsql {
    DELETE FROM y1;
    SELECT count(*) FROM y1;
  }
} 0
do_test misc3-7.3 {
  execsql {
    SELECT count(*) FROM y3;
  }
} 32


finish_test