/ Check-in [e93aecc0]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:If an SQL function makes a recursive call to do an INSERT into the same database, make sure that the last_insert_rowid() for that INSERT is recorded.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e93aecc090c2a1d3c231bb2bde044886eff0bdf7
User & Date: drh 2014-09-26 01:10:02
Context
2014-09-26
02:41
Fix the "PRAGMA integrity_check" command so that it avoids formatting error message context messages until it actually needs to generate an error message. This avoids much formatting, and hence greatly improves the performance of "PRAGMA integrity_check" in the common case when there are no errors. It also makes the code a little smaller. check-in: 83913515 user: drh tags: trunk
01:10
If an SQL function makes a recursive call to do an INSERT into the same database, make sure that the last_insert_rowid() for that INSERT is recorded. check-in: e93aecc0 user: drh tags: trunk
2014-09-25
17:42
Minor code reformatting and comment change, to improve clarity. No logic changes. check-in: baeb72a3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

1555
1556
1557
1558
1559
1560
1561

1562
1563
1564
1565
1566
1567
1568
  assert( pOp->p4type==P4_FUNCDEF );
  ctx.pFunc = pOp->p4.pFunc;
  ctx.iOp = pc;
  ctx.pVdbe = p;
  MemSetTypeFlag(ctx.pOut, MEM_Null);
  ctx.fErrorOrAux = 0;
  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */


  /* If the function returned an error, throw an exception */
  if( ctx.fErrorOrAux ){
    if( ctx.isError ){
      sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut));
      rc = ctx.isError;
    }







>







1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
  assert( pOp->p4type==P4_FUNCDEF );
  ctx.pFunc = pOp->p4.pFunc;
  ctx.iOp = pc;
  ctx.pVdbe = p;
  MemSetTypeFlag(ctx.pOut, MEM_Null);
  ctx.fErrorOrAux = 0;
  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
  lastRowid = db->lastRowid;  /* Remember rowid changes made by xFunc */

  /* If the function returned an error, throw an exception */
  if( ctx.fErrorOrAux ){
    if( ctx.isError ){
      sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut));
      rc = ctx.isError;
    }

Changes to test/rowid.test.

697
698
699
700
701
702
703


704












705
  db eval {DELETE FROM t7temp; INSERT INTO t7temp VALUES(1);}
  restore_prng_state
  catchsql {
    INSERT INTO t7 VALUES(NULL,'x');
  }
} {1 {database or disk is full}}
















finish_test







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

697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
  db eval {DELETE FROM t7temp; INSERT INTO t7temp VALUES(1);}
  restore_prng_state
  catchsql {
    INSERT INTO t7 VALUES(NULL,'x');
  }
} {1 {database or disk is full}}

# INSERTs that happen inside of nested function calls are recorded
# by last_insert_rowid.
#
proc rowid_addrow_func {n} {
  db eval {INSERT INTO t13(rowid,x) VALUES($n,$n*$n)}
  return [db last_insert_rowid]
}
db function addrow rowid_addrow_func
do_execsql_test rowid-13.1 {
  CREATE TABLE t13(x);
  INSERT INTO t13(rowid,x) VALUES(1234,5);
  SELECT rowid, x, addrow(rowid+1000), '|' FROM t13 LIMIT 3;
  SELECT last_insert_rowid();
} {1234 5 2234 | 2234 4990756 3234 | 3234 10458756 4234 | 4234}

finish_test