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

Overview
Comment:Remove the sqlite4_last_insert_rowid() and related infrastructure, since in SQLite4 we no longer have a rowid. Other cleanup of the sqlite4.h file.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c92e61312fd26ab89807775eef73c77fa77da09d
User & Date: drh 2013-02-23 16:32:17.432
Context
2013-02-23
17:39
Factor out methods of sqlite4_env into a separate env.c source file. Add in the sqlite4_mm object. Remove deprecated interfaces. check-in: 1e83e737e4 user: drh tags: trunk
16:32
Remove the sqlite4_last_insert_rowid() and related infrastructure, since in SQLite4 we no longer have a rowid. Other cleanup of the sqlite4.h file. check-in: c92e61312f user: drh tags: trunk
14:16
Add the "Programmers Introduction To SQLite4" document outlining the desired API for SQLite4. check-in: a4782fccbe user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
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
  p = contextMalloc(context, n);
  if( p ){
    sqlite4_randomness(sqlite4_context_env(context), n, p);
    sqlite4_result_blob(context, (char*)p, n, SQLITE4_DYNAMIC, 0);
  }
}

/*
** Implementation of the last_insert_rowid() SQL function.  The return
** value is the same as the sqlite4_last_insert_rowid() API function.
*/
static void last_insert_rowid(
  sqlite4_context *context, 
  int NotUsed, 
  sqlite4_value **NotUsed2
){
  sqlite4 *db = sqlite4_context_db_handle(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
  ** wrapper around the sqlite4_last_insert_rowid() C/C++ interface
  ** function. */
  sqlite4_result_int64(context, sqlite4_last_insert_rowid(db));
}

/*
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite4_changes() C/C++ function and hence follows the same
** rules for counting changes.
*/







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







434
435
436
437
438
439
440

















441
442
443
444
445
446
447
  p = contextMalloc(context, n);
  if( p ){
    sqlite4_randomness(sqlite4_context_env(context), n, p);
    sqlite4_result_blob(context, (char*)p, n, SQLITE4_DYNAMIC, 0);
  }
}


















/*
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite4_changes() C/C++ function and hence follows the same
** rules for counting changes.
*/
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */
    FUNCTION(quote,              1, 0, 0, quoteFunc        ),
    FUNCTION(last_insert_rowid,  0, 0, 0, last_insert_rowid),
    FUNCTION(changes,            0, 0, 0, changes          ),
    FUNCTION(total_changes,      0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
  #ifdef SQLITE4_SOUNDEX
    FUNCTION(soundex,            1, 0, 0, soundexFunc      ),
  #endif
  #if 0 /*ndef SQLITE4_OMIT_LOAD_EXTENSION*/







<







1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */
    FUNCTION(quote,              1, 0, 0, quoteFunc        ),

    FUNCTION(changes,            0, 0, 0, changes          ),
    FUNCTION(total_changes,      0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
  #ifdef SQLITE4_SOUNDEX
    FUNCTION(soundex,            1, 0, 0, soundexFunc      ),
  #endif
  #if 0 /*ndef SQLITE4_OMIT_LOAD_EXTENSION*/
Changes to src/insert.c.
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
    if( pIdx!=pPk ){
      for(i=0; i<pPk->nColumn; i++){
        int idx = pPk->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn);
      }
    }
    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdx, regTmp, regKey);
    if( pIdx==pPk && (pPk->fIndex & IDX_IntPK)!=0 ){
      sqlite4VdbeChangeP5(v, OPFLAG_LASTROWID);
    }
    VdbeComment((v, "key for %s", pIdx->zName));

    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the regKey register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;







<
<
<







1315
1316
1317
1318
1319
1320
1321



1322
1323
1324
1325
1326
1327
1328
    if( pIdx!=pPk ){
      for(i=0; i<pPk->nColumn; i++){
        int idx = pPk->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn);
      }
    }
    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iIdx, regTmp, regKey);



    VdbeComment((v, "key for %s", pIdx->zName));

    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the regKey register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
    addr1 = sqlite4VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
  }else{
    addr1 = sqlite4VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
  }
  sqlite4VdbeAddOp2(v, OP_RowData, iSrc, regData);
  sqlite4VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
  sqlite4VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
  sqlite4VdbeChangeP4(v, -1, pDest->zName, 0);
  sqlite4VdbeAddOp2(v, OP_Next, iSrc, addr1);
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
    for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
    }
    assert( pSrcIdx );







|







1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
    addr1 = sqlite4VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
  }else{
    addr1 = sqlite4VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
  }
  sqlite4VdbeAddOp2(v, OP_RowData, iSrc, regData);
  sqlite4VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
  sqlite4VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_APPEND);
  sqlite4VdbeChangeP4(v, -1, pDest->zName, 0);
  sqlite4VdbeAddOp2(v, OP_Next, iSrc, addr1);
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
    for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
    }
    assert( pSrcIdx );
Changes to src/main.c.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#endif

/*
** Dummy function used as a unique symbol for SQLITE4_DYNAMIC
*/
void sqlite4_dynamic(void *pArg,void *p){ (void)pArg; (void)p; }

#ifndef SQLITE4_AMALGAMATION
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite4_version[] string constant
** contains the text of SQLITE4_VERSION macro. 
*/
const char sqlite4_version[] = SQLITE4_VERSION;
#endif

/* IMPLEMENTATION-OF: R-53536-42575 The sqlite4_libversion() function returns
** a pointer to the to the sqlite4_version[] string constant. 
*/
const char *sqlite4_libversion(void){ return SQLITE4_VERSION; }

/* IMPLEMENTATION-OF: R-63124-39300 The sqlite4_sourceid() function returns a
** pointer to a string constant whose value is the same as the







<
<
<
<
<
<
<







27
28
29
30
31
32
33







34
35
36
37
38
39
40
#endif

/*
** Dummy function used as a unique symbol for SQLITE4_DYNAMIC
*/
void sqlite4_dynamic(void *pArg,void *p){ (void)pArg; (void)p; }








/* IMPLEMENTATION-OF: R-53536-42575 The sqlite4_libversion() function returns
** a pointer to the to the sqlite4_version[] string constant. 
*/
const char *sqlite4_libversion(void){ return SQLITE4_VERSION; }

/* IMPLEMENTATION-OF: R-63124-39300 The sqlite4_sourceid() function returns a
** pointer to a string constant whose value is the same as the
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
    for(i=0; i<nIn; i++){
      aOut[i] = sqlite4_tolower(aIn[i]);
    }
  }
  return nIn;
}

/*
** Return the ROWID of the most recent insert
*/
sqlite4_int64 sqlite4_last_insert_rowid(sqlite4 *db){
  return db->lastRowid;
}

/*
** Return the number of changes in the most recent call to sqlite4_exec().
*/
int sqlite4_changes(sqlite4 *db){
  return db->nChange;
}








<
<
<
<
<
<
<







655
656
657
658
659
660
661







662
663
664
665
666
667
668
    for(i=0; i<nIn; i++){
      aOut[i] = sqlite4_tolower(aIn[i]);
    }
  }
  return nIn;
}








/*
** Return the number of changes in the most recent call to sqlite4_exec().
*/
int sqlite4_changes(sqlite4 *db){
  return db->nChange;
}

Changes to src/mem.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34



















35

36
37
38
39
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
/*
** 2013-01-01
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite4 memory
** management logic.
**
** Some of this will eventually fold into sqliteInt.h.


*/


/*
** object declarations
*/
typedef struct sqlite4_mm sqlite4_mm;
typedef struct sqlite4_mm_methods sqlite4_mm_methods;

/*
** Base class.  Each implementation extends this with additional
** fields specific to its own needs.  This needs to be public so that
** applications can supply their on customized memory allocators.
*/
struct sqlite4_mm {
  const sqlite4_mm_methods *pMethods;
};

/*



















** An instance of the following object defines a BESPOKE memory alloator

*/
struct sqlite4_mm_methods {
  int iVersion;
  void *(*xMalloc)(sqlite4_mm*, sqlite4_int64);
  void *(*xRealloc)(sqlite4_mm*, void*, sqlite4_int64);
  void (*xFree)(sqlite4_mm*, void*);
  sqlite4_int64 (*xMsize)(sqlite4_mm*, void*);
  int (*xMember)(sqlite4_mm*, const void*);
  void (*xBenign)(sqlite4_mm*, int);

  void (*xFinal)(sqlite4_mm*);
};

/*
** Available memory management types:
*/
typedef enum {
  SQLITE4_MM_SYSTEM,         /* Use the system malloc() */
  SQLITE4_MM_ONESIZE,        /* All allocations map to a fixed size */
  SQLITE4_MM_OVERFLOW,       /* Two allocators. Use A first; failover to B */
  SQLITE4_MM_COMPACT,        /* Like memsys3 from SQLite3 */
  SQLITE4_MM_ROBSON,         /* Like memsys5 from SQLite3 */
  SQLITE4_MM_LINEAR,         /* Allocate from a fixed buffer w/o free */

  SQLITE4_MM_DEBUG,          /* Debugging memory allocator */
  SQLITE4_MM_STATS,          /* Keep memory statistics */
  SQLITE4_MM_BESPOKE         /* Caller-defined implementation */
} sqlite4_mm_type;

/*
** Allocate a new memory manager.  Return NULL if unable.
*/
sqlite4_mm *sqlite4_mm_new(sqlite4_mm_type, ...);












<
<

<
>
>



















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









>







|
|
|
|
|
|
>

|
<







1
2
3
4
5
6
7
8
9
10
11


12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
75
76
77
78
79
80

81
82
83
84
85
86
87
/*
** 2013-01-01
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************


**

** This file defines the sqlite4_mm "SQLite4 Memory Manager" object and
** its interfaces.
*/


/*
** object declarations
*/
typedef struct sqlite4_mm sqlite4_mm;
typedef struct sqlite4_mm_methods sqlite4_mm_methods;

/*
** Base class.  Each implementation extends this with additional
** fields specific to its own needs.  This needs to be public so that
** applications can supply their on customized memory allocators.
*/
struct sqlite4_mm {
  const sqlite4_mm_methods *pMethods;
};

/*
** Memory statistics reporting
*/
typedef enum {
  SQLITE4_MMSTAT_OUT = 1,         /* Bytes of memory outstanding */
  SQLITE4_MMSTAT_UNITS = 2,       /* Separate allocations outstanding */
  SQLITE4_MMSTAT_SIZE = 3,        /* Size of the allocation */
  SQLITE4_MMSTAT_SZFAULT = 4,     /* Number of faults due to size */
  SQLITE4_MMSTAT_MEMFAULT = 5,    /* Number of faults due to out of space */
  SQLITE4_MMSTAT_FAULT = 6,       /* Total number of faults */
};

/*
** Bit flags for the 3rd parameter of xStat()
*/
#define SQLITE4_MMSTAT_HIGHWATER  0x01
#define SQLITE4_MMSTAT_RESET      0x02
#define SQLITE4_MMSTAT_HWRESET    0x03

/*
** An instance of the following object defines the methods on
** a BESPOKE memory allocator.
*/
struct sqlite4_mm_methods {
  int iVersion;
  void *(*xMalloc)(sqlite4_mm*, sqlite4_int64);
  void *(*xRealloc)(sqlite4_mm*, void*, sqlite4_int64);
  void (*xFree)(sqlite4_mm*, void*);
  sqlite4_int64 (*xMsize)(sqlite4_mm*, void*);
  int (*xMember)(sqlite4_mm*, const void*);
  void (*xBenign)(sqlite4_mm*, int);
  sqlite4_int64 (*xStat)(sqlite4_mm*, sqlite4_mm_stattype, unsigned flags);
  void (*xFinal)(sqlite4_mm*);
};

/*
** Available memory management types:
*/
typedef enum {
  SQLITE4_MM_SYSTEM = 1,     /* Use the system malloc() */
  SQLITE4_MM_ONESIZE = 2,    /* All allocations map to a fixed size */
  SQLITE4_MM_OVERFLOW = 3,   /* Two allocators. Use A first; failover to B */
  SQLITE4_MM_COMPACT = 4,    /* Like memsys3 from SQLite3 */
  SQLITE4_MM_ROBSON = 5,     /* Like memsys5 from SQLite3 */
  SQLITE4_MM_LINEAR = 6,     /* Allocate from a fixed buffer w/o free */
  SQLITE4_MM_BESPOKE = 7,    /* Caller-defined implementation */
  SQLITE4_MM_DEBUG,          /* Debugging memory allocator */
  SQLITE4_MM_STATS           /* Keep memory statistics */

} sqlite4_mm_type;

/*
** Allocate a new memory manager.  Return NULL if unable.
*/
sqlite4_mm *sqlite4_mm_new(sqlite4_mm_type, ...);

103
104
105
106
107
108
109



/*
** Enable or disable benign failure mode.  Benign failure mode can be
** nested.  In benign failure mode, OOM errors do not necessarily propagate
** back out to the application but can be dealt with internally.  Memory
** allocations that occur in benign failure mode are considered "optional".
*/
void sqlite4_mm_benign_failures(sqlite4_mm*, int bEnable);










>
>
>
123
124
125
126
127
128
129
130
131
132
/*
** Enable or disable benign failure mode.  Benign failure mode can be
** nested.  In benign failure mode, OOM errors do not necessarily propagate
** back out to the application but can be dealt with internally.  Memory
** allocations that occur in benign failure mode are considered "optional".
*/
void sqlite4_mm_benign_failures(sqlite4_mm*, int bEnable);

/*
** Rest
Changes to src/sqlite.h.in.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************

** This header file defines the interface that the SQLite library
** presents to client programs.  If a C-function, structure, datatype,
** or constant definition does not appear in this file, then it is
** not a published API of SQLite, is subject to change without
** notice, and should not be referenced by programs that use SQLite.
**
** Some of the definitions that are in this file are marked as
** "experimental".  Experimental interfaces are normally new
** features recently added to SQLite.  We do not anticipate changes
** to experimental interfaces but reserve the right to make minor changes
** if experience from use "in the wild" suggest such changes are prudent.
**
** The official C-language API documentation for SQLite is derived
** from comments in this file.  This file is the authoritative source
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite4.h" as
** part of the build process.
*/
#ifndef _SQLITE4_H_
#define _SQLITE4_H_











>
|





<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18










19
20
21
22
23
24
25
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This header file defines the interface that the SQLite4 library
** presents to client programs.  If a C-function, structure, datatype,
** or constant definition does not appear in this file, then it is
** not a published API of SQLite, is subject to change without
** notice, and should not be referenced by programs that use SQLite.
**










** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite4.h" as
** part of the build process.
*/
#ifndef _SQLITE4_H_
#define _SQLITE4_H_
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
/*
** Add the ability to override 'extern'
*/
#ifndef SQLITE4_EXTERN
# define SQLITE4_EXTERN extern
#endif

/*
** These no-op macros are used in front of interfaces to mark those
** interfaces as either deprecated or experimental.  New applications
** should not use deprecated interfaces - they are support for backwards
** compatibility only.  Application writers should be aware that
** experimental interfaces are subject to change in point releases.
**
** These macros used to resolve to various kinds of compiler magic that
** would generate warning messages when they were used.  But that
** compiler magic ended up generating such a flurry of bug reports
** that we have taken it all out and gone back to using simple
** noop macros.
*/
#define SQLITE4_DEPRECATED
#define SQLITE4_EXPERIMENTAL

/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE4_VERSION
# undef SQLITE4_VERSION
#endif
#ifdef SQLITE4_VERSION_NUMBER







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







36
37
38
39
40
41
42
















43
44
45
46
47
48
49
/*
** Add the ability to override 'extern'
*/
#ifndef SQLITE4_EXTERN
# define SQLITE4_EXTERN extern
#endif

















/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE4_VERSION
# undef SQLITE4_VERSION
#endif
#ifdef SQLITE4_VERSION_NUMBER
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
** </dl>
*/
#define SQLITE4_DBCONFIG_LOOKASIDE       1001  /* void* int int */
#define SQLITE4_DBCONFIG_ENABLE_FKEY     1002  /* int int* */
#define SQLITE4_DBCONFIG_ENABLE_TRIGGER  1003  /* int int* */


/*
** CAPIREF: Last Insert Rowid
**
** ^The sqlite4_last_insert_rowid(D) routine returns the primary key value
** of the the most recent successful [INSERT] from [database connection] D
** into a table where the primary key of the inserted row is a single
** integer.
** ^If there have been no successful [INSERT]s of rows with a single integer
** PRIMARY KEY value on database connection D, then this routine returns
** zero.
**
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
** But once the trigger or virtual table method ends, the value returned 
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
** routine.  ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
** and INSERT OR ABORT make no changes to the return value of this
** routine when their insertion fails.  ^(When INSERT OR REPLACE
** encounters a constraint violation, it does not fail.  The
** INSERT continues to completion after deleting rows that caused
** the constraint problem so INSERT OR REPLACE will always change
** the return value of this interface.)^
**
** ^For the purposes of this routine, an [INSERT] is considered to
** be successful even if it is subsequently rolled back.
**
** This function is accessible to SQL statements via the
** [last_insert_rowid() SQL function].
**
** If a separate thread performs a new [INSERT] on the same
** database connection while the [sqlite4_last_insert_rowid()]
** function is running and thus changes the last insert [rowid],
** then the value returned by [sqlite4_last_insert_rowid()] is
** unpredictable and might not equal either the old or the new
** last insert [rowid].
*/
sqlite4_int64 sqlite4_last_insert_rowid(sqlite4*);

/*
** CAPIREF: Count The Number Of Rows Modified
**
** ^This function returns the number of database rows that were changed
** or inserted or deleted by the most recently completed SQL statement
** on the [database connection] specified by the first parameter.
** ^(Only changes that are directly specified by the [INSERT], [UPDATE],







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







712
713
714
715
716
717
718











































719
720
721
722
723
724
725
** </dl>
*/
#define SQLITE4_DBCONFIG_LOOKASIDE       1001  /* void* int int */
#define SQLITE4_DBCONFIG_ENABLE_FKEY     1002  /* int int* */
#define SQLITE4_DBCONFIG_ENABLE_TRIGGER  1003  /* int int* */













































/*
** CAPIREF: Count The Number Of Rows Modified
**
** ^This function returns the number of database rows that were changed
** or inserted or deleted by the most recently completed SQL statement
** on the [database connection] specified by the first parameter.
** ^(Only changes that are directly specified by the [INSERT], [UPDATE],
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless.  Future versions of SQLite
** might provide greater resolution on the profiler callback.  The
** sqlite4_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
void *sqlite4_trace(sqlite4*, void(*xTrace)(void*,const char*), void*);
SQLITE4_EXPERIMENTAL void *sqlite4_profile(sqlite4*,
   void(*xProfile)(void*,const char*,sqlite4_uint64), void*);

/*
** CAPIREF: Query Progress Callbacks
**
** ^The sqlite4_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to







|







1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless.  Future versions of SQLite
** might provide greater resolution on the profiler callback.  The
** sqlite4_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
void *sqlite4_trace(sqlite4*, void(*xTrace)(void*,const char*), void*);
void *sqlite4_profile(sqlite4*,
   void(*xProfile)(void*,const char*,sqlite4_uint64), void*);

/*
** CAPIREF: Query Progress Callbacks
**
** ^The sqlite4_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
2140
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
** If [sqlite4_step()] or [sqlite4_reset()] or [sqlite4_finalize()]
** are called from a different thread while any of these routines
** are pending, then the results are undefined.
**
** ^The sqlite4_column_type() routine returns the
** [SQLITE4_INTEGER | datatype code] for the initial data type
** of the result column.  ^The returned value is one of [SQLITE4_INTEGER],
** [SQLITE4_FLOAT], [SQLITE4_TEXT], [SQLITE4_BLOB], or [SQLITE4_NULL].  The value

** returned by sqlite4_column_type() is only meaningful if no type
** conversions have occurred as described below.  After a type conversion,
** the value returned by sqlite4_column_type() is undefined.  Future
** versions of SQLite may change the behavior of sqlite4_column_type()
** following a type conversion.
**
** ^If the result is a BLOB or UTF-8 string then the sqlite4_column_bytes()







|
>







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
** If [sqlite4_step()] or [sqlite4_reset()] or [sqlite4_finalize()]
** are called from a different thread while any of these routines
** are pending, then the results are undefined.
**
** ^The sqlite4_column_type() routine returns the
** [SQLITE4_INTEGER | datatype code] for the initial data type
** of the result column.  ^The returned value is one of [SQLITE4_INTEGER],
** [SQLITE4_FLOAT], [SQLITE4_TEXT], [SQLITE4_BLOB], or [SQLITE4_NULL].
** The value
** returned by sqlite4_column_type() is only meaningful if no type
** conversions have occurred as described below.  After a type conversion,
** the value returned by sqlite4_column_type() is undefined.  Future
** versions of SQLite may change the behavior of sqlite4_column_type()
** following a type conversion.
**
** ^If the result is a BLOB or UTF-8 string then the sqlite4_column_bytes()
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
#define SQLITE4_UTF8           1
#define SQLITE4_UTF16LE        2
#define SQLITE4_UTF16BE        3
#define SQLITE4_UTF16          4    /* Use native byte order */
#define SQLITE4_ANY            5    /* sqlite4_create_function only */
#define SQLITE4_UTF16_ALIGNED  8    /* sqlite4_create_collation only */

/*
** CAPIREF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated].  In order to maintain
** backwards compatibility with older code, these functions continue 
** to be supported.  However, new applications should avoid
** the use of these functions.  To help encourage people to avoid
** using these functions, we are not going to tell you what they do.
*/
#ifndef SQLITE4_OMIT_DEPRECATED
SQLITE4_DEPRECATED int sqlite4_aggregate_count(sqlite4_context*);
SQLITE4_DEPRECATED int sqlite4_expired(sqlite4_stmt*);
SQLITE4_DEPRECATED int sqlite4_transfer_bindings(sqlite4_stmt*, sqlite4_stmt*);
SQLITE4_DEPRECATED int sqlite4_global_recover(void);
#endif

/*
** CAPIREF: Obtaining SQL Function Parameter Values
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
**







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2402
2403
2404
2405
2406
2407
2408

















2409
2410
2411
2412
2413
2414
2415
#define SQLITE4_UTF8           1
#define SQLITE4_UTF16LE        2
#define SQLITE4_UTF16BE        3
#define SQLITE4_UTF16          4    /* Use native byte order */
#define SQLITE4_ANY            5    /* sqlite4_create_function only */
#define SQLITE4_UTF16_ALIGNED  8    /* sqlite4_create_collation only */


















/*
** CAPIREF: Obtaining SQL Function Parameter Values
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
**
2719
2720
2721
2722
2723
2724
2725
2726

2727
2728
2729
2730
2731
2732
2733
** bytes (not characters) from the 2nd parameter as the error message.
** ^The sqlite4_result_error() and sqlite4_result_error16()
** routines make a private copy of the error message text before
** they return.  Hence, the calling function can deallocate or
** modify the text after they return without harm.
** ^The sqlite4_result_error_code() function changes the error code
** returned by SQLite as a result of an error in a function.  ^By default,
** the error code is SQLITE4_ERROR.  ^A subsequent call to sqlite4_result_error()

** or sqlite4_result_error16() resets the error code to SQLITE4_ERROR.
**
** ^The sqlite4_result_toobig() interface causes SQLite to throw an error
** indicating that a string or BLOB is too long to represent.
**
** ^The sqlite4_result_nomem() interface causes SQLite to throw an error
** indicating that a memory allocation failed.







|
>







2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
** bytes (not characters) from the 2nd parameter as the error message.
** ^The sqlite4_result_error() and sqlite4_result_error16()
** routines make a private copy of the error message text before
** they return.  Hence, the calling function can deallocate or
** modify the text after they return without harm.
** ^The sqlite4_result_error_code() function changes the error code
** returned by SQLite as a result of an error in a function.  ^By default,
** the error code is SQLITE4_ERROR.
** ^A subsequent call to sqlite4_result_error()
** or sqlite4_result_error16() resets the error code to SQLITE4_ERROR.
**
** ^The sqlite4_result_toobig() interface causes SQLite to throw an error
** indicating that a string or BLOB is too long to represent.
**
** ^The sqlite4_result_nomem() interface causes SQLite to throw an error
** indicating that a memory allocation failed.
3851
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
** New verbs may be added in future releases of SQLite. Existing verbs
** might be discontinued. Applications should check the return code from
** [sqlite4_db_status()] to make sure that the call worked.
** The [sqlite4_db_status()] interface will return a non-zero error code
** if a discontinued or unsupported verb is invoked.
**
** <dl>
** [[SQLITE4_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_USED</dt>

** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** [[SQLITE4_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^







|
>







3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
** New verbs may be added in future releases of SQLite. Existing verbs
** might be discontinued. Applications should check the return code from
** [sqlite4_db_status()] to make sure that the call worked.
** The [sqlite4_db_status()] interface will return a non-zero error code
** if a discontinued or unsupported verb is invoked.
**
** <dl>
** [[SQLITE4_DBSTATUS_LOOKASIDE_USED]]
** ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** [[SQLITE4_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968
3969
3970
** KEYWORDS: {SQLITE4_STMTSTATUS counter} {SQLITE4_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite4_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
** [[SQLITE4_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE4_STMTSTATUS_FULLSCAN_STEP</dt>

** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan.  Large numbers for this counter
** may indicate opportunities for performance improvement through 
** careful use of indices.</dd>
**
** [[SQLITE4_STMTSTATUS_SORT]] <dt>SQLITE4_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.







|
>







3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
** KEYWORDS: {SQLITE4_STMTSTATUS counter} {SQLITE4_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite4_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
** [[SQLITE4_STMTSTATUS_FULLSCAN_STEP]]
** <dt>SQLITE4_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan.  Large numbers for this counter
** may indicate opportunities for performance improvement through 
** careful use of indices.</dd>
**
** [[SQLITE4_STMTSTATUS_SORT]] <dt>SQLITE4_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
4197
4198
4199
4200
4201
4202
4203
4204

4205
4206
4207
4208
4209
4210
4211
#define SQLITE4_VTAB_CONSTRAINT_SUPPORT 1

/*
** CAPIREF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE4_ROLLBACK], [SQLITE4_IGNORE], [SQLITE4_FAIL],

** [SQLITE4_ABORT], or [SQLITE4_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
int sqlite4_vtab_on_conflict(sqlite4 *);

/*







|
>







4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
#define SQLITE4_VTAB_CONSTRAINT_SUPPORT 1

/*
** CAPIREF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE4_ROLLBACK], [SQLITE4_IGNORE],
** [SQLITE4_FAIL],
** [SQLITE4_ABORT], or [SQLITE4_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
int sqlite4_vtab_on_conflict(sqlite4 *);

/*
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332

/*
** CAPIREF: Key-value storage object factory
**
** New key/value storage engines can be added to SQLite4 at run-time.
** In order to create a new KV storage engine, the application must 
** supply a "factory" function that creates an instance of the
** sqlite4_kvstore object.  This is typedef defines the signature
** of that factory function.
*/
typedef int (*sqlite4_kvfactory)(
  sqlite4_env *pEnv,             /* The environment to use */
  sqlite4_kvstore **ppKVStore,   /* OUT: New KV store returned here */
  const char *zFilename,         /* Name of database file to open */
  unsigned flags                 /* Bit flags */







|







4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252

/*
** CAPIREF: Key-value storage object factory
**
** New key/value storage engines can be added to SQLite4 at run-time.
** In order to create a new KV storage engine, the application must 
** supply a "factory" function that creates an instance of the
** sqlite4_kvstore object.  This typedef defines the signature
** of that factory function.
*/
typedef int (*sqlite4_kvfactory)(
  sqlite4_env *pEnv,             /* The environment to use */
  sqlite4_kvstore **ppKVStore,   /* OUT: New KV store returned here */
  const char *zFilename,         /* Name of database file to open */
  unsigned flags                 /* Bit flags */
Changes to src/sqliteInt.h.
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
  u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
};


/*
** Each database connection is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
** insert statement.  Inserts on views do not affect its value.  Each
** trigger has its own context, so that lastRowid can be updated inside
** triggers as usual.  The previous value will be restored once the trigger
** exits.  Upon entering a before or instead of trigger, lastRowid is no
** longer (since after version 2.8.12) reset to -1.
**
** The sqlite.nChange does not count changes within triggers and keeps no
** context.  It is reset at start of sqlite4_exec.
** The sqlite.lsChange represents the number of changes made by the last
** insert, update, or delete statement.  It remains constant throughout the
** length of a statement and is then updated by OP_SetCounts.  It keeps a
** context stack just like lastRowid so that the count of changes
** within a trigger is not seen outside the trigger.  Changes to views do not
** affect the value of lsChange.
** The sqlite.csChange keeps track of the number of current changes (since
** the last statement) and is used to update sqlite_lsChange.
**
** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16
** store the most recent error code and, if applicable, string. The







<
<
<
<
<
<
<





|







763
764
765
766
767
768
769







770
771
772
773
774
775
776
777
778
779
780
781
782
  u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
};


/*
** Each database connection is an instance of the following structure.
**







** The sqlite.nChange does not count changes within triggers and keeps no
** context.  It is reset at start of sqlite4_exec.
** The sqlite.lsChange represents the number of changes made by the last
** insert, update, or delete statement.  It remains constant throughout the
** length of a statement and is then updated by OP_SetCounts.  It keeps a
** context stack so that the count of changes
** within a trigger is not seen outside the trigger.  Changes to views do not
** affect the value of lsChange.
** The sqlite.csChange keeps track of the number of current changes (since
** the last statement) and is used to update sqlite_lsChange.
**
** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16
** store the most recent error code and, if applicable, string. The
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  int nTable;                   /* Number of tables in the database */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  i64 lastRowid;                /* ROWID of most recent insert (see above) */
  u32 magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Value returned by sqlite4_changes() */
  int nTotalChange;             /* Value returned by sqlite4_total_changes() */
  sqlite4_mutex *mutex;         /* Connection mutex */
  int aLimit[SQLITE4_N_LIMIT];   /* Limits */
  Sqlite4InitInfo init;         /* Information used during initialization */
  int nExtension;               /* Number of loaded extensions */







<







795
796
797
798
799
800
801

802
803
804
805
806
807
808
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  int nTable;                   /* Number of tables in the database */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */

  u32 magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Value returned by sqlite4_changes() */
  int nTotalChange;             /* Value returned by sqlite4_total_changes() */
  sqlite4_mutex *mutex;         /* Connection mutex */
  int aLimit[SQLITE4_N_LIMIT];   /* Limits */
  Sqlite4InitInfo init;         /* Information used during initialization */
  int nExtension;               /* Number of loaded extensions */
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
  Parse *pParse;              /* The Parse structure */
};

/*
** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE       0x01    /* Set to update db->nChange */
#define OPFLAG_LASTROWID     0x02    /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE      0x04    /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND        0x08    /* This is likely to be an append */
#define OPFLAG_SEQCOUNT      0x10    /* Append sequence number to key */
#define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_APPENDBIAS    0x40    /* Bias inserts for appending */

/*







<







2246
2247
2248
2249
2250
2251
2252

2253
2254
2255
2256
2257
2258
2259
  Parse *pParse;              /* The Parse structure */
};

/*
** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE       0x01    /* Set to update db->nChange */

#define OPFLAG_ISUPDATE      0x04    /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND        0x08    /* This is likely to be an append */
#define OPFLAG_SEQCOUNT      0x10    /* Append sequence number to key */
#define OPFLAG_CLEARCACHE    0x20    /* Clear pseudo-table cache in OP_Column */
#define OPFLAG_APPENDBIAS    0x40    /* Bias inserts for appending */

/*
Changes to src/tclsqlite.c.
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
  int choice;
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "authorizer",         "cache",             "changes",
    "close",              "collate",           "collation_needed",
    "complete",           "copy",              "enable_load_extension", 
    "errorcode",          "eval",              "exists",             
    "function",           "interrupt",         "last_insert_rowid",
    "nullvalue",          "onecolumn",         "profile",
    "rekey",              "status",            "total_changes",
    "trace",              "transaction",       "unlock_notify",
    "version",            0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_CACHE,            DB_CHANGES,
    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION, 
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,            
    DB_FUNCTION,          DB_INTERRUPT,        DB_LAST_INSERT_ROWID, 
    DB_NULLVALUE,         DB_ONECOLUMN,        DB_PROFILE,           
    DB_REKEY,             DB_STATUS,           DB_TOTAL_CHANGES,    
    DB_TRACE,             DB_TRANSACTION,      DB_UNLOCK_NOTIFY,
    DB_VERSION
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */








|










|







1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
  int choice;
  int rc = TCL_OK;
  static const char *DB_strs[] = {
    "authorizer",         "cache",             "changes",
    "close",              "collate",           "collation_needed",
    "complete",           "copy",              "enable_load_extension", 
    "errorcode",          "eval",              "exists",             
    "function",           "interrupt",         
    "nullvalue",          "onecolumn",         "profile",
    "rekey",              "status",            "total_changes",
    "trace",              "transaction",       "unlock_notify",
    "version",            0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_CACHE,            DB_CHANGES,
    DB_CLOSE,             DB_COLLATE,          DB_COLLATION_NEEDED,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION, 
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,            
    DB_FUNCTION,          DB_INTERRUPT,        
    DB_NULLVALUE,         DB_ONECOLUMN,        DB_PROFILE,           
    DB_REKEY,             DB_STATUS,           DB_TOTAL_CHANGES,    
    DB_TRACE,             DB_TRANSACTION,      DB_UNLOCK_NOTIFY,
    DB_VERSION
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
        pDb->zNull = 0;
      }
    }
    Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
    break;
  }

  /*
  **     $db last_insert_rowid 
  **
  ** Return an integer which is the ROWID for the most recent insert.
  */
  case DB_LAST_INSERT_ROWID: {
    Tcl_Obj *pResult;
    Tcl_WideInt rowid;
    if( objc!=2 ){
      Tcl_WrongNumArgs(interp, 2, objv, "");
      return TCL_ERROR;
    }
    rowid = sqlite4_last_insert_rowid(pDb->db);
    pResult = Tcl_GetObjResult(interp);
    Tcl_SetWideIntObj(pResult, rowid);
    break;
  }

  /*
  ** The DB_ONECOLUMN method is implemented together with DB_EXISTS.
  */


  /*    $db profile ?CALLBACK?
  **







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1899
1900
1901
1902
1903
1904
1905


















1906
1907
1908
1909
1910
1911
1912
        pDb->zNull = 0;
      }
    }
    Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
    break;
  }



















  /*
  ** The DB_ONECOLUMN method is implemented together with DB_EXISTS.
  */


  /*    $db profile ?CALLBACK?
  **
Changes to src/vdbe.c.
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int iCompare = 0;          /* Result of last OP_Compare operation */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
  i64 lastRowid = db->lastRowid;  /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite4_step() verifies this */







<







522
523
524
525
526
527
528

529
530
531
532
533
534
535
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int iCompare = 0;          /* Result of last OP_Compare operation */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */

#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite4_step() verifies this */
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  if( pOp->p1==SQLITE4_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    VdbeFrame *pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite4VdbeSetChanges(db, p->nChange);
    pc = sqlite4VdbeFrameRestore(pFrame);
    lastRowid = db->lastRowid;
    if( pOp->p2==OE_Ignore ){
      /* Instruction pc is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
      pc = p->aOp[pc].p2-1;







<







790
791
792
793
794
795
796

797
798
799
800
801
802
803
  if( pOp->p1==SQLITE4_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    VdbeFrame *pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite4VdbeSetChanges(db, p->nChange);
    pc = sqlite4VdbeFrameRestore(pFrame);

    if( pOp->p2==OE_Ignore ){
      /* Instruction pc is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
      pc = p->aOp[pc].p2-1;
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
  ctx.isError = 0;
  if( ctx.pFunc->flags & SQLITE4_FUNC_NEEDCOLL ){
    assert( pOp>aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    ctx.pColl = pOp[-1].p4.pColl;
  }
  db->lastRowid = lastRowid;
  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
  lastRowid = db->lastRowid;

  /* If any auxiliary data functions have been called by this user function,
  ** immediately call the destructor for any non-static values.
  */
  if( ctx.pVdbeFunc ){
    sqlite4VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
    pOp->p4.pVdbeFunc = ctx.pVdbeFunc;







<

<







1377
1378
1379
1380
1381
1382
1383

1384

1385
1386
1387
1388
1389
1390
1391
  ctx.isError = 0;
  if( ctx.pFunc->flags & SQLITE4_FUNC_NEEDCOLL ){
    assert( pOp>aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    ctx.pColl = pOp[-1].p4.pColl;
  }

  (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */


  /* If any auxiliary data functions have been called by this user function,
  ** immediately call the destructor for any non-static values.
  */
  if( ctx.pVdbeFunc ){
    sqlite4VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
    pOp->p4.pVdbeFunc = ctx.pVdbeFunc;
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
** This instruction encodes the N values into a database key and writes
** the result to register P3. No affinity transformations are applied to 
** the input values before they are encoded. 
**
** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number 
** (unique within the cursor) is appended to the record. The sole purpose
** of this is to ensure that the key blob is unique within the cursors table.
**
** If the OPFLAG_LASTROWID bit of P5 is set and the value of the first and
** only field of the key is an integer, then set the lastRowid field to the
** value of that integer.
*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */







<
<
<
<







2188
2189
2190
2191
2192
2193
2194




2195
2196
2197
2198
2199
2200
2201
** This instruction encodes the N values into a database key and writes
** the result to register P3. No affinity transformations are applied to 
** the input values before they are encoded. 
**
** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number 
** (unique within the cursor) is appended to the record. The sole purpose
** of this is to ensure that the key blob is unique within the cursors table.




*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
    do {
      nSeq++;
      aSeq[sizeof(aSeq)-nSeq] = (u8)(iSeq & 0x007F);
      iSeq = iSeq >> 7;
    }while( iSeq );
    aSeq[sizeof(aSeq)-nSeq] |= 0x80;
  }
  if( (pOp->p5 & OPFLAG_LASTROWID)!=0 && (pData0->flags & MEM_Int)!=0 ){
    lastRowid = pData0->u.i;
  }

  memAboutToChange(p, pOut);

  nField = pKeyInfo->nField;
  if( pOp->p4type==P4_INT32 && pOp->p4.i ){
    nField = pOp->p4.i;
    assert( nField<=pKeyInfo->nField );







<
<
<







2220
2221
2222
2223
2224
2225
2226



2227
2228
2229
2230
2231
2232
2233
    do {
      nSeq++;
      aSeq[sizeof(aSeq)-nSeq] = (u8)(iSeq & 0x007F);
      iSeq = iSeq >> 7;
    }while( iSeq );
    aSeq[sizeof(aSeq)-nSeq] |= 0x80;
  }




  memAboutToChange(p, pOut);

  nField = pKeyInfo->nField;
  if( pOp->p4type==P4_INT32 && pOp->p4.i ){
    nField = pOp->p4.i;
    assert( nField<=pKeyInfo->nField );
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
    iKey = pKey->u.i;
  }else{
    /* assert( pOp->opcode==OP_InsertInt ); */
    iKey = pOp->p3;
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
  if( pData->flags & MEM_Null ){
    pData->z = 0;
    pData->n = 0;
  }else{
    assert( pData->flags & (MEM_Blob|MEM_Str) );
  }
  n = sqlite4PutVarint64(aKey, pC->iRoot);







<







3418
3419
3420
3421
3422
3423
3424

3425
3426
3427
3428
3429
3430
3431
    iKey = pKey->u.i;
  }else{
    /* assert( pOp->opcode==OP_InsertInt ); */
    iKey = pOp->p3;
  }

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;

  if( pData->flags & MEM_Null ){
    pData->z = 0;
    pData->n = 0;
  }else{
    assert( pData->flags & (MEM_Blob|MEM_Str) );
  }
  n = sqlite4PutVarint64(aKey, pC->iRoot);
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
case OP_NullRow: {
  VdbeCursor *pC;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  pC->nullRow = 1;
  pC->rowidIsValid = 0;
  break;
}

/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.







<







3620
3621
3622
3623
3624
3625
3626

3627
3628
3629
3630
3631
3632
3633
case OP_NullRow: {
  VdbeCursor *pC;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  pC->nullRow = 1;

  break;
}

/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
#ifdef SQLITE4_TEST
    sqlite4_search_count++;
#endif
  }else if( rc==SQLITE4_NOTFOUND ){
    pC->nullRow = 1;
    rc = SQLITE4_OK;
  }
  pC->rowidIsValid = 0;
  break;
}


/* Opcode: SorterInsert P1 P2 P3
*/
/* Opcode: IdxInsert P1 P2 P3 * P5







<







3760
3761
3762
3763
3764
3765
3766

3767
3768
3769
3770
3771
3772
3773
#ifdef SQLITE4_TEST
    sqlite4_search_count++;
#endif
  }else if( rc==SQLITE4_NOTFOUND ){
    pC->nullRow = 1;
    rc = SQLITE4_OK;
  }

  break;
}


/* Opcode: SorterInsert P1 P2 P3
*/
/* Opcode: IdxInsert P1 P2 P3 * P5
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
    assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
    assert( pProgram->nCsr==pFrame->nChildCsr );
    assert( pc==pFrame->pc );
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;
  pFrame->lastRowid = lastRowid;
  pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = pFrame;
  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];







<







4174
4175
4176
4177
4178
4179
4180

4181
4182
4183
4184
4185
4186
4187
    assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
    assert( pProgram->nCsr==pFrame->nChildCsr );
    assert( pc==pFrame->pc );
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;

  pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = pFrame;
  p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = (u16)pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
      apArg[i] = pX;
      pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, pVtab);
    if( rc==SQLITE4_OK && pOp->p1 ){
      assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = rowid;
    }
    if( rc==SQLITE4_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE4_OK;
      }else{
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
      }
    }else{







<
<
<
<







4798
4799
4800
4801
4802
4803
4804




4805
4806
4807
4808
4809
4810
4811
      apArg[i] = pX;
      pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, pVtab);




    if( rc==SQLITE4_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE4_OK;
      }else{
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
      }
    }else{
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
    sqlite4ResetInternalSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
  db->lastRowid = lastRowid;
  return rc;

  /* Jump to here if a string or blob larger than SQLITE4_MAX_LENGTH
  ** is encountered.
  */
too_big:
  sqlite4SetString(&p->zErrMsg, db, "string or blob too big");







<







5050
5051
5052
5053
5054
5055
5056

5057
5058
5059
5060
5061
5062
5063
    sqlite4ResetInternalSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:

  return rc;

  /* Jump to here if a string or blob larger than SQLITE4_MAX_LENGTH
  ** is encountered.
  */
too_big:
  sqlite4SetString(&p->zErrMsg, db, "string or blob too big");
Changes to src/vdbeInt.h.
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  KVStore *pTmpKV;      /* Separate file holding a temporary table */
  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
  int iRoot;            /* Root page of the table */
  int pseudoTableReg;   /* Register holding pseudotable content. */
  int nField;           /* Number of fields in the header */
  Bool zeroed;          /* True if zeroed out and ready for reuse */
  Bool rowidIsValid;    /* True if lastRowid is valid */
  Bool atFirst;         /* True if pointing to first entry */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred move-to */
  i64 lastRowid;        /* Last rowid from a Next or NextIdx operation */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */

  /* Result of last sqlite4-Moveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
  int seekResult;
};







<









<







54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
  KVStore *pTmpKV;      /* Separate file holding a temporary table */
  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
  int iRoot;            /* Root page of the table */
  int pseudoTableReg;   /* Register holding pseudotable content. */
  int nField;           /* Number of fields in the header */
  Bool zeroed;          /* True if zeroed out and ready for reuse */

  Bool atFirst;         /* True if pointing to first entry */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred move-to */

  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */

  /* Result of last sqlite4-Moveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
  int seekResult;
};
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  u16 nCursor;            /* Number of entries in apCsr */
  void *token;            /* Copy of SubProgram.token */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  i64 lastRowid;          /* Last insert rowid (sqlite4.lastRowid) */
  int nChange;            /* Statement changes (Vdbe.nChanges)     */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*







<







107
108
109
110
111
112
113

114
115
116
117
118
119
120
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  u16 nCursor;            /* Number of entries in apCsr */
  void *token;            /* Copy of SubProgram.token */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */

  int nChange;            /* Statement changes (Vdbe.nChanges)     */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
Changes to src/vdbeaux.c.
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
  v->nOnceFlag = pFrame->nOnceFlag;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->db->lastRowid = pFrame->lastRowid;
  v->nChange = pFrame->nChange;
  return pFrame->pc;
}

/*
** Close all cursors.
**







<







1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
  v->nOnceFlag = pFrame->nOnceFlag;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;

  v->nChange = pFrame->nChange;
  return pFrame->pc;
}

/*
** Close all cursors.
**
Deleted test/lastinsert.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests to make sure that value returned by last_insert_rowid() (LIRID)
# is updated properly, especially inside triggers
#
# Note 1: insert into table is now the only statement which changes LIRID
# Note 2: upon entry into before or instead of triggers,
#           LIRID is unchanged (rather than -1)
# Note 3: LIRID is changed within the context of a trigger,
#           but is restored once the trigger exits
# Note 4: LIRID is not changed by an insert into a view (since everything
#           is done within instead of trigger context)
#

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

# ----------------------------------------------------------------------------
# 1.x - basic tests (no triggers)

# LIRID changed properly after an insert into a table
do_test lastinsert-1.1 {
    catchsql {
        create table t1 (k integer primary key);
        insert into t1 values (1);
        insert into t1 values (NULL);
        insert into t1 values (NULL);
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after an update on a table
do_test lastinsert-1.2 {
    catchsql {
        update t1 set k=4 where k=2;
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after a delete from a table
do_test lastinsert-1.3 {
    catchsql {
        delete from t1 where k=4;
        select last_insert_rowid();
    }
} {0 3}

# LIRID unchanged after create table/view statements
do_test lastinsert-1.4.1 {
    catchsql {
        create table t2 (k integer primary key, val1, val2, val3);
        select last_insert_rowid();
    }
} {0 3}
ifcapable view {
do_test lastinsert-1.4.2 {
    catchsql {
        create view v as select * from t1;
        select last_insert_rowid();
    }
} {0 3}
} ;# ifcapable view

# All remaining tests involve triggers.  Skip them if triggers are not
# supported in this build.
#
ifcapable {!trigger} {
  finish_test
  return
}

# ----------------------------------------------------------------------------
# 2.x - tests with after insert trigger

# LIRID changed properly after an insert into table containing an after trigger
do_test lastinsert-2.1 {
    catchsql {
        delete from t2;
        create trigger r1 after insert on t1 for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        insert into t1 values (13);
        select last_insert_rowid();
    }
} {0 13}

# LIRID equals NEW.k upon entry into after insert trigger
do_test lastinsert-2.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of after insert trigger
do_test lastinsert-2.3 {
    catchsql {
        select val2 from t2;
    }
} {0 126}

# LIRID unchanged by update within context of after insert trigger
do_test lastinsert-2.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1026}

# ----------------------------------------------------------------------------
# 3.x - tests with after update trigger

# LIRID not changed after an update onto a table containing an after trigger
do_test lastinsert-3.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 after update on t1 for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        update t1 set k=14 where k=3;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into after update trigger
do_test lastinsert-3.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of after update trigger
do_test lastinsert-3.3 {
    catchsql {
        select val2 from t2;
    }
} {0 128}

# LIRID unchanged by update within context of after update trigger
do_test lastinsert-3.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1028}

# ----------------------------------------------------------------------------
# 4.x - tests with instead of insert trigger
# These may not be run if either views or triggers were disabled at 
# compile-time

ifcapable {view && trigger} {
# LIRID not changed after an insert into view containing an instead of trigger
do_test lastinsert-4.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 instead of insert on v for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        insert into v values (15);
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into instead of trigger
do_test lastinsert-4.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of instead of trigger
do_test lastinsert-4.3 {
    catchsql {
        select val2 from t2;
    }
} {0 130}

# LIRID unchanged by update within context of instead of trigger
do_test lastinsert-4.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1030}
} ;# ifcapable (view && trigger)

# ----------------------------------------------------------------------------
# 5.x - tests with before delete trigger

# LIRID not changed after a delete on a table containing a before trigger
do_test lastinsert-5.1 {
    catchsql {
      drop trigger r1;  -- This was not created if views are disabled.
    }
    catchsql {
        delete from t2;
        create trigger r1 before delete on t1 for each row begin
            insert into t2 values (77, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        delete from t1 where k=1;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into delete trigger
do_test lastinsert-5.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of delete trigger
do_test lastinsert-5.3 {
    catchsql {
        select val2 from t2;
    }
} {0 177}

# LIRID unchanged by update within context of delete trigger
do_test lastinsert-5.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1077}

# ----------------------------------------------------------------------------
# 6.x - tests with instead of update trigger
# These tests may not run if either views or triggers are disabled.

ifcapable {view && trigger} {
# LIRID not changed after an update on a view containing an instead of trigger
do_test lastinsert-6.1 {
    catchsql {
        delete from t2;
        drop trigger r1;
        create trigger r1 instead of update on v for each row begin
            insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL);
            update t2 set k=k+10, val2=100+last_insert_rowid();
            update t2 set val3=1000+last_insert_rowid();
        end;
        update v set k=16 where k=14;
        select last_insert_rowid();
    }
} {0 13}

# LIRID unchanged upon entry into instead of trigger
do_test lastinsert-6.2 {
    catchsql {
        select val1 from t2;
    }
} {0 13}

# LIRID changed properly by insert within context of instead of trigger
do_test lastinsert-6.3 {
    catchsql {
        select val2 from t2;
    }
} {0 132}

# LIRID unchanged by update within context of instead of trigger
do_test lastinsert-6.4 {
    catchsql {
        select val3 from t2;
    }
} {0 1032}
} ;# ifcapable (view && trigger)

# ----------------------------------------------------------------------------
# 7.x - complex tests with temporary tables and nested instead of triggers
# These do not run if views or triggers are disabled.

ifcapable {trigger && view && tempdb} {
do_test lastinsert-7.1 {
    catchsql {
        drop table t1; drop table t2; drop trigger r1;
        create temp table t1 (k integer primary key);
        create temp table t2 (k integer primary key);
        create temp view v1 as select * from t1;
        create temp view v2 as select * from t2;
        create temp table rid (k integer primary key, rin, rout);
        insert into rid values (1, NULL, NULL);
        insert into rid values (2, NULL, NULL);
        create temp trigger r1 instead of insert on v1 for each row begin
            update rid set rin=last_insert_rowid() where k=1;
            insert into t1 values (100+NEW.k);
            insert into v2 values (100+last_insert_rowid());
            update rid set rout=last_insert_rowid() where k=1;
        end;
        create temp trigger r2 instead of insert on v2 for each row begin
            update rid set rin=last_insert_rowid() where k=2;
            insert into t2 values (1000+NEW.k);
            update rid set rout=last_insert_rowid() where k=2;
        end;
        insert into t1 values (77);
        select last_insert_rowid();
    }
} {0 77}

do_test lastinsert-7.2 {
    catchsql {
        insert into v1 values (5);
        select last_insert_rowid();
    }
} {0 77}

do_test lastinsert-7.3 {
    catchsql {
        select rin from rid where k=1;
    }
} {0 77}

do_test lastinsert-7.4 {
    catchsql {
        select rout from rid where k=1;
    }
} {0 105}

do_test lastinsert-7.5 {
    catchsql {
        select rin from rid where k=2;
    }
} {0 105}

do_test lastinsert-7.6 {
    catchsql {
        select rout from rid where k=2;
    }
} {0 1205}

do_test lastinsert-8.1 {
  db close
  sqlite4 db test.db
  execsql {
    CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
    CREATE TABLE t3(a, b);
    CREATE TRIGGER after_t2 AFTER INSERT ON t2 BEGIN
      INSERT INTO t3 VALUES(new.x, new.y);
    END;
    INSERT INTO t2 VALUES(5000000000, 1);
    SELECT last_insert_rowid();
  }
} 5000000000

do_test lastinsert-9.1 {
  db eval {INSERT INTO t2 VALUES(123456789012345,0)}
  db last_insert_rowid
} {123456789012345}


} ;# ifcapable (view && trigger)

finish_test
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































































































































































































































































































































Changes to test/test_main.c.
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  sqlite4_snprintf(zStr, sizeof(zStr), "abcdefghijklmnopqrstuvwxyz");
  sqlite4_snprintf(zStr, n, zFormat, a1);
  Tcl_AppendResult(interp, zStr, 0);
  return TCL_OK;
}



/*
** Usage:  sqlite4_last_insert_rowid DB
**
** Returns the integer ROWID of the most recent insert.
*/
static int test_last_rowid(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  char zBuf[30];

  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  sprintf(zBuf, "%lld", sqlite4_last_insert_rowid(db));
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE4_OK;
}

/*
** Usage:  sqlite4_key DB KEY
**
** Set the codec key.
*/
static int test_key(
  void *NotUsed,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







563
564
565
566
567
568
569

























570
571
572
573
574
575
576
  sqlite4_snprintf(zStr, sizeof(zStr), "abcdefghijklmnopqrstuvwxyz");
  sqlite4_snprintf(zStr, n, zFormat, a1);
  Tcl_AppendResult(interp, zStr, 0);
  return TCL_OK;
}



























/*
** Usage:  sqlite4_key DB KEY
**
** Set the codec key.
*/
static int test_key(
  void *NotUsed,
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
     { "sqlite4_mprintf_stronly",       (Tcl_CmdProc*)sqlite4_mprintf_stronly},
     { "sqlite4_mprintf_double",        (Tcl_CmdProc*)sqlite4_mprintf_double },
     { "sqlite4_mprintf_scaled",        (Tcl_CmdProc*)sqlite4_mprintf_scaled },
     { "sqlite4_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite4_mprintf_hexdouble},
     { "sqlite4_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
     { "sqlite4_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
     { "sqlite4_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
     { "sqlite4_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite4_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite4_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
     { "sqlite4_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite4_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
     { "sqlite4_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite4_create_function",       (Tcl_CmdProc*)test_create_function  },
     { "sqlite4_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },







<







4518
4519
4520
4521
4522
4523
4524

4525
4526
4527
4528
4529
4530
4531
     { "sqlite4_mprintf_stronly",       (Tcl_CmdProc*)sqlite4_mprintf_stronly},
     { "sqlite4_mprintf_double",        (Tcl_CmdProc*)sqlite4_mprintf_double },
     { "sqlite4_mprintf_scaled",        (Tcl_CmdProc*)sqlite4_mprintf_scaled },
     { "sqlite4_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite4_mprintf_hexdouble},
     { "sqlite4_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
     { "sqlite4_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
     { "sqlite4_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },

     { "sqlite4_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite4_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
     { "sqlite4_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite4_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
     { "sqlite4_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite4_create_function",       (Tcl_CmdProc*)test_create_function  },
     { "sqlite4_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },