]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the "wordcount.c" test program.
authordrh <drh@noemail.net>
Thu, 7 Nov 2013 18:37:31 +0000 (18:37 +0000)
committerdrh <drh@noemail.net>
Thu, 7 Nov 2013 18:37:31 +0000 (18:37 +0000)
FossilOrigin-Name: f02ee5463084cef45ae412c51211b66de7e86baf

Makefile.in
Makefile.msc
main.mk
manifest
manifest.uuid
test/wordcount.c [new file with mode: 0644]

index f01cae05e7b2dcf3ebcc965eccedb800c4b05f32..deb5019e50b42ba9f71f7908f0da566adddf41bf 100644 (file)
@@ -932,6 +932,12 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TO
 sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
        $(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
 
+showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.c
+       $(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.c $(TLIBS)
+
+wordcount$(TEXE):      $(TOP)/test/wordcount.c sqlite3.c
+       $(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.c $(TLIBS)
+
 # Standard install and cleanup targets
 #
 lib_install:   libsqlite3.la
index b9aeea334b8b02f226a6ca33124e6cdac05f43dc..44428f0f9767656027137f503d6885797c98dc1f 100644 (file)
@@ -1332,6 +1332,14 @@ sqlite3_analyzer.exe:    sqlite3_analyzer.c $(LIBRESOBJS)
        $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
                /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
 
+showdb.exe:    $(TOP)/tool/showdb.c sqlite3.c
+       $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
+               $(TOP)/tool/showdb.c sqlite3.c
+
+wordcount.exe: $(TOP)/test/wordcount.c sqlite3.c
+       $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
+               $(TOP)/test/wordcount.c sqlite3.c
+
 clean:
        del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
        del /Q *.cod *.da *.bb *.bbg gmon.out
diff --git a/main.mk b/main.mk
index 9eb384d9054398778d68bbe40ac279b7879ce065..7571996906efb350b6e68dcb750fdb3727b3430e 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -620,10 +620,14 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
 extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
        ./testfixture$(EXE) $(TOP)/test/loadext.test
 
-showdb:        $(TOP)/tool/showdb.c sqlite3.c
-       $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb \
+showdb$(EXE):  $(TOP)/tool/showdb.c sqlite3.c
+       $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb$(EXE) \
                $(TOP)/tool/showdb.c sqlite3.c
 
+wordcount$(EXE):       $(TOP)/test/wordcount.c sqlite3.c
+       $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
+               $(TOP)/test/wordcount.c sqlite3.c
+
 # This target will fail if the SQLite amalgamation contains any exported
 # symbols that do not begin with "sqlite3_". It is run as part of the
 # releasetest.tcl script.
index fe7f8655f015cab92268f62758399f12ef001ead..2927066f4bc6670a0f92a9e68cace9f5d69123b2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Add\ssupport\sfor\sWITHOUT\sROWID\stables.\s\sThis\schange\salso\sincludes\n(1)\sstandardization\sof\sthe\serror\smessage\sreturned\sfrom\srun-time\sconstraint\nerrors,\s(2)\simproved\sEXPLAIN\scomments,\s(3)\sthe\sSQLITE_ENABLE_EXPLAIN_COMMENTS\noption,\s(4)\sthe\sSQLITE_ENABLE_MODULE_COMMENTS\soption,\sand\s(5)\sa\sbug\sfix\n(see\s[573cc27427])\sin\sthe\shandling\sof\sREPLACE\son\sthe\srowid\swhen\ssecondary\nindices\suse\sFAIL\sor\sIGNORE.
-D 2013-11-07T16:08:10.334
+C Add\sthe\s"wordcount.c"\stest\sprogram.
+D 2013-11-07T18:37:31.917
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
-F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
+F Makefile.in d12e4455cf7a36e42d3949876c1c3b88ff70867a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
-F Makefile.msc ec5d662ed5a15ff819928c0495017af13910d7b6
+F Makefile.msc eaf39e18f37637111c6e39ed35b1da9092c8816f
 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
 F VERSION a8d1f6839521130dc73c5408cdd24bcfd791df34
@@ -141,7 +141,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
-F main.mk c6a433cb334bbb019625c137ab5d5e7568b47cff
+F main.mk fbd5fed974f68cc312e4f73770df0f5221b3b460
 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
@@ -1083,6 +1083,7 @@ F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
 F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
+F test/wordcount.c 77aaf31e8107bc8aa22adea9f7ed9a4525157d8b
 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
 F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd
 F tool/build-all-msvc.bat 1bac6adc3fdb4d9204f21d17b14be25778370e48 x
@@ -1134,8 +1135,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 49be646cd981f8ff0434cf90d2748afa30260017 55eea1782aead6a6aaf93f14d85486f8fd2209ad
-R 1e773dfb806625ad59b6a083881b6fca
-T +closed 55eea1782aead6a6aaf93f14d85486f8fd2209ad
+P c80e229dd9c1230abefbc707d4bf0b24315c6bb5
+R c8deac31b5ce7060977908f205c33403
 U drh
-Z 3c1e4b61d489a4d1c755b624a57fdf8f
+Z e0ecc34e281066dd75e22b62900090ff
index 5f791aebdc4840c943d673769b6ff884058ffad8..a55f9c6910bd68aec2b284b63e40b5bd9790991c 100644 (file)
@@ -1 +1 @@
-c80e229dd9c1230abefbc707d4bf0b24315c6bb5
\ No newline at end of file
+f02ee5463084cef45ae412c51211b66de7e86baf
\ No newline at end of file
diff --git a/test/wordcount.c b/test/wordcount.c
new file mode 100644 (file)
index 0000000..b9f7109
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+** This C program extracts all "words" from an input document and adds them
+** to an SQLite database.  A "word" is any contiguous sequence of alphabetic
+** characters.  All digits, punctuation, and whitespace characters are 
+** word separators.  The database stores a single entry for each distinct
+** word together with a count of the number of occurrences of that word.
+** A fresh database is created automatically on each run.
+**
+**     wordcount DATABASE INPUTFILE
+**
+** The INPUTFILE name can be omitted, in which case input it taken from
+** standard input.
+**
+** Option:
+**
+**     --without-rowid      Use a WITHOUT ROWID table to store the words.
+**     --insert             Use INSERT mode (the default)
+**     --replace            Use REPLACE mode
+**     --select             Use SELECT mode
+**     --update             Use UPDATE mode
+**     --nocase             Add the NOCASE collating sequence to the words.
+**     --trace              Enable sqlite3_trace() output.
+**
+** Modes:
+**
+** Insert mode means:
+**    (1) INSERT OR IGNORE INTO wordcount VALUES($new,1)
+**    (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new -- if (1) is a noop
+**
+** Update mode means:
+**    (1) INSERT OR IGNORE INTO wordcount VALUES($new,0)
+**    (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new
+**
+** Replace mode means:
+**    (1) REPLACE INTO wordcount
+**        VALUES($new,ifnull((SELECT cnt FROM wordcount WHERE word=$new),0)+1);
+**
+** Select mode modes:
+**    (1) SELECT 1 FROM wordcount WHERE word=$newword
+**    (2) INSERT INTO wordcount VALUES($new,1) -- if (1) returns nothing
+**    (3) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new  --if (1) return TRUE
+**
+******************************************************************************
+**
+** Compile as follows:
+**
+**    gcc -I. wordcount.c sqlite3.c -ldl -lpthreads
+**
+** Or:
+**
+**    gcc -I. -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
+**        wordcount.c sqlite3.c
+*/
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "sqlite3.h"
+
+/* Print an error message and exit */
+static void fatal_error(const char *zMsg, ...){
+  va_list ap;
+  va_start(ap, zMsg);
+  vfprintf(stderr, zMsg, ap);
+  va_end(ap);
+  exit(1);
+}
+
+/* The sqlite3_trace() callback function */
+static void traceCallback(void *NotUsed, const char *zSql){
+  printf("%s;\n", zSql);
+}
+
+/* Define operating modes */
+#define MODE_INSERT     0
+#define MODE_REPLACE    1
+#define MODE_SELECT     2
+#define MODE_UPDATE     3
+
+int main(int argc, char **argv){
+  const char *zFileToRead = 0;  /* Input file.  NULL for stdin */
+  const char *zDbName = 0;      /* Name of the database file to create */
+  int useWithoutRowid = 0;      /* True for --without-rowid */
+  int iMode = MODE_INSERT;      /* One of MODE_xxxxx */
+  int useNocase = 0;            /* True for --nocase */
+  int doTrace = 0;              /* True for --trace */
+  int i, j;                     /* Loop counters */
+  sqlite3 *db;                  /* The SQLite database connection */
+  char *zSql;                   /* Constructed SQL statement */
+  sqlite3_stmt *pInsert = 0;    /* The INSERT statement */
+  sqlite3_stmt *pUpdate = 0;    /* The UPDATE statement */
+  sqlite3_stmt *pSelect = 0;    /* The SELECT statement */
+  FILE *in;                     /* The open input file */
+  int rc;                       /* Return code from an SQLite interface */
+  int iCur, iHiwtr;             /* Statistics values, current and "highwater" */
+  char zInput[2000];            /* A single line of input */
+
+  /* Process command-line arguments */
+  for(i=1; i<argc; i++){
+    const char *z = argv[i];
+    if( z[0]=='-' ){
+      do{ z++; }while( z[0]=='-' );
+      if( strcmp(z,"without-rowid")==0 ){
+        useWithoutRowid = 1;
+      }else if( strcmp(z,"replace")==0 ){
+        iMode = MODE_REPLACE;
+      }else if( strcmp(z,"select")==0 ){
+        iMode = MODE_SELECT;
+      }else if( strcmp(z,"insert")==0 ){
+        iMode = MODE_INSERT;
+      }else if( strcmp(z,"update")==0 ){
+        iMode = MODE_UPDATE;
+      }else if( strcmp(z,"nocase")==0 ){
+        useNocase = 1;
+      }else if( strcmp(z,"trace")==0 ){
+        doTrace = 1;
+      }else{
+        fatal_error("unknown option: %s\n", argv[i]);
+      }
+    }else if( zDbName==0 ){
+      zDbName = argv[i];
+    }else if( zFileToRead==0 ){
+      zFileToRead = argv[i];
+    }else{
+      fatal_error("surplus argument: %s\n", argv[i]);
+    }
+  }
+  if( zDbName==0 ){
+    fatal_error("Usage: %s [--options] DATABASE [INPUTFILE]\n", argv[0]);
+  }
+
+  /* Open the database and the input file */
+  if( sqlite3_open(zDbName, &db) ){
+    fatal_error("Cannot open database file: %s\n", zDbName);
+  }
+  if( zFileToRead ){
+    in = fopen(zFileToRead, "rb");
+    if( in==0 ){
+      fatal_error("Could not open input file \"%s\"\n", zFileToRead);
+    }
+  }else{
+    in = stdin;
+  }
+
+  /* Construct the "wordcount" table into which to put the words */
+  if( doTrace ) sqlite3_trace(db, traceCallback, 0);
+  if( sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0) ){
+    fatal_error("Could not start a transaction\n");
+  }
+  zSql = sqlite3_mprintf(
+     "CREATE TABLE wordcount(\n"
+     "  word TEXT PRIMARY KEY COLLATE %s,\n"
+     "  cnt INTEGER\n"
+     ")%s",
+     useNocase ? "nocase" : "binary",
+     useWithoutRowid ? " WITHOUT ROWID" : ""
+  );
+  if( zSql==0 ) fatal_error("out of memory\n");
+  rc = sqlite3_exec(db, zSql, 0, 0, 0);
+  if( rc ) fatal_error("Could not create the wordcount table: %s.\n",
+                       sqlite3_errmsg(db));
+  sqlite3_free(zSql);
+
+  /* Prepare SQL statements that will be needed */
+  if( iMode==MODE_SELECT ){
+    rc = sqlite3_prepare_v2(db,
+          "SELECT 1 FROM wordcount WHERE word=?1",
+          -1, &pSelect, 0);
+    if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
+                          sqlite3_errmsg(db));
+    rc = sqlite3_prepare_v2(db,
+          "INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
+          -1, &pInsert, 0);
+    if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
+                         sqlite3_errmsg(db));
+  }
+  if( iMode==MODE_SELECT || iMode==MODE_UPDATE || iMode==MODE_INSERT ){
+    rc = sqlite3_prepare_v2(db,
+          "UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
+          -1, &pUpdate, 0);
+    if( rc ) fatal_error("Could not prepare the UPDATE statement: %s\n",
+                         sqlite3_errmsg(db));
+  }
+  if( iMode==MODE_INSERT ){
+    rc = sqlite3_prepare_v2(db,
+          "INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
+          -1, &pInsert, 0);
+    if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
+                         sqlite3_errmsg(db));
+  }
+  if( iMode==MODE_UPDATE ){
+    rc = sqlite3_prepare_v2(db,
+          "INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
+          -1, &pInsert, 0);
+    if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
+                         sqlite3_errmsg(db));
+  }
+  if( iMode==MODE_REPLACE ){
+    rc = sqlite3_prepare_v2(db,
+          "REPLACE INTO wordcount(word,cnt)"
+          "VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)",
+          -1, &pInsert, 0);
+    if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n",
+                          sqlite3_errmsg(db));
+  }
+
+  /* Process the input file */
+  while( fgets(zInput, sizeof(zInput), in) ){
+    for(i=0; zInput[i]; i++){
+      if( !isalpha(zInput[i]) ) continue;
+      for(j=i+1; isalpha(zInput[j]); j++){}
+
+      /* Found a new word at zInput[i] that is j-i bytes long. 
+      ** Process it into the wordcount table.  */
+      if( iMode==MODE_SELECT ){
+        sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
+        rc = sqlite3_step(pSelect);
+        sqlite3_reset(pSelect);
+        if( rc==SQLITE_ROW ){
+          sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
+          if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
+            fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
+          }
+          sqlite3_reset(pUpdate);
+        }else if( rc==SQLITE_DONE ){
+          sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
+          if( sqlite3_step(pInsert)!=SQLITE_DONE ){
+            fatal_error("Insert failed: %s\n", sqlite3_errmsg(db));
+          }
+          sqlite3_reset(pInsert);
+        }else{
+          fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db));
+        }
+      }else{
+        sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
+        if( sqlite3_step(pInsert)!=SQLITE_DONE ){
+          fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db));
+        }
+        sqlite3_reset(pInsert);
+        if( iMode==MODE_UPDATE
+         || (iMode==MODE_INSERT && sqlite3_changes(db)==0)
+        ){
+          sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
+          if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
+            fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
+          }
+          sqlite3_reset(pUpdate);
+        }
+      }
+      i = j-1;
+    }
+  }
+  sqlite3_exec(db, "COMMIT", 0, 0, 0);
+  if( zFileToRead ) fclose(in);
+  sqlite3_finalize(pInsert);
+  sqlite3_finalize(pUpdate);
+  sqlite3_finalize(pSelect);
+
+  /* Database connection statistics printed after both prepared statements
+  ** have been finalized */
+  sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, 0);
+  printf("-- Lookaside Slots Used:        %d (max %d)\n", iCur,iHiwtr);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, 0);
+  printf("-- Successful lookasides:       %d\n", iHiwtr);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, 0);
+  printf("-- Lookaside size faults:       %d\n", iHiwtr);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, 0);
+  printf("-- Lookaside OOM faults:        %d\n", iHiwtr);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, 0);
+  printf("-- Pager Heap Usage:            %d bytes\n", iCur);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
+  printf("-- Page cache hits:             %d\n", iCur);
+  sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
+  printf("-- Page cache misses:           %d\n", iCur); 
+  sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
+  printf("-- Page cache writes:           %d\n", iCur); 
+  sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, 0);
+  printf("-- Schema Heap Usage:           %d bytes\n", iCur); 
+  sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, 0);
+  printf("-- Statement Heap Usage:        %d bytes\n", iCur); 
+
+  sqlite3_close(db);
+
+  /* Global memory usage statistics printed after the database connection
+  ** has closed.  Memory usage should be zero at this point. */
+  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, 0);
+  printf("-- Memory Used (bytes):         %d (max %d)\n", iCur,iHiwtr);
+  sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, 0);
+  printf("-- Outstanding Allocations:     %d (max %d)\n", iCur,iHiwtr);
+  sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, 0);
+  printf("-- Pcache Overflow Bytes:       %d (max %d)\n", iCur,iHiwtr);
+  sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, 0);
+  printf("-- Scratch Overflow Bytes:      %d (max %d)\n", iCur,iHiwtr);
+  sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, 0);
+  printf("-- Largest Allocation:          %d bytes\n",iHiwtr);
+  sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, 0);
+  printf("-- Largest Pcache Allocation:   %d bytes\n",iHiwtr);
+  sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, 0);
+  printf("-- Largest Scratch Allocation:  %d bytes\n", iHiwtr);
+
+  return 0;
+}