1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Add the "wordcount.c" test program.

FossilOrigin-Name: f02ee5463084cef45ae412c51211b66de7e86baf
This commit is contained in:
drh
2013-11-07 18:37:31 +00:00
parent b0e503409d
commit 9ac3c1ea40
6 changed files with 333 additions and 12 deletions

View 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

View 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

View File

@@ -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.

View File

@@ -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

View File

@@ -1 +1 @@
c80e229dd9c1230abefbc707d4bf0b24315c6bb5
f02ee5463084cef45ae412c51211b66de7e86baf

303
test/wordcount.c Normal file
View File

@@ -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;
}