/ Check-in [bb83642e]
Login

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

Overview
Comment:Fix for bug #11: Output the correct row count when and INSERT does an IGNORE action. (CVS 524)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:bb83642e9a6c1c9ade861618496933c9f922a8f8
User & Date: drh 2002-04-09 03:28:01
Context
2002-04-12
03:55
Fix for bug #16: Check for invalid functions in the VALUES clause of an INSERT statement. (CVS 525) check-in: 43a77f01 user: drh tags: trunk
2002-04-09
03:28
Fix for bug #11: Output the correct row count when and INSERT does an IGNORE action. (CVS 524) check-in: bb83642e user: drh tags: trunk
03:15
Fix for bug #10: Pop the stack by the right amount on an IGNORE so that the stack does not grow without bound. (CVS 523) check-in: f46acfc3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
178
179
180
181
182
183
184






185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
**    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 INSERT statements in SQLite.
**
** $Id: insert.c,v 1.49 2002/04/09 03:15:07 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
  sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
  sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
    sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
  }
  pParse->nTab += idx;







  /* If the data source is a SELECT statement, then we have to create
  ** a loop because there might be multiple rows of data.  If the data
  ** source is an expression list, then exactly one row will be inserted
  ** and the loop is not used.
  */
  if( srcTab>=0 ){
    if( db->flags & SQLITE_CountRows ){
      sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
    }
    iBreak = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
    iCont = sqliteVdbeCurrentAddr(v);
  }

  /* Push the record number for the new entry onto the stack.  The
  ** record number is a randomly generate integer created by NewRecno
................................................................................
  /* Generate code to check constraints and generate index keys and
  ** do the insertion.
  */
  endOfLoop = sqliteVdbeMakeLabel(v);
  sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0, onError, endOfLoop);
  sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);

  /* If inserting from a SELECT, keep a count of the number of
  ** rows inserted.
  */
  if( srcTab>=0 && (db->flags & SQLITE_CountRows)!=0 ){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }

  /* The bottom of the loop, if the data source is a SELECT statement
  */
  sqliteVdbeResolveLabel(v, endOfLoop);
  if( srcTab>=0 ){
................................................................................
  /*
  ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
    sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
    if( srcTab<0 ){
      sqliteVdbeAddOp(v, OP_Integer, 1, 0);
    }
    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
  }

insert_cleanup:
  if( pList ) sqliteExprListDelete(pList);
  if( pSelect ) sqliteSelectDelete(pSelect);
  sqliteIdListDelete(pColumn);







|







 







>
>
>
>
>
>







<
<
<







 







|
<

|







 







<
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197



198
199
200
201
202
203
204
...
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
...
284
285
286
287
288
289
290



291
292
293
294
295
296
297
**    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 INSERT statements in SQLite.
**
** $Id: insert.c,v 1.50 2002/04/09 03:28:01 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
  sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
  sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
    sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
  }
  pParse->nTab += idx;

  /* Initialize the count of rows to be inserted
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
  }

  /* If the data source is a SELECT statement, then we have to create
  ** a loop because there might be multiple rows of data.  If the data
  ** source is an expression list, then exactly one row will be inserted
  ** and the loop is not used.
  */
  if( srcTab>=0 ){



    iBreak = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
    iCont = sqliteVdbeCurrentAddr(v);
  }

  /* Push the record number for the new entry onto the stack.  The
  ** record number is a randomly generate integer created by NewRecno
................................................................................
  /* Generate code to check constraints and generate index keys and
  ** do the insertion.
  */
  endOfLoop = sqliteVdbeMakeLabel(v);
  sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0, onError, endOfLoop);
  sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);

  /* Update the count of rows that are inserted

  */
  if( (db->flags & SQLITE_CountRows)!=0 ){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }

  /* The bottom of the loop, if the data source is a SELECT statement
  */
  sqliteVdbeResolveLabel(v, endOfLoop);
  if( srcTab>=0 ){
................................................................................
  /*
  ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
    sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);



    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
  }

insert_cleanup:
  if( pList ) sqliteExprListDelete(pList);
  if( pSelect ) sqliteSelectDelete(pSelect);
  sqliteIdListDelete(pColumn);

Changes to test/conflict.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
422
423
424
425
426
427
428





































429
430
431
432
433
434
435
436
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.9 2002/04/09 03:15:08 drh Exp $

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

# Create tables for the first group of tests.
#
do_test conflict-1.0 {
................................................................................
} {51}
do_test conflict-7.7 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {1}







































do_test insert-99.1 {
  set x [execsql {PRAGMA integrity_check}]
  if {$x==""} {set x ok}
  set x
} {ok}

finish_test







|







 







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








9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
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
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.10 2002/04/09 03:28:01 drh Exp $

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

# Create tables for the first group of tests.
#
do_test conflict-1.0 {
................................................................................
} {51}
do_test conflict-7.7 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {1}

# Make sure the row count is right for rows that are ignored on
# an insert.
#
do_test conflict-8.1 {
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2);
  }
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,3);
  }
} {1}
do_test conflict-8.2 {
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,4);
  }
} {0}
do_test conflict-8.3 {
  execsql {
    INSERT OR REPLACE INTO t1 VALUES(2,4);
  }
} {1}
do_test conflict-8.4 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT * FROM t1;
  }
} {0}
do_test conflict-8.5 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
  }
} {2}
do_test conflict-8.6 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
  }
} {3}

do_test insert-99.1 {
  set x [execsql {PRAGMA integrity_check}]
  if {$x==""} {set x ok}
  set x
} {ok}

finish_test