]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Additional testing and bug fixing with the non-callback API. Updated the
authordrh <drh@noemail.net>
Wed, 29 Jan 2003 22:58:26 +0000 (22:58 +0000)
committerdrh <drh@noemail.net>
Wed, 29 Jan 2003 22:58:26 +0000 (22:58 +0000)
C/C++ interface document to describe the non-callback API. (CVS 855)

FossilOrigin-Name: af1e9299468aa70d7d91e7a5445ba391ccc8ff8b

manifest
manifest.uuid
src/btree.c
src/pager.c
src/test1.c
src/vdbe.c
test/capi2.test
www/c_interface.tcl
www/lang.tcl

index ce629e696c72b5df7cd2efa8e950cbdd2fa133aa..e9a033cb9328b11d6f8bea2174f1748c654bbb5f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Better\serror\smessages\son\sconstraint\sviolations.\s\sAdditional\stests\sand\sbug\sfixes\nfor\sthe\scallback-free\sAPI.\s(CVS\s854)
-D 2003-01-29T18:46:52
+C Additional\stesting\sand\sbug\sfixing\swith\sthe\snon-callback\sAPI.\s\sUpdated\sthe\nC/C++\sinterface\sdocument\sto\sdescribe\sthe\snon-callback\sAPI.\s(CVS\s855)
+D 2003-01-29T22:58:26
 F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -19,7 +19,7 @@ F publish.sh ce0bf7e235984bc156dc5d1a0c8092db4c8442f3
 F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
 F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
 F src/auth.c 9c2db0bc7707f2d2e227f47e3d557b41d44ade75
-F src/btree.c eb4f430b062500d7533c031097d3ff8824eca3ba
+F src/btree.c 668402ca441592d85da521309625bd1bcc6f010e
 F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda
 F src/build.c 6e0310086b8e2deef74f0d4fb3297c4e8fcf6222
 F src/delete.c cbd499f3f9297504c42e328af89bef1a2113d04c
@@ -33,7 +33,7 @@ F src/main.c 764a72e6a4f021ae1d3db7e82dab625075f4fedb
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c ed27e178e0c4b71f2807da81b8851f0fadc50778
 F src/os.h afa3e096213bad86845f8bdca81a9e917505e401
-F src/pager.c 95f5c5c775ed47e837ce02b407d80527d93e6c43
+F src/pager.c 7ca152bb9fcab56e2f6df62e2ebd20f538214fad
 F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626
 F src/parse.y cdaed5009423d851708848bd279147c268e6022e
 F src/printf.c f8fd911a8738f9b2eb07aca2870473d34707055d
@@ -45,7 +45,7 @@ F src/sqlite.h.in 6f648803f2ffb9beb35cb1cfa42b323d55519171
 F src/sqliteInt.h f22092ed33fea784f58bcd57b90c0babd16a0e29
 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
 F src/tclsqlite.c 9f2c00a92338c51171ded8943bd42d77f7e69e64
-F src/test1.c a24735c6e6364ccaa73ce3b106859fb325b076d9
+F src/test1.c eb05abd3ec6822f800476c04aed4db112690b144
 F src/test2.c 03f05e984c8e2f2badc44644d42baf72b249096b
 F src/test3.c c12ea7f1c3fbbd58904e81e6cb10ad424e6fc728
 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e
@@ -53,7 +53,7 @@ F src/tokenize.c bc40937d6666f188037aa3e54f0a2661a6fef6d1
 F src/trigger.c da142decd2808bc39e801f3bb1f161dbc2bd4005
 F src/update.c f06afa9bf1f777d17702e0f6e33cf44c44bc4f75
 F src/util.c 757875a366be838d96c09f255631596a2f558fca
-F src/vdbe.c de4c00495ed6d3c7798153996ea174881fc29b42
+F src/vdbe.c 2ad2510bc3d25db9da66054d33fdcadf54d25fff
 F src/vdbe.h ed43771f1dc2b994d5c484fdf2eab357c6ef0ee3
 F src/where.c 5bf7f1e1d756ab3d25a18b24bb42106cb8e14d18
 F test/all.test 873d30e25a41b3aa48fec5633a7ec1816e107029
@@ -64,7 +64,7 @@ F test/btree.test 10e75aec120ecefc0edc4c912a0980a43db1b6c2
 F test/btree2.test e3b81ec33dc2f89b3e6087436dfe605b870c9080
 F test/btree3.test e597fb59be2ac0ea69c62aaa2064e998e528b665
 F test/btree4.test fa955a3d7a8bc91d6084b7f494f9e5d1bdfb15b6
-F test/capi2.test 21f73319ae288d874f68787b5af4bd2022e25dcb
+F test/capi2.test b0b4b73b3e6a5babe8a4945fb7d74c2bc4443b15
 F test/conflict.test d7d9dbea9909c1b843f9e89c8318fdb7ca07a5e5
 F test/copy.test 73df5ed3112e858e006a8b7ddb4c9bab6a25d0fb
 F test/delete.test 5821a95a66061ae09723a88938f23d10d8a881ad
@@ -134,7 +134,7 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
 F www/arch.tcl 679a0c48817f71bc91d5911ef386e5ef35d4f178
 F www/audit.tcl 90e09d580f79c7efec0c7d6f447b7ec5c2dce5c0
-F www/c_interface.tcl e76c9fd609326c34cd45cd040b508b0e21908800
+F www/c_interface.tcl bca0aea880d043ed1bc0ad3bb39e24043f88b5bf
 F www/changes.tcl b48068eabfd0ff603d90f75b01bed295f23198e2
 F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
@@ -145,7 +145,7 @@ F www/faq.tcl 06276ff6c3e369374bb83034cc9d4a7d3a2a34a1
 F www/fileformat.tcl a4b5c2c6e89b7d42d09f97fd4d7bbd39cbf24936
 F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e
 F www/index.tcl b5265ca54a5124ec40bffb7c7943e072e074d61a
-F www/lang.tcl 1c11172bd6511b39d2c69f153a5e82332d0379ef
+F www/lang.tcl 7ad51d873059368a98bcc2afec60d6ba4bb5688a
 F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
 F www/nulls.tcl 29497dac2bc5b437aa7e2e94577dad4d8933ed26
 F www/omitted.tcl 118062f40a203fcb88b8d68ef1d7c0073ac191ec
@@ -155,7 +155,7 @@ F www/speed.tcl 4d463e2aea41f688ed320a937f93ff885be918c3
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 162b259188e6967fe9c3722da26b81aab5655d83
-R 715f66b82d831caba169ad25678a9655
+P ccc82f1ab4539a60ee5cc2625743c5389f9ccd8e
+R 71f3061b9977afdcd191ea15858b4f86
 U drh
-Z 12bd865865cbc9da0a476fa88511badb
+Z da2509caf930012c96a4743c5b339fae
index 54d77cb4ad8be86563dd93fa929610a8f45a7dce..1534f006efc449cb3a9395a36cd7a23066eea6a3 100644 (file)
@@ -1 +1 @@
-ccc82f1ab4539a60ee5cc2625743c5389f9ccd8e
\ No newline at end of file
+af1e9299468aa70d7d91e7a5445ba391ccc8ff8b
\ No newline at end of file
index db0ba024693c499b607062755a303d11d29dbb58..80bf9254fb85c80e2dd0ebf6c18cac54271b80d6 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.81 2003/01/24 12:14:20 drh Exp $
+** $Id: btree.c,v 1.82 2003/01/29 22:58:26 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -900,13 +900,13 @@ int sqliteBtreeRollback(Btree *pBt){
   if( pBt->inTrans==0 ) return SQLITE_OK;
   pBt->inTrans = 0;
   pBt->inCkpt = 0;
+  rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->pPage ){
+    if( pCur->pPage && pCur->pPage->isInit==0 ){
       sqlitepager_unref(pCur->pPage);
       pCur->pPage = 0;
     }
   }
-  rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
   unlockBtreeIfUnused(pBt);
   return rc;
 }
@@ -959,13 +959,13 @@ int sqliteBtreeRollbackCkpt(Btree *pBt){
   int rc;
   BtCursor *pCur;
   if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
+  rc = sqlitepager_ckpt_rollback(pBt->pPager);
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->pPage ){
+    if( pCur->pPage && pCur->pPage->isInit==0 ){
       sqlitepager_unref(pCur->pPage);
       pCur->pPage = 0;
     }
   }
-  rc = sqlitepager_ckpt_rollback(pBt->pPager);
   pBt->inCkpt = 0;
   return rc;
 }
index 6fada9c343b003387e14e38fe514a990a7a9ce16..7b0b4bd937c48f518fb9314c65e03f546bb059a9 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.71 2003/01/25 15:43:22 drh Exp $
+** @(#) $Id: pager.c,v 1.72 2003/01/29 22:58:26 drh Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -450,8 +450,19 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd){
     rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
   }
   if( pPg ){
-    memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
-    memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
+    if( pPg->nRef==0 ||
+        memcmp(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE)==0
+    ){
+      /* Do not update the data on this page if the page is in use
+      ** and the page has never been modified.  This avoids resetting
+      ** the "extra" data.  That in turn avoids invalidating BTree cursors
+      ** in trees that have never been modified.  The end result is that
+      ** you can have a SELECT going on in one table and ROLLBACK changes
+      ** to a different table and the SELECT is unaffected by the ROLLBACK.
+      */
+      memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
+      memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
+    }
     pPg->dirty = 0;
     pPg->needSync = 0;
   }
@@ -545,14 +556,18 @@ end_playback:
   if( rc==SQLITE_OK ){
     PgHdr *pPg;
     for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+      char zBuf[SQLITE_PAGE_SIZE];
       if( (int)pPg->pgno <= pPager->origDbSize ){
         sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
-        rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
+        rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
         if( rc ) break;
       }else{
-        memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
+        memset(zBuf, 0, SQLITE_PAGE_SIZE);
+      }
+      if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
+        memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
+        memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
       }
-      memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
       pPg->needSync = 0;
       pPg->dirty = 0;
     }
index b6fc45e6d80bf05e88d74bd1e54f73a659ebb303..9a0c7cdefcd3df2257ba801aa79a536afbbf984a 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.19 2003/01/29 18:46:53 drh Exp $
+** $Id: test1.c,v 1.20 2003/01/29 22:58:26 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -755,9 +755,9 @@ static int test_step(
 ){
   sqlite_vm *vm;
   int rc, i;
-  const char **azValue;
-  const char **azColName;
-  int N;
+  const char **azValue = 0;
+  const char **azColName = 0;
+  int N = 0;
   char *zRc;
   char zBuf[50];
   if( argc!=5 ){
@@ -767,17 +767,17 @@ static int test_step(
   }
   if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
   rc = sqlite_step(vm, &N, &azValue, &azColName);
-  if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
-    sprintf(zBuf, "%d", N);
-    Tcl_SetVar(interp, argv[2], zBuf, 0);
-    Tcl_SetVar(interp, argv[3], "", 0);
-    if( rc==SQLITE_ROW ){
-      for(i=0; i<N; i++){
-        Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "",
-            TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
-      }
+  sprintf(zBuf, "%d", N);
+  Tcl_SetVar(interp, argv[2], zBuf, 0);
+  Tcl_SetVar(interp, argv[3], "", 0);
+  if( azValue ){
+    for(i=0; i<N; i++){
+      Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "",
+          TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
     }
-    Tcl_SetVar(interp, argv[4], "", 0);
+  }
+  Tcl_SetVar(interp, argv[4], "", 0);
+  if( azColName ){
     for(i=0; i<N*2; i++){
       Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "",
           TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
index 3db04a1c874a5a5b3f66e108fedd8392a102eabe..67c7fdbd593f6383fd411d6c53aaf1a932e2f973 100644 (file)
@@ -36,7 +36,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.202 2003/01/29 18:46:53 drh Exp $
+** $Id: vdbe.c,v 1.203 2003/01/29 22:58:26 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -738,8 +738,8 @@ int sqlite_aggregate_count(sqlite_func *p){
 /*
 ** Advance the virtual machine to the next output row.
 **
-** The return vale will be either SQLITE_BUSY, SQLITE_DONE, or
-** SQLITE_ROW.
+** The return vale will be either SQLITE_BUSY, SQLITE_DONE, 
+** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.
 **
 ** SQLITE_BUSY means that the virtual machine attempted to open
 ** a locked database and there is no busy callback registered.
@@ -759,9 +759,16 @@ int sqlite_aggregate_count(sqlite_func *p){
 ** The name of the i-th column is (*pazColName)[i] and the datatype
 ** of the i-th column is (*pazColName)[i+*pN].
 **
-** If a run-time error is encountered, SQLITE_DONE is returned.  You
-** can access the error code and error message using the sqlite_finalize()
-** routine. 
+** SQLITE_ERROR means that a run-time error (such as a constraint
+** violation) has occurred.  The details of the error will be returned
+** by the next call to sqlite_finalize().  sqlite_step() should not
+** be called again on the VM.
+**
+** SQLITE_MISUSE means that the this routine was called inappropriately.
+** Perhaps it was called on a virtual machine that had already been
+** finalized or on one that had previously returned SQLITE_ERROR or
+** SQLITE_DONE.  Or it could be the case the the same database connection
+** is being used simulataneously by two or more threads.
 */
 int sqlite_step(
   sqlite_vm *pVm,              /* The virtual machine to execute */
@@ -1588,7 +1595,8 @@ int sqliteVdbeExec(
 
   if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
   assert( db->magic==SQLITE_MAGIC_BUSY );
-  assert( p->rc==SQLITE_OK );
+  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+  p->rc = SQLITE_OK;
   assert( p->explain==0 );
   if( sqlite_malloc_failed ) goto no_mem;
   if( p->popStack ){
index 796f4710a385fa12433d4c27262cb33d0c12e3e2..b29797e8d07e99d2b7dc82a6e415c66ed27e3e0d 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script testing the callback-free C/C++ API.
 #
-# $Id: capi2.test,v 1.2 2003/01/29 18:46:54 drh Exp $
+# $Id: capi2.test,v 1.3 2003/01/29 22:58:27 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -55,7 +55,7 @@ do_test capi2-1.8 {
 } {SQLITE_MISUSE}
 do_test capi2-1.9 {
   list $N $VALUES $COLNAMES
-} {x y z}
+} {0 {} {}}
 do_test capi2-1.10 {
   sqlite_finalize $VM
 } {}
@@ -175,6 +175,219 @@ do_test capi2-3.13 {
 do_test capi2-3.14 {
   list [catch {sqlite_finalize $VM} msg] [set msg]
 } {1 {(19) uniqueness constraint failed}}
+do_test capi2-3.15 {
+  set VM [sqlite_compile $DB {CREATE TABLE t2(a NOT NULL, b)} TAIL]
+  set TAIL
+} {}
+do_test capi2-3.16 {
+  list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-3.17 {
+  list [catch {sqlite_finalize $VM} msg] [set msg]
+} {0 {}}
+do_test capi2-3.18 {
+  set VM [sqlite_compile $DB {INSERT INTO t2 VALUES(NULL,2)} TAIL]
+  list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ERROR 0 {} {}}
+do_test capi2-3.19 {
+  list [catch {sqlite_finalize $VM} msg] [set msg]
+} {1 {(19) t2.a may not be NULL}}
+
+# Two or more virtual machines exists at the same time.
+#
+do_test capi2-4.1 {
+  set VM1 [sqlite_compile $DB {INSERT INTO t2 VALUES(1,2)} TAIL]
+  set TAIL
+} {}
+do_test capi2-4.2 {
+  set VM2 [sqlite_compile $DB {INSERT INTO t2 VALUES(2,3)} TAIL]
+  set TAIL
+} {}
+do_test capi2-4.3 {
+  set VM3 [sqlite_compile $DB {INSERT INTO t2 VALUES(3,4)} TAIL]
+  set TAIL
+} {}
+do_test capi2-4.4 {
+  list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.5 {
+  execsql {SELECT * FROM t2 ORDER BY a}
+} {2 3}
+do_test capi2-4.6 {
+  list [catch {sqlite_finalize $VM2} msg] [set msg]
+} {0 {}}  
+do_test capi2-4.7 {
+  list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.8 {
+  execsql {SELECT * FROM t2 ORDER BY a}
+} {2 3 3 4}
+do_test capi2-4.9 {
+  list [catch {sqlite_finalize $VM3} msg] [set msg]
+} {0 {}}  
+do_test capi2-4.10 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 0 {} {}}
+do_test capi2-4.11 {
+  execsql {SELECT * FROM t2 ORDER BY a}
+} {1 2 2 3 3 4}
+do_test capi2-4.12 {
+  list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}  
 
+# Interleaved SELECTs
+#
+do_test capi2-5.1 {
+  set VM1 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+  set VM2 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+  set VM3 [sqlite_compile $DB {SELECT * FROM t2} TAIL]
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.2 {
+  list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.3 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.4 {
+  list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {2 3} {a b {} {}}}
+do_test capi2-5.5 {
+  list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.6 {
+  list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.7 {
+  list [sqlite_step $VM3 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_DONE 2 {} {a b {} {}}}
+do_test capi2-5.8 {
+  list [catch {sqlite_finalize $VM3} msg] [set msg]
+} {0 {}}  
+do_test capi2-5.9 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.10 {
+  list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}  
+do_test capi2-5.11 {
+  list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {3 4} {a b {} {}}}
+do_test capi2-5.12 {
+  list [sqlite_step $VM2 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 2 {1 2} {a b {} {}}}
+do_test capi2-5.11 {
+  list [catch {sqlite_finalize $VM2} msg] [set msg]
+} {0 {}}  
+
+# Check for proper SQLITE_BUSY returns.
+#
+do_test capi2-6.1 {
+  execsql {
+    BEGIN;
+    CREATE TABLE t3(x counter);
+    INSERT INTO t3 VALUES(1);
+    INSERT INTO t3 VALUES(2);
+    INSERT INTO t3 SELECT x+2 FROM t3;
+    INSERT INTO t3 SELECT x+4 FROM t3;
+    INSERT INTO t3 SELECT x+8 FROM t3;
+    COMMIT;
+  }
+  set VM1 [sqlite_compile $DB {SELECT * FROM t3} TAIL]
+  sqlite db2 test.db
+  execsql {BEGIN} db2
+} {}
+do_test capi2-6.2 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_BUSY 0 {} {}}
+do_test capi2-6.3 {
+  execsql {COMMIT} db2
+} {}
+do_test capi2-6.4 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 1 {x counter}}
+do_test capi2-6.5 {
+  catchsql {BEGIN} db2
+} {1 {database is locked}}
+do_test capi2-6.6 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 2 {x counter}}
+do_test capi2-6.7 {
+  execsql {SELECT * FROM t2} db2
+} {2 3 3 4 1 2}
+do_test capi2-6.8 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 3 {x counter}}
+do_test capi2-6.9 {
+  execsql {SELECT * FROM t2} 
+} {2 3 3 4 1 2}
+do_test capi2-6.10 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 4 {x counter}}
+do_test capi2-6.11 {
+  execsql {BEGIN}
+} {}
+do_test capi2-6.12 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 5 {x counter}}
+# execsql {pragma vdbe_trace=on}
+do_test capi2-6.13 {
+  catchsql {UPDATE t3 SET x=x+1}
+} {1 {database table is locked}}
+do_test capi2-6.14 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 6 {x counter}}
+# puts [list [catch {sqlite_finalize $VM1} msg] [set msg]]; exit
+do_test capi2-6.15 {
+  execsql {SELECT * FROM t1}
+} {1 2 3}
+do_test capi2-6.16 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 7 {x counter}}
+do_test capi2-6.17 {
+  catchsql {UPDATE t1 SET b=b+1}
+} {0 {}}
+do_test capi2-6.18 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 8 {x counter}}
+do_test capi2-6.19 {
+  execsql {SELECT * FROM t1}
+} {1 3 3}
+do_test capi2-6.20 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 9 {x counter}}
+do_test capi2-6.21 {
+  execsql {ROLLBACK; SELECT * FROM t1}
+} {1 2 3}
+do_test capi2-6.22 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 10 {x counter}}
+do_test capi2-6.23 {
+  execsql {BEGIN TRANSACTION ON CONFLICT ROLLBACK;}
+} {}
+do_test capi2-6.24 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 11 {x counter}}
+do_test capi2-6.25 {
+  execsql {
+    INSERT INTO t1 VALUES(2,3,4);
+    SELECT * FROM t1;
+  }
+} {1 2 3 2 3 4}
+do_test capi2-6.26 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 12 {x counter}}
+do_test capi2-6.27 {
+  catchsql {
+    INSERT INTO t1 VALUES(2,4,5);
+    SELECT * FROM t1;
+  }
+} {1 {uniqueness constraint failed}}
+do_test capi2-6.28 {
+  list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME]
+} {SQLITE_ROW 1 13 {x counter}}
+do_test capi2-6.99 {
+  list [catch {sqlite_finalize $VM1} msg] [set msg]
+} {0 {}}
 
 finish_test
index b1b8855d64dbf49bc0b7d568179c49ac2715a9be..4798c188e2a163e605c489c25f6dbc1fe10b27fb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: c_interface.tcl,v 1.35 2002/08/24 18:24:57 drh Exp $}
+set rcsid {$Id: c_interface.tcl,v 1.36 2003/01/29 22:58:27 drh Exp $}
 
 puts {<html>
 <head>
@@ -20,7 +20,7 @@ puts {
 a C or C++ program.  This document gives an overview of the C/C++
 programming interface.</p>
 
-<h2>The Core API</h2>
+<h2>1.0 The Core API</h2>
 
 <p>The interface to the SQLite library consists of three core functions,
 one opaque data structure, and some constants used as return values.
@@ -32,26 +32,28 @@ typedef struct sqlite sqlite;
 
 sqlite *sqlite_open(const char *dbname, int mode, char **errmsg);
 
-void sqlite_close(sqlite*);
+void sqlite_close(sqlite *db);
 
 int sqlite_exec(
-  sqlite*,
+  sqlite *db,
   char *sql,
-  int (*)(void*,int,char**,char**),
-  void*,
+  int (*xCallback)(void*,int,char**,char**),
+  void *pArg,
   char **errmsg
 );
 </pre></blockquote>
 
 <p>
 The above is all you really need to know in order to use SQLite
-in your C or C++ programs.  There are other convenience functions
+in your C or C++ programs.  There are other interface functions
 available (and described below) but we will begin by describing
 the core functions shown above.
 </p>
-<h2>Opening a database</h2>
 
-<p>Use the <b>sqlite_open()</b> function to open an existing SQLite
+<a name="sqlite_open">
+<h3>1.1 Opening a database</h3>
+
+<p>Use the <b>sqlite_open</b> function to open an existing SQLite
 database or to create a new SQLite database.  The first argument
 is the database name.  The second argument is intended to signal
 whether the database is going to be used for reading and writing
@@ -74,28 +76,30 @@ additional temporary files may be created during the execution of
 an SQL command in order to store the database rollback journal or
 temporary and intermediate results of a query.</p>
 
-<p>The return value of the <b>sqlite_open()</b> function is a
+<p>The return value of the <b>sqlite_open</b> function is a
 pointer to an opaque <b>sqlite</b> structure.  This pointer will
 be the first argument to all subsequent SQLite function calls that
 deal with the same database.  NULL is returned if the open fails
 for any reason.</p>
 
-<h2>Closing the database</h2>
+<a name="sqlite_close">
+<h3>1.2 Closing the database</h3>
 
-<p>To close an SQLite database, call the <b>sqlite_close()</b>
+<p>To close an SQLite database, call the <b>sqlite_close</b>
 function passing it the sqlite structure pointer that was obtained
 from a prior call to <b>sqlite_open</b>.
 If a transaction is active when the database is closed, the transaction
 is rolled back.</p>
 
-<h2>Executing SQL statements</h2>
+<a name="sqlite_exec">
+<h3>1.3 Executing SQL statements</h3>
 
-<p>The <b>sqlite_exec()</b> function is used to process SQL statements
+<p>The <b>sqlite_exec</b> function is used to process SQL statements
 and queries.  This function requires 5 parameters as follows:</p>
 
 <ol>
 <li><p>A pointer to the sqlite structure obtained from a prior call
-       to <b>sqlite_open()</b>.</p></li>
+       to <b>sqlite_open</b>.</p></li>
 <li><p>A null-terminated string containing the text of one or more
        SQL statements and/or queries to be processed.</p></li>
 <li><p>A pointer to a callback function which is invoked once for each
@@ -121,8 +125,9 @@ int Callback(void *pArg, int argc, char **argv, char **columnNames){
 }
 </pre></blockquote>
 
+<a name="callback_row_data">
 <p>The first argument to the callback is just a copy of the fourth argument
-to <b>sqlite_exec()</b>  This parameter can be used to pass arbitrary
+to <b>sqlite_exec</b>  This parameter can be used to pass arbitrary
 information through to the callback function from client code.
 The second argument is the number of columns in the query result.
 The third argument is an array of pointers to strings where each string
@@ -137,9 +142,17 @@ argv[i][0] == 0
 <blockquote><pre>
 argv[i] == 0
 </pre></blockquote>
-<p>The names of the columns are contained in the fourth argument.</p>
 
-<p>If the EMPTY_RESULT_CALLBACKS pragma is set to ON and the result of
+<p>The names of the columns are contained in first <i>argc</i>
+entries of the fourth argument.
+If the <a href="lang.html#pragma_show_datatypes">SHOW_DATATYPES</a> pragma
+is on (it is off by default) then
+the second <i>argc</i> entries in the 4th argument are the datatypes
+for the corresponding columns.
+</p>
+
+<p>If the <a href="lang.html#pragma_empty_result_callbacks">
+EMPTY_RESULT_CALLBACKS</a> pragma is set to ON and the result of
 a query is an empty set, then the callback is invoked once with the
 third parameter (argv) set to 0.  In other words
 <blockquote><pre>
@@ -152,14 +165,15 @@ columns if there had been a result.
 The default behavior is not to invoke the callback at all if the
 result set is empty.</p>
 
+<a name="callback_returns_nonzero">
 <p>The callback function should normally return 0.  If the callback
 function returns non-zero, the query is immediately aborted and 
-<b>sqlite_exec()</b> will return SQLITE_ABORT.</p>
+<b>sqlite_exec</b> will return SQLITE_ABORT.</p>
 
-<h2>Error Codes</h2>
+<h3>1.4 Error Codes</h3>
 
 <p>
-The <b>sqlite_exec()</b> function normally returns SQLITE_OK.  But
+The <b>sqlite_exec</b> function normally returns SQLITE_OK.  But
 if something goes wrong it can return a different value to indicate
 the type of error.  Here is a complete list of the return codes:
 </p>
@@ -187,6 +201,10 @@ the type of error.  Here is a complete list of the return codes:
 #define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
 #define SQLITE_MISMATCH    20   /* Data type mismatch */
 #define SQLITE_MISUSE      21   /* Library used incorrectly */
+#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
+#define SQLITE_AUTH        23   /* Authorization denied */
+#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
+#define SQLITE_DONE        101  /* sqlite_step() has finished executing */
 </pre></blockquote>
 
 <p>
@@ -202,12 +220,12 @@ The meanings of these various return values are as follows:
 <dd><p>This value indicates that an internal consistency check within
 the SQLite library failed.  This can only happen if there is a bug in
 the SQLite library.  If you ever get an SQLITE_INTERNAL reply from
-an <b>sqlite_exec()</b> call, please report the problem on the SQLite
+an <b>sqlite_exec</b> call, please report the problem on the SQLite
 mailing list.
 </p></dd>
 <dt>SQLITE_ERROR</dt>
 <dd><p>This return value indicates that there was an error in the SQL
-that was passed into the <b>sqlite_exec()</b>.
+that was passed into the <b>sqlite_exec</b>.
 </p></dd>
 <dt>SQLITE_PERM</dt>
 <dd><p>This return value says that the access permissions on the database
@@ -226,21 +244,21 @@ entire database.</p>
 <dt>SQLITE_LOCKED</dt>
 <dd><p>This return code is similar to SQLITE_BUSY in that it indicates
 that the database is locked.  But the source of the lock is a recursive
-call to <b>sqlite_exec()</b>.  This return can only occur if you attempt
-to invoke sqlite_exec() from within a callback routine of a query
-from a prior invocation of sqlite_exec().  Recursive calls to
-sqlite_exec() are allowed as long as they do
+call to <b>sqlite_exec</b>.  This return can only occur if you attempt
+to invoke sqlite_exec from within a callback routine of a query
+from a prior invocation of sqlite_exec.  Recursive calls to
+sqlite_exec are allowed as long as they do
 not attempt to write the same table.
 </p></dd>
 <dt>SQLITE_NOMEM</dt>
-<dd><p>This value is returned if a call to <b>malloc()</b> fails.
+<dd><p>This value is returned if a call to <b>malloc</b> fails.
 </p></dd>
 <dt>SQLITE_READONLY</dt>
 <dd><p>This return code indicates that an attempt was made to write to
 a database file that is opened for reading only.
 </p></dd>
 <dt>SQLITE_INTERRUPT</dt>
-<dd><p>This value is returned if a call to <b>sqlite_interrupt()</b>
+<dd><p>This value is returned if a call to <b>sqlite_interrupt</b>
 interrupts a database operation in progress.
 </p></dd>
 <dt>SQLITE_IOERR</dt>
@@ -298,16 +316,249 @@ an INTEGER PRIMARY KEY column is only allowed to store integer data.
 <dt>SQLITE_MISUSE</dt>
 <dd><p>This error might occur if one or more of the SQLite API routines
 is used incorrectly.  Examples of incorrect usage include calling
-<b>sqlite_exec()</b> after the database has been closed using
-<b>sqlite_close()</b> or calling <b>sqlite_exec()</b> with the same
+<b>sqlite_exec</b> after the database has been closed using
+<b>sqlite_close</b> or 
+calling <b>sqlite_exec</b> with the same
 database pointer simultaneously from two separate threads.
 </p></dd>
+<dt>SQLITE_NOLFS</dt>
+<dd><p>This error means that you have attempts to create or access a file
+database file that is larger that 2GB on a legacy Unix machine that
+lacks large file support.
+</p></dd>
+<dt>SQLITE_AUTH</dt>
+<dd><p>This error indicates that the authorizer callback
+has disallowed the SQL you are attempting to execute.
+</p></dd>
+<dt>SQLITE_ROW</dt>
+<dd><p>This is one of the return codes from the
+<b>sqlite_step</b> routine which is part of the non-callback API.
+It indicates that another row of result data is available.
+</p></dd>
+<dt>SQLITE_DONE</dt>
+<dd><p>This is one of the return codes from the
+<b>sqlite_step</b> routine which is part of the non-callback API.
+It indicates that the SQL statement has been completely executed and
+the <b>sqlite_finalize</b> routine is ready to be called.
+</p></dd>
 </dl>
 </blockquote>
 
-<h2>The Extended API</h2>
+<h2>2.0 Accessing Data Without Using A Callback Function</h2>
+
+<p>
+The <b>sqlite_exec</b> routine described above used to be the only
+way to retrieve data from an SQLite database.  But many programmers found
+it inconvenient to use a callback function to obtain results.  So beginning
+with SQLite version 2.7.7, a second access interface is available that
+does not use callbacks.
+</p>
+
+<p>
+The new interface uses three separate functions to replace the single
+<b>sqlite_exec</b> function.
+</p>
+
+<blockquote><pre>
+typedef struct sqlite_vm sqlite_vm;
+
+int sqlite_compile(
+  sqlite *db,              /* The open database */
+  const char *zSql,        /* SQL statement to be compiled */
+  const char **pzTail,     /* OUT: uncompiled tail of zSql */
+  sqlite_vm **ppVm,        /* OUT: the virtual machine to execute zSql */
+  char **pzErrmsg          /* OUT: Error message. */
+);
+
+int sqlite_step(
+  sqlite_vm *pVm,          /* The virtual machine to execute */
+  int *pN,                 /* OUT: Number of columns in result */
+  const char ***pazValue,  /* OUT: Column data */
+  const char ***pazColName /* OUT: Column names and datatypes */
+);
+
+int sqlite_finalize(
+  sqlite_vm *pVm,          /* The virtual machine to be finalized */
+  char **pzErrMsg          /* OUT: Error message */
+);
+</pre></blockquote>
+
+<p>
+The strategy is to compile a single SQL statement using
+<b>sqlite_compile</b> then invoke <b>sqlite_step</b> multiple times,
+once for each row of output, and finally call <b>sqlite_finalize</b>
+to clean up after the SQL has finished execution.
+</p>
+
+<h3>2.1 Compiling An SQL Statement Into A Virtual Machine</h3>
+
+<p>
+The <b>sqlite_compile</b> "compiles" a single SQL statement (specified
+by the second parameter) and generates a virtual machine that is able
+to execute that statement.  
+As with must interface routines, the first parameter must be a pointer
+to an sqlite structure that was obtained from a prior call to
+<b>sqlite_open</b>.
+
+<p>
+A pointer to the virtual machine is stored in a pointer which is passed
+in as the 4th parameter.
+Space to hold the virtual machine is dynamically allocated.  To avoid
+a memory leak, the calling function must invoke
+<b>sqlite_finalize</b> on the virtual machine after it has finished
+with it.
+The 4th parameter may be set to NULL if an error is encountered during
+compilation.
+</p>
+
+<p>
+If any errors are encountered during compilation, an error message is
+written into memory obtained from <b>malloc</b> and the 5th parameter
+is made to point to that memory.  If the 5th parameter is NULL, then
+no error message is generated.  If the 5th parameter is not NULL, then
+the calling function should dispose of the memory containing the error
+message by calling <b>sqlite_freemem</b>.
+</p>
+
+<p>
+If the 2nd parameter actually contains two or more statements of SQL,
+only the first statement is compiled.  (This is different from the
+behavior of <b>sqlite_exec</b> which executes all SQL statements
+in its input string.)  The 3rd parameter to <b>sqlite_compile</b>
+is made to point to the first character beyond the end of the first
+statement of SQL in the input.  If the 2nd parameter contains only
+a single SQL statement, then the 3rd parameter will be made to point
+to the '\000' terminator at the end of the 2nd parameter.
+</p>
+
+<p>
+On success, <b>sqlite_compile</b> returns SQLITE_OK.
+Otherwise and error code is returned.
+</p>
+
+<h3>2.2 Step-By-Step Execution Of An SQL Statement</h3>
+
+<p>
+After a virtual machine has been generated using <b>sqlite_compile</b>
+it is executed by one or more calls to <b>sqlite_step</b>.  Each
+invocation of <b>sqlite_step</b>, except the last one,
+returns a single row of the result.
+The number of columns in  the result is stored in the integer that
+the 2nd parameter points to.
+The pointer specified by the 3rd parameter is made to point
+to an array of pointers to column values.
+The pointer in the 4th parameter is made to point to an array
+of pointers to column names and datatypes.
+The 2nd through 4th parameters to <b>sqlite_step</b> convey the
+same information as the 2nd through 4th parameters of the
+<b>callback</b> routine when using
+the <b>sqlite_exec</b> interface.  Except, with <b>sqlite_step</b>
+the column datatype information is always included in the in the
+4th parameter regardless of whether or not the
+<a href="lang.html#pragma_show_datatypes">SHOW_DATATYPES</a> pragma
+is on or off.
+</p>
+
+<p>
+Each invocation of <b>sqlite_step</b> returns an integer code that
+indicates what happened during that step.  This code may be
+SQLITE_BUSY, SQLITE_ROW, SQLITE_DONE, SQLITE_ERROR, or
+SQLITE_MISUSE.
+</p>
+
+<p>
+If the virtual machine is unable to open the database file because
+it is locked by another thread or process, <b>sqlite_step</b>
+will return SQLITE_BUSY.  The calling function should do some other
+activity, or sleep, for a short amount of time to give the lock a
+chance to clear, then invoke <b>sqlite_step</b> again.  This can
+be repeated as many times as desired.
+</p>
+
+<p>
+Whenever another row of result data is available,
+<b>sqlite_step</b> will return SQLITE_ROW.  The row data is
+stored in an array of pointers to strings and the 2nd parameter
+is made to point to this array.
+</p>
+
+<p>
+When all processing is complete, <b>sqlite_step</b> will return
+either SQLITE_DONE or SQLITE_ERROR.  SQLITE_DONE indicates that the
+statement completed successfully and SQLITE_ERROR indicates that there
+was a run-time error.  (The details of the error are obtained from
+<b>sqlite_finalize</b>.)  It is a misuse of the library to attempt
+to call <b>sqlite_step</b> again after it has returned SQLITE_DONE
+or SQLITE_ERROR.
+</p>
+
+<p>
+When <b>sqlite_step</b> returns SQLITE_DONE or SQLITE_ERROR,
+the *pN and *pazColName values are set to the number of columns
+in the result set and to the names of the columns, just as they
+are for an SQLITE_ROW return.  This allows the calling code to
+find the number of result columns and the column names and datatypes
+even if the result set is empty.  The *pazValue parameter is always
+set to NULL when the return codes is SQLITE_DONE or SQLITE_ERROR.
+If the SQL being executed is a statement that does not
+return a result (such as an INSERT or an UPDATE) then *pN will
+be set to zero and *pazColName will be set to NULL.
+</p>
+
+<p>
+If you abuse the library by trying to call <b>sqlite_step</b>
+inappropriately it will attempt return SQLITE_MISUSE.
+This can happen if you call sqlite_step() on the same virtual machine
+at the same
+time from two or more threads or if you call sqlite_step()
+again after it returned SQLITE_DONE or SQLITE_ERROR or if you
+pass in an invalid virtual machine pointer to sqlite_step().
+You should not depend on the SQLITE_MISUSE return code to indicate
+an error.  It is possible that a misuse of the interface will go
+undetected and result in a program crash.  The SQLITE_MISUSE is
+intended as a debugging aid only - to help you detect incorrect
+usage prior to a mishap.  The misuse detection logic is not guaranteed
+to work in every case.
+</p>
+
+<h3>2.3 Deleting A Virtual Machine</h3>
+
+<p>
+Every virtual machine that <b>sqlite_compile</b> creates should
+eventually be handed to <b>sqlite_finalize</b>.  The sqlite_finalize()
+procedure deallocates the memory and other resources that the virtual
+machine uses.  Failure to call sqlite_finalize() will result in 
+resource leaks in your program.
+</p>
+
+<p>
+The <b>sqlite_finalize</b> routine also returns the result code
+that indicates success or failure of the SQL operation that the
+virtual machine carried out.
+The value returned by sqlite_finalize() will be the same as would
+have been returned had the same SQL been executed by <b>sqlite_exec</b>.
+The error message returned will also be the same.
+</p>
+
+<p>
+It is acceptable to call <b>sqlite_finalize</b> on a virtual machine
+before <b>sqlite_step</b> has returned SQLITE_DONE.  Doing so has
+the effect of interrupting the operation in progress.  Partially completed
+changes will be rolled back and the database will be restored to its
+original state (unless an alternative recovery algorithm is selected using
+an ON CONFLICT clause in the SQL being executed.)  The effect is the
+same as if a callback function of <b>sqlite_exec</b> had returned
+non-zero.
+</p>
+
+<p>
+It is also acceptable to call <b>sqlite_finalize</b> on a virtual machine
+that has never been passed to <b>sqlite_step</b> even once.
+</p>
+
+<h2>3.0 The Extended API</h2>
 
-<p>Only the three core routines shown above are required to use
+<p>Only the three core routines described in section 1.0 are required to use
 SQLite.  But there are many other functions that provide 
 useful interfaces.  These extended routines are as follows:
 </p>
@@ -389,7 +640,7 @@ void sqlite_freemem(char*);
 <p>All of the above definitions are included in the "sqlite.h"
 header file that comes in the source tree.</p>
 
-<h2>The ROWID of the most recent insert</h2>
+<h3>3.1 The ROWID of the most recent insert</h3>
 
 <p>Every row of an SQLite table has a unique integer key.  If the
 table has a column labeled INTEGER PRIMARY KEY, then that column
@@ -403,33 +654,33 @@ KEY column, or if the table does have an INTEGER PRIMARY KEY but the value
 for that column is not specified in the VALUES clause of the insert, then
 the key is automatically generated.  You can find the value of the key
 for the most recent INSERT statement using the
-<b>sqlite_last_insert_rowid()</b> API function.</p>
+<b>sqlite_last_insert_rowid</b> API function.</p>
 
-<h2>The number of rows that changed</h2>
+<h3>3.2 The number of rows that changed</h3>
 
-<p>The <b>sqlite_changes()</b> API function returns the number of rows
+<p>The <b>sqlite_changes</b> API function returns the number of rows
 that were inserted, deleted, or modified during the most recent
-<b>sqlite_exec()</b> call.  The number reported includes any changes
+<b>sqlite_exec</b> call.  The number reported includes any changes
 that were later undone by a ROLLBACK or ABORT.  But rows that are
 deleted because of a DROP TABLE are <em>not</em> counted.</p>
 
 <p>SQLite implements the command "<b>DELETE FROM table</b>" (without
 a WHERE clause) by dropping the table then recreating it.  
 This is much faster than deleting the elements of the table individually.
-But it also means that the value returned from <b>sqlite_changes()</b>
+But it also means that the value returned from <b>sqlite_changes</b>
 will be zero regardless of the number of elements that were originally
 in the table.  If an accurate count of the number of elements deleted
 is necessary, use "<b>DELETE FROM table WHERE 1</b>" instead.</p>
 
-<h2>Querying without using a callback function</h2>
+<h3>3.3 Querying into memory obtained from malloc()</h3>
 
-<p>The <b>sqlite_get_table()</b> function is a wrapper around
-<b>sqlite_exec()</b> that collects all the information from successive
+<p>The <b>sqlite_get_table</b> function is a wrapper around
+<b>sqlite_exec</b> that collects all the information from successive
 callbacks and writes it into memory obtained from malloc().  This
 is a convenience function that allows the application to get the
 entire result of a database query with a single function call.</p>
 
-<p>The main result from <b>sqlite_get_table()</b> is an array of pointers
+<p>The main result from <b>sqlite_get_table</b> is an array of pointers
 to strings.  There is one element in this array for each column of
 each row in the result.  NULL results are represented by a NULL
 pointer. In addition to the regular data, there is an added row at the 
@@ -444,7 +695,7 @@ SELECT employee_name, login, host FROM users WHERE logic LIKE 'd%';
 
 <p>This query will return the name, login and host computer name
 for every employee whose login begins with the letter "d".  If this
-query is submitted to <b>sqlite_get_table()</b> the result might
+query is submitted to <b>sqlite_get_table</b> the result might
 look like this:</p>
 
 <blockquote>
@@ -465,7 +716,7 @@ result[8] = "zadok"
 the result[] array contains a NULL pointer at that slot.</p>
 
 <p>If the result set of a query is empty, then by default
-<b>sqlite_get_table()</b> will set nrow to 0 and leave its
+<b>sqlite_get_table</b> will set nrow to 0 and leave its
 result parameter is set to NULL.  But if the EMPTY_RESULT_CALLBACKS
 pragma is ON then the result parameter is initialized to the names
 of the columns only.  For example, consider this query which has
@@ -498,47 +749,47 @@ result[1] = "login"<br>
 result[2] = "host"<br>
 </blockquote>
 
-<p>Memory to hold the information returned by <b>sqlite_get_table()</b>
+<p>Memory to hold the information returned by <b>sqlite_get_table</b>
 is obtained from malloc().  But the calling function should not try
 to free this information directly.  Instead, pass the complete table
-to <b>sqlite_free_table()</b> when the table is no longer needed.
-It is safe to call <b>sqlite_free_table()</b> with a NULL pointer such
+to <b>sqlite_free_table</b> when the table is no longer needed.
+It is safe to call <b>sqlite_free_table</b> with a NULL pointer such
 as would be returned if the result set is empty.</p>
 
-<p>The <b>sqlite_get_table()</b> routine returns the same integer
-result code as <b>sqlite_exec()</b>.</p>
+<p>The <b>sqlite_get_table</b> routine returns the same integer
+result code as <b>sqlite_exec</b>.</p>
 
-<h2>Interrupting an SQLite operation</h2>
+<h3>3.4 Interrupting an SQLite operation</h3>
 
-<p>The <b>sqlite_interrupt()</b> function can be called from a
+<p>The <b>sqlite_interrupt</b> function can be called from a
 different thread or from a signal handler to cause the current database
 operation to exit at its first opportunity.  When this happens,
-the <b>sqlite_exec()</b> routine (or the equivalent) that started
+the <b>sqlite_exec</b> routine (or the equivalent) that started
 the database operation will return SQLITE_INTERRUPT.</p>
 
-<h2>Testing for a complete SQL statement</h2>
+<h3>3.5 Testing for a complete SQL statement</h3>
 
 <p>The next interface routine to SQLite is a convenience function used
 to test whether or not a string forms a complete SQL statement.
-If the <b>sqlite_complete()</b> function returns true when its input
+If the <b>sqlite_complete</b> function returns true when its input
 is a string, then the argument forms a complete SQL statement.
 There are no guarantees that the syntax of that statement is correct,
-but we at least know the statement is complete.  If <b>sqlite_complete()</b>
+but we at least know the statement is complete.  If <b>sqlite_complete</b>
 returns false, then more text is required to complete the SQL statement.</p>
 
-<p>For the purpose of the <b>sqlite_complete()</b> function, an SQL
+<p>For the purpose of the <b>sqlite_complete</b> function, an SQL
 statement is complete if it ends in a semicolon.</p>
 
-<p>The <b>sqlite</b> command-line utility uses the <b>sqlite_complete()</b>
-function to know when it needs to call <b>sqlite_exec()</b>.  After each
-line of input is received, <b>sqlite</b> calls <b>sqlite_complete()</b>
-on all input in its buffer.  If <b>sqlite_complete()</b> returns true, 
-then <b>sqlite_exec()</b> is called and the input buffer is reset.  If
-<b>sqlite_complete()</b> returns false, then the prompt is changed to
+<p>The <b>sqlite</b> command-line utility uses the <b>sqlite_complete</b>
+function to know when it needs to call <b>sqlite_exec</b>.  After each
+line of input is received, <b>sqlite</b> calls <b>sqlite_complete</b>
+on all input in its buffer.  If <b>sqlite_complete</b> returns true, 
+then <b>sqlite_exec</b> is called and the input buffer is reset.  If
+<b>sqlite_complete</b> returns false, then the prompt is changed to
 the continuation prompt and another line of text is read and added to
 the input buffer.</p>
 
-<h2>Library version string</h2>
+<h3>3.6 Library version string</h3>
 
 <p>The SQLite library exports the string constant named
 <b>sqlite_version</b> which contains the version number of the
@@ -548,7 +799,7 @@ the SQLITE_VERSION macro against the <b>sqlite_version</b>
 string constant to verify that the version number of the
 header file and the library match.</p> 
 
-<h2>Library character encoding</h2>
+<h3>3.7 Library character encoding</h3>
 
 <p>By default, SQLite assumes that all data uses a fixed-size
 8-bit character (iso8859).  But if you give the --enable-utf8 option
@@ -565,9 +816,9 @@ be changed at run-time.  This is a compile-time option only.  The
 <b>sqlite_encoding</b> character string just tells you how the library
 was compiled.</p>
 
-<h2>Changing the library's response to locked files</h2>
+<h3>3.8 Changing the library's response to locked files</h3>
 
-<p>The <b>sqlite_busy_handler()</b> procedure can be used to register
+<p>The <b>sqlite_busy_handler</b> procedure can be used to register
 a busy callback with an open SQLite database.  The busy callback will
 be invoked whenever SQLite tries to access a database that is locked.
 The callback will typically do some other useful work, or perhaps sleep,
@@ -576,8 +827,8 @@ non-zero, then SQLite tries again to access the database and the cycle
 repeats.  If the callback returns zero, then SQLite aborts the current
 operation and returns SQLITE_BUSY.</p>
 
-<p>The arguments to <b>sqlite_busy_handler()</b> are the opaque
-structure returned from <b>sqlite_open()</b>, a pointer to the busy
+<p>The arguments to <b>sqlite_busy_handler</b> are the opaque
+structure returned from <b>sqlite_open</b>, a pointer to the busy
 callback function, and a generic pointer that will be passed as
 the first argument to the busy callback.  When SQLite invokes the
 busy callback, it sends it three arguments:  the generic pointer
@@ -587,15 +838,15 @@ to access, and the number of times that the library has attempted to
 access the database table or index.</p>
 
 <p>For the common case where we want the busy callback to sleep,
-the SQLite library provides a convenience routine <b>sqlite_busy_timeout()</b>.
-The first argument to <b>sqlite_busy_timeout()</b> is a pointer to
+the SQLite library provides a convenience routine <b>sqlite_busy_timeout</b>.
+The first argument to <b>sqlite_busy_timeout</b> is a pointer to
 an open SQLite database and the second argument is a number of milliseconds.
-After <b>sqlite_busy_timeout()</b> has been executed, the SQLite library
+After <b>sqlite_busy_timeout</b> has been executed, the SQLite library
 will wait for the lock to clear for at least the number of milliseconds 
 specified before it returns SQLITE_BUSY.  Specifying zero milliseconds for
 the timeout restores the default behavior.</p>
 
-<h2>Using the <tt>_printf()</tt> wrapper functions</h2>
+<h3>3.9 Using the <tt>_printf()</tt> wrapper functions</h3>
 
 <p>The four utility functions</p>
 
@@ -608,23 +859,23 @@ the timeout restores the default behavior.</p>
 </ul>
 </p>
 
-<p>implement the same query functionality as <b>sqlite_exec()</b>
-and <b>sqlite_get_table()</b>.  But instead of taking a complete
+<p>implement the same query functionality as <b>sqlite_exec</b>
+and <b>sqlite_get_table</b>.  But instead of taking a complete
 SQL statement as their second argument, the four <b>_printf</b>
 routines take a printf-style format string.  The SQL statement to
 be executed is generated from this format string and from whatever
 additional arguments are attached to the end of the function call.</p>
 
 <p>There are two advantages to using the SQLite printf
-functions instead of <b>sprintf()</b>.  First of all, with the
+functions instead of <b>sprintf</b>.  First of all, with the
 SQLite printf routines, there is never a danger of overflowing a
-static buffer as there is with <b>sprintf()</b>.  The SQLite
+static buffer as there is with <b>sprintf</b>.  The SQLite
 printf routines automatically allocate (and later frees)
 as much memory as is 
 necessary to hold the SQL statements generated.</p>
 
 <p>The second advantage the SQLite printf routines have over
-<b>sprintf()</b> are two new formatting options specifically designed
+<b>sprintf</b> are two new formatting options specifically designed
 to support string literals in SQL.  Within the format string,
 the %q formatting option works very much like %s in that it
 reads a null-terminated string from the argument list and inserts
@@ -717,7 +968,7 @@ by passing it to <b>sqlite_freemem()</b>.
 </p>
 
 <a name="cfunc">
-<h2>Adding New SQL Functions</h2>
+<h2>4.0 Adding New SQL Functions</h2>
 
 <p>Beginning with version 2.4.0, SQLite allows the SQL language to be
 extended with new functions implemented as C code.  The following interface
@@ -800,13 +1051,13 @@ new SQL functions, review the SQLite source code in the file
 <b>func.c</b>.
 </p>
 
-<h2>Multi-Threading And SQLite</h2>
+<h2>5.0 Multi-Threading And SQLite</h2>
 
 <p>
 If SQLite is compiled with the THREADSAFE preprocessor macro set to 1,
 then it is safe to use SQLite from two or more threads of the same process
 at the same time.  But each thread should have its own <b>sqlite*</b>
-pointer returned from <b>sqlite_open()</b>.  It is never safe for two
+pointer returned from <b>sqlite_open</b>.  It is never safe for two
 or more threads to access the same <b>sqlite*</b> pointer at the same time.
 </p>
 
@@ -823,7 +1074,7 @@ Under Unix, an <b>sqlite*</b> pointer should not be carried across a
 should open its own copy of the database after the <b>fork()</b>.
 </p>
 
-<h2>Usage Examples</h2>
+<h2>6.0 Usage Examples</h2>
 
 <p>For examples of how the SQLite C/C++ interface can be used,
 refer to the source code for the <b>sqlite</b> program in the
index 5cea5f381e10a96725b21e823a4f9f0593737675..113c42dc253474dfdf7bea7a85559324aa311e25 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: lang.tcl,v 1.48 2003/01/26 15:28:18 jplyon Exp $}
+set rcsid {$Id: lang.tcl,v 1.49 2003/01/29 22:58:27 drh Exp $}
 
 puts {<html>
 <head>
@@ -1103,6 +1103,7 @@ with caution.</p>
     <b>synchronous</b> pragma does the same thing but only applies the setting
     to the current session.</p>
 
+<a name="pragma_empty_result_callbacks">
 <li><p><b>PRAGMA empty_result_callbacks = ON;
        <br>PRAGMA empty_result_callbacks = OFF;</b></p>
     <p>When on, the EMPTY_RESULT_CALLBACKS pragma causes the callback
@@ -1145,14 +1146,17 @@ with caution.</p>
     a description of all problems.  If everything is in order, "ok" is
     returned.</p>
 
+<a name="pragma_show_datatypes">
 <li><p><b>PRAGMA show_datatypes = ON;<br>PRAGMA show_datatypes = OFF;</b></p>
     <p>When turned on, the SHOW_DATATYPES pragma causes extra entries containing
     the names of <a href="datatypes.html">datatypes</a> of columns to be
     appended to the 4th ("columnNames") argument to <b>sqlite_exec()</b>
     callbacks.  When
     turned off, the 4th argument to callbacks contains only the column names.
-    SQLite <a href="datatypes.html">datatypes</a> are always either "TEXT"
-    or "NUMERIC".
+    The datatype for table columns is taken from the CREATE TABLE statement
+    that defines the table.  Columns with an unspecified datatype have a
+    datatype of "NUMERIC" and the results of expression have a datatype of
+    either "TEXT" or "NUMERIC" depending on the expression.
     The following chart illustrates the difference for the query
     "SELECT 'xyzzy', 5, NULL AS empty ":</p>