SQLite

Check-in [58ea768c3e]
Login

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

Overview
Comment:Fix a bug in the sqlite3_changes() function reported on the mailing list. (CVS 3868)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 58ea768c3e9905bd9db137f1b31dd3dd6c6001d0
User & Date: drh 2007-04-25 11:28:17.000
Context
2007-04-25
11:32
Fix duplicate test IDs in the test suite. No changes to code. Ticket #2319. (CVS 3869) (check-in: 0935cdf82a user: drh tags: trunk)
11:28
Fix a bug in the sqlite3_changes() function reported on the mailing list. (CVS 3868) (check-in: 58ea768c3e user: drh tags: trunk)
2007-04-24
17:35
This fixes a missed case in check-in (3866). Do not apply patch (3866) without also applying this patch. (CVS 3867) (check-in: 66c2fa0836 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/legacy.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: legacy.c,v 1.16 2006/09/15 07:28:50 drh Exp $
*/

#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: legacy.c,v 1.17 2007/04/25 11:28:17 drh Exp $
*/

#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
){
  int rc = SQLITE_OK;
  const char *zLeftover;
  sqlite3_stmt *pStmt = 0;
  char **azCols = 0;

  int nRetry = 0;
  int nChange = 0;
  int nCallback;

  if( zSql==0 ) return SQLITE_OK;
  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }

    db->nChange += nChange;
    nCallback = 0;

    nCol = sqlite3_column_count(pStmt);
    azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1);
    if( azCols==0 ){
      goto exec_out;
    }







<



















<







40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
){
  int rc = SQLITE_OK;
  const char *zLeftover;
  sqlite3_stmt *pStmt = 0;
  char **azCols = 0;

  int nRetry = 0;

  int nCallback;

  if( zSql==0 ) return SQLITE_OK;
  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }


    nCallback = 0;

    nCol = sqlite3_column_count(pStmt);
    azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1);
    if( azCols==0 ){
      goto exec_out;
    }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3_finalize(pStmt);
        pStmt = 0;
        if( db->pVdbe==0 ){
          nChange = db->nChange;
        }
        if( rc!=SQLITE_SCHEMA ){
          nRetry = 0;
          zSql = zLeftover;
          while( isspace((unsigned char)zSql[0]) ) zSql++;
        }
        break;
      }







<
<
<







95
96
97
98
99
100
101



102
103
104
105
106
107
108
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3_finalize(pStmt);
        pStmt = 0;



        if( rc!=SQLITE_SCHEMA ){
          nRetry = 0;
          zSql = zLeftover;
          while( isspace((unsigned char)zSql[0]) ) zSql++;
        }
        break;
      }
Changes to test/laststmtchanges.test.
45
46
47
48
49
50
51










52
53
54

55
56
57
58
59
60
61
# changes() set properly after update
do_test laststmtchanges-1.2 {
    catchsql {
        update t0 set x=3 where x=1;
        select changes(), total_changes();
    }
} {0 {5 13}}











# changes() unchanged within an update statement
do_test laststmtchanges-1.3 {

    catchsql {
        update t0 set x=x+changes() where x=3;
        select count() from t0 where x=8;
    }
} {0 5}

# changes() set properly after update on table where no rows changed







>
>
>
>
>
>
>
>
>
>



>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# changes() set properly after update
do_test laststmtchanges-1.2 {
    catchsql {
        update t0 set x=3 where x=1;
        select changes(), total_changes();
    }
} {0 {5 13}}

# There was some goofy change-counting logic in sqlite3_exec() that
# appears to have been left over from SQLite version 2.  This test
# makes sure it has been removed.
#
do_test laststmtchanges-1.2.1 {
    db cache flush
    sqlite3_exec_printf db {update t0 set x=4 where x=3; select 1;} {}
    execsql {select changes()}
} {5}

# changes() unchanged within an update statement
do_test laststmtchanges-1.3 {
    execsql {update t0 set x=3 where x=4}
    catchsql {
        update t0 set x=x+changes() where x=3;
        select count() from t0 where x=8;
    }
} {0 5}

# changes() set properly after update on table where no rows changed