2 ** This C program extracts all "words" from an input document and adds them
3 ** to an SQLite database. A "word" is any contiguous sequence of alphabetic
4 ** characters. All digits, punctuation, and whitespace characters are
5 ** word separators. The database stores a single entry for each distinct
6 ** word together with a count of the number of occurrences of that word.
7 ** A fresh database is created automatically on each run.
9 ** wordcount DATABASE INPUTFILE
11 ** The INPUTFILE name can be omitted, in which case input it taken from
20 ** (1) INSERT OR IGNORE INTO wordcount VALUES($new,1)
21 ** (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new -- if (1) is a noop
24 ** (1) INSERT OR IGNORE INTO wordcount VALUES($new,0)
25 ** (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new
27 ** Replace mode means:
28 ** (1) REPLACE INTO wordcount
29 ** VALUES($new,ifnull((SELECT cnt FROM wordcount WHERE word=$new),0)+1);
32 ** (1) INSERT INTO wordcount VALUES($new,1)
33 ** ON CONFLICT(word) DO UPDATE SET cnt=cnt+1
36 ** (1) SELECT 1 FROM wordcount WHERE word=$new
37 ** (2) INSERT INTO wordcount VALUES($new,1) -- if (1) returns nothing
38 ** (3) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new --if (1) return TRUE
41 ** (1) DELETE FROM wordcount WHERE word=$new
44 ** (1) SELECT cnt FROM wordcount WHERE word=$new
46 ** Note that delete mode and query mode are only useful for preexisting
47 ** databases. The wordcount table is created using IF NOT EXISTS so this
48 ** utility can be run multiple times on the same database file. The
49 ** --without-rowid, --nocase, and --pagesize parameters are only effective
50 ** when creating a new database and are harmless no-ops on preexisting
53 ******************************************************************************
55 ** Compile as follows:
57 ** gcc -I. wordcount.c sqlite3.c -ldl -lpthreads
61 ** gcc -I. -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
62 ** wordcount.c sqlite3.c
75 #define ISALPHA(X) isalpha((unsigned char)(X))
78 "Usage: wordcount [OPTIONS] DATABASE [INPUT]\n"
79 " --all Repeat the test for all test modes\n"
80 " --cachesize NNN Use a cache size of NNN\n"
81 " --commit NNN Commit after every NNN operations\n"
82 " --delete Use DELETE mode\n"
83 " --insert Use INSERT mode (the default)\n"
84 " --journal MMMM Use PRAGMA journal_mode=MMMM\n"
85 " --nocase Add the NOCASE collating sequence to the words.\n"
86 " --nosync Use PRAGMA synchronous=OFF\n"
87 " --pagesize NNN Use a page size of NNN\n"
88 " --query Use QUERY mode\n"
89 " --replace Use REPLACE mode\n"
90 " --select Use SELECT mode\n"
91 " --stats Show sqlite3_status() results at the end.\n"
92 " --summary Show summary information on the collected data.\n"
93 " --tag NAME Tag all output using NAME. Use only stdout.\n"
94 " --timer Time the operation of this program\n"
95 " --trace Enable sqlite3_trace() output.\n"
96 " --update Use UPDATE mode\n"
97 " --upsert Use UPSERT mode\n"
98 " --without-rowid Use a WITHOUT ROWID table to store the words.\n"
104 /* Return the current wall-clock time */
105 static sqlite3_int64
realTime(void){
106 static sqlite3_vfs
*clockVfs
= 0;
108 if( clockVfs
==0 ) clockVfs
= sqlite3_vfs_find(0);
109 if( clockVfs
->iVersion
>=1 && clockVfs
->xCurrentTimeInt64
!=0 ){
110 clockVfs
->xCurrentTimeInt64(clockVfs
, &t
);
113 clockVfs
->xCurrentTime(clockVfs
, &r
);
114 t
= (sqlite3_int64
)(r
*86400000.0);
119 /* Print an error message and exit */
120 static void fatal_error(const char *zMsg
, ...){
123 vfprintf(stderr
, zMsg
, ap
);
128 /* Print a usage message and quit */
129 static void usage(void){
134 /* The sqlite3_trace() callback function */
135 static void traceCallback(void *NotUsed
, const char *zSql
){
136 printf("%s;\n", zSql
);
139 /* An sqlite3_exec() callback that prints results on standard output,
140 ** each column separated by a single space. */
141 static int printResult(void *NotUsed
, int nArg
, char **azArg
, char **azNm
){
144 for(i
=0; i
<nArg
; i
++){
145 printf(" %s", azArg
[i
] ? azArg
[i
] : "(null)");
153 ** Add one character to a hash
155 static void addCharToHash(unsigned int *a
, unsigned char x
){
157 a
[1] = (a
[1]<<8) | x
;
160 a
[2] = (a
[2]<<8) | x
;
165 a
[0] = a
[1] = a
[2] = 0;
171 ** Compute the final hash value.
173 static void finalHash(unsigned int *a
, char *z
){
174 a
[3] += a
[1] + a
[4] + a
[0];
176 sqlite3_snprintf(17, z
, "%08x%08x", a
[3], a
[4]);
181 ** Implementation of a checksum() aggregate SQL function
183 static void checksumStep(
184 sqlite3_context
*context
,
188 const unsigned char *zVal
;
191 a
= (unsigned*)sqlite3_aggregate_context(context
, sizeof(unsigned int)*5);
194 for(i
=0; i
<argc
; i
++){
195 nVal
= sqlite3_value_bytes(argv
[i
]);
196 zVal
= (const unsigned char*)sqlite3_value_text(argv
[i
]);
197 if( zVal
) for(j
=0; j
<nVal
; j
++) addCharToHash(a
, zVal
[j
]);
198 addCharToHash(a
, '|');
200 addCharToHash(a
, '\n');
203 static void checksumFinalize(sqlite3_context
*context
){
206 a
= sqlite3_aggregate_context(context
, 0);
208 finalHash(a
, zResult
);
209 sqlite3_result_text(context
, zResult
, -1, SQLITE_TRANSIENT
);
213 /* Define operating modes */
214 #define MODE_INSERT 0
215 #define MODE_REPLACE 1
216 #define MODE_UPSERT 2
217 #define MODE_SELECT 3
218 #define MODE_UPDATE 4
219 #define MODE_DELETE 5
222 #define MODE_ALL (-1)
225 static const char *azMode
[] = {
236 ** Determine if another iteration of the test is required. Return true
237 ** if so. Return zero if all iterations have finished.
240 int iMode
, /* The selected test mode */
241 int *piLoopCnt
, /* Iteration loop counter */
242 int *piMode2
, /* The test mode to use on the next iteration */
243 int *pUseWithoutRowid
/* Whether or not to use --without-rowid */
246 if( iMode
!=MODE_ALL
){
247 if( *piLoopCnt
) return 0;
252 if( (*piLoopCnt
)>=MODE_COUNT
*2 ) return 0;
254 *pUseWithoutRowid
= i
&1;
259 int main(int argc
, char **argv
){
260 const char *zFileToRead
= 0; /* Input file. NULL for stdin */
261 const char *zDbName
= 0; /* Name of the database file to create */
262 int useWithoutRowid
= 0; /* True for --without-rowid */
263 int iMode
= MODE_INSERT
; /* One of MODE_xxxxx */
264 int iMode2
; /* Mode to use for current --all iteration */
265 int iLoopCnt
= 0; /* Which iteration when running --all */
266 int useNocase
= 0; /* True for --nocase */
267 int doTrace
= 0; /* True for --trace */
268 int showStats
= 0; /* True for --stats */
269 int showSummary
= 0; /* True for --summary */
270 int showTimer
= 0; /* True for --timer */
271 int cacheSize
= 0; /* Desired cache size. 0 means default */
272 int pageSize
= 0; /* Desired page size. 0 means default */
273 int commitInterval
= 0; /* How often to commit. 0 means never */
274 int noSync
= 0; /* True for --nosync */
275 const char *zJMode
= 0; /* Journal mode */
276 int nOp
= 0; /* Operation counter */
277 int i
, j
; /* Loop counters */
278 sqlite3
*db
; /* The SQLite database connection */
279 char *zSql
; /* Constructed SQL statement */
280 sqlite3_stmt
*pInsert
= 0; /* The INSERT statement */
281 sqlite3_stmt
*pUpdate
= 0; /* The UPDATE statement */
282 sqlite3_stmt
*pSelect
= 0; /* The SELECT statement */
283 sqlite3_stmt
*pDelete
= 0; /* The DELETE statement */
284 FILE *in
; /* The open input file */
285 int rc
; /* Return code from an SQLite interface */
286 int iCur
, iHiwtr
; /* Statistics values, current and "highwater" */
287 FILE *pTimer
= stderr
; /* Output channel for the timer */
288 sqlite3_int64 sumCnt
= 0; /* Sum in QUERY mode */
289 sqlite3_int64 startTime
; /* Time of start */
290 sqlite3_int64 totalTime
= 0; /* Total time */
291 char zInput
[2000]; /* A single line of input */
293 /* Process command-line arguments */
294 for(i
=1; i
<argc
; i
++){
295 const char *z
= argv
[i
];
297 do{ z
++; }while( z
[0]=='-' );
298 if( strcmp(z
,"without-rowid")==0 ){
300 }else if( strcmp(z
,"replace")==0 ){
301 iMode
= MODE_REPLACE
;
302 }else if( strcmp(z
,"upsert")==0 ){
304 }else if( strcmp(z
,"select")==0 ){
306 }else if( strcmp(z
,"insert")==0 ){
308 }else if( strcmp(z
,"update")==0 ){
310 }else if( strcmp(z
,"delete")==0 ){
312 }else if( strcmp(z
,"query")==0 ){
314 }else if( strcmp(z
,"all")==0 ){
317 }else if( strcmp(z
,"nocase")==0 ){
319 }else if( strcmp(z
,"trace")==0 ){
321 }else if( strcmp(z
,"nosync")==0 ){
323 }else if( strcmp(z
,"stats")==0 ){
325 }else if( strcmp(z
,"summary")==0 ){
327 }else if( strcmp(z
,"timer")==0 ){
329 }else if( strcmp(z
,"cachesize")==0 && i
<argc
-1 ){
331 cacheSize
= atoi(argv
[i
]);
332 }else if( strcmp(z
,"pagesize")==0 && i
<argc
-1 ){
334 pageSize
= atoi(argv
[i
]);
335 }else if( strcmp(z
,"commit")==0 && i
<argc
-1 ){
337 commitInterval
= atoi(argv
[i
]);
338 }else if( strcmp(z
,"journal")==0 && i
<argc
-1 ){
340 }else if( strcmp(z
,"tag")==0 && i
<argc
-1 ){
343 }else if( strcmp(z
, "help")==0 || strcmp(z
,"?")==0 ){
346 fatal_error("unknown option: \"%s\"\n"
347 "Use --help for a list of options\n",
350 }else if( zDbName
==0 ){
352 }else if( zFileToRead
==0 ){
353 zFileToRead
= argv
[i
];
355 fatal_error("surplus argument: \"%s\"\n", argv
[i
]);
361 startTime
= realTime();
363 /* Open the database and the input file */
364 if( zDbName
[0] && strcmp(zDbName
,":memory:")!=0 ){
367 if( sqlite3_open(zDbName
, &db
) ){
368 fatal_error("Cannot open database file: %s\n", zDbName
);
371 in
= fopen(zFileToRead
, "rb");
373 fatal_error("Could not open input file \"%s\"\n", zFileToRead
);
376 if( iMode
==MODE_ALL
){
377 fatal_error("The --all mode cannot be used with stdin\n");
382 /* Set database connection options */
383 if( doTrace
) sqlite3_trace(db
, traceCallback
, 0);
385 zSql
= sqlite3_mprintf("PRAGMA page_size=%d", pageSize
);
386 sqlite3_exec(db
, zSql
, 0, 0, 0);
390 zSql
= sqlite3_mprintf("PRAGMA cache_size=%d", cacheSize
);
391 sqlite3_exec(db
, zSql
, 0, 0, 0);
394 if( noSync
) sqlite3_exec(db
, "PRAGMA synchronous=OFF", 0, 0, 0);
396 zSql
= sqlite3_mprintf("PRAGMA journal_mode=%s", zJMode
);
397 sqlite3_exec(db
, zSql
, 0, 0, 0);
402 while( allLoop(iMode
, &iLoopCnt
, &iMode2
, &useWithoutRowid
) ){
403 /* Delete prior content in --all mode */
404 if( iMode
==MODE_ALL
){
405 if( sqlite3_exec(db
, "DROP TABLE IF EXISTS wordcount; VACUUM;",0,0,0) ){
406 fatal_error("Could not clean up prior iteration\n");
408 startTime
= realTime();
412 /* Construct the "wordcount" table into which to put the words */
413 if( sqlite3_exec(db
, "BEGIN IMMEDIATE", 0, 0, 0) ){
414 fatal_error("Could not start a transaction\n");
416 zSql
= sqlite3_mprintf(
417 "CREATE TABLE IF NOT EXISTS wordcount(\n"
418 " word TEXT PRIMARY KEY COLLATE %s,\n"
421 useNocase
? "nocase" : "binary",
422 useWithoutRowid
? " WITHOUT ROWID" : ""
424 if( zSql
==0 ) fatal_error("out of memory\n");
425 rc
= sqlite3_exec(db
, zSql
, 0, 0, 0);
426 if( rc
) fatal_error("Could not create the wordcount table: %s.\n",
430 /* Prepare SQL statements that will be needed */
431 if( iMode2
==MODE_QUERY
){
432 rc
= sqlite3_prepare_v2(db
,
433 "SELECT cnt FROM wordcount WHERE word=?1",
435 if( rc
) fatal_error("Could not prepare the SELECT statement: %s\n",
438 if( iMode2
==MODE_SELECT
){
439 rc
= sqlite3_prepare_v2(db
,
440 "SELECT 1 FROM wordcount WHERE word=?1",
442 if( rc
) fatal_error("Could not prepare the SELECT statement: %s\n",
444 rc
= sqlite3_prepare_v2(db
,
445 "INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
447 if( rc
) fatal_error("Could not prepare the INSERT statement: %s\n",
450 if( iMode2
==MODE_SELECT
|| iMode2
==MODE_UPDATE
|| iMode2
==MODE_INSERT
){
451 rc
= sqlite3_prepare_v2(db
,
452 "UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
454 if( rc
) fatal_error("Could not prepare the UPDATE statement: %s\n",
457 if( iMode2
==MODE_INSERT
){
458 rc
= sqlite3_prepare_v2(db
,
459 "INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
461 if( rc
) fatal_error("Could not prepare the INSERT statement: %s\n",
464 if( iMode2
==MODE_UPDATE
){
465 rc
= sqlite3_prepare_v2(db
,
466 "INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
468 if( rc
) fatal_error("Could not prepare the INSERT statement: %s\n",
471 if( iMode2
==MODE_REPLACE
){
472 rc
= sqlite3_prepare_v2(db
,
473 "REPLACE INTO wordcount(word,cnt)"
474 "VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)",
476 if( rc
) fatal_error("Could not prepare the REPLACE statement: %s\n",
479 if( iMode2
==MODE_UPSERT
){
480 rc
= sqlite3_prepare_v2(db
,
481 "INSERT INTO wordcount(word,cnt) VALUES(?1,1) "
482 "ON CONFLICT(word) DO UPDATE SET cnt=cnt+1",
484 if( rc
) fatal_error("Could not prepare the UPSERT statement: %s\n",
487 if( iMode2
==MODE_DELETE
){
488 rc
= sqlite3_prepare_v2(db
,
489 "DELETE FROM wordcount WHERE word=?1",
491 if( rc
) fatal_error("Could not prepare the DELETE statement: %s\n",
495 /* Process the input file */
496 while( fgets(zInput
, sizeof(zInput
), in
) ){
497 for(i
=0; zInput
[i
]; i
++){
498 if( !ISALPHA(zInput
[i
]) ) continue;
499 for(j
=i
+1; ISALPHA(zInput
[j
]); j
++){}
501 /* Found a new word at zInput[i] that is j-i bytes long.
502 ** Process it into the wordcount table. */
503 if( iMode2
==MODE_DELETE
){
504 sqlite3_bind_text(pDelete
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
505 if( sqlite3_step(pDelete
)!=SQLITE_DONE
){
506 fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db
));
508 sqlite3_reset(pDelete
);
509 }else if( iMode2
==MODE_SELECT
){
510 sqlite3_bind_text(pSelect
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
511 rc
= sqlite3_step(pSelect
);
512 sqlite3_reset(pSelect
);
513 if( rc
==SQLITE_ROW
){
514 sqlite3_bind_text(pUpdate
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
515 if( sqlite3_step(pUpdate
)!=SQLITE_DONE
){
516 fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db
));
518 sqlite3_reset(pUpdate
);
519 }else if( rc
==SQLITE_DONE
){
520 sqlite3_bind_text(pInsert
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
521 if( sqlite3_step(pInsert
)!=SQLITE_DONE
){
522 fatal_error("Insert failed: %s\n", sqlite3_errmsg(db
));
524 sqlite3_reset(pInsert
);
526 fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db
));
528 }else if( iMode2
==MODE_QUERY
){
529 sqlite3_bind_text(pSelect
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
530 if( sqlite3_step(pSelect
)==SQLITE_ROW
){
531 sumCnt
+= sqlite3_column_int64(pSelect
, 0);
533 sqlite3_reset(pSelect
);
535 sqlite3_bind_text(pInsert
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
536 if( sqlite3_step(pInsert
)!=SQLITE_DONE
){
537 fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db
));
539 sqlite3_reset(pInsert
);
540 if( iMode2
==MODE_UPDATE
541 || (iMode2
==MODE_INSERT
&& sqlite3_changes(db
)==0)
543 sqlite3_bind_text(pUpdate
, 1, zInput
+i
, j
-i
, SQLITE_STATIC
);
544 if( sqlite3_step(pUpdate
)!=SQLITE_DONE
){
545 fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db
));
547 sqlite3_reset(pUpdate
);
552 /* Increment the operation counter. Do a COMMIT if it is time. */
554 if( commitInterval
>0 && (nOp
%commitInterval
)==0 ){
555 sqlite3_exec(db
, "COMMIT; BEGIN IMMEDIATE", 0, 0, 0);
559 sqlite3_exec(db
, "COMMIT", 0, 0, 0);
560 sqlite3_finalize(pInsert
); pInsert
= 0;
561 sqlite3_finalize(pUpdate
); pUpdate
= 0;
562 sqlite3_finalize(pSelect
); pSelect
= 0;
563 sqlite3_finalize(pDelete
); pDelete
= 0;
565 if( iMode2
==MODE_QUERY
&& iMode
!=MODE_ALL
){
566 printf("%s sum of cnt: %lld\n", zTag
, sumCnt
);
567 rc
= sqlite3_prepare_v2(db
,"SELECT sum(cnt*cnt) FROM wordcount", -1,
569 if( rc
==SQLITE_OK
&& sqlite3_step(pSelect
)==SQLITE_ROW
){
570 printf("%s double-check: %lld\n", zTag
,sqlite3_column_int64(pSelect
,0));
572 sqlite3_finalize(pSelect
);
577 sqlite3_int64 elapseTime
= realTime() - startTime
;
578 totalTime
+= elapseTime
;
579 fprintf(pTimer
, "%3d.%03d wordcount", (int)(elapseTime
/1000),
580 (int)(elapseTime
%1000));
581 if( iMode
==MODE_ALL
){
582 fprintf(pTimer
, " %s%s\n", azMode
[iMode2
],
583 useWithoutRowid
? " --without-rowid" : "");
585 for(i
=1; i
<argc
; i
++) if( i
!=showTimer
) fprintf(pTimer
," %s",argv
[i
]);
586 fprintf(pTimer
, "\n");
591 sqlite3_create_function(db
, "checksum", -1, SQLITE_UTF8
, 0,
592 0, checksumStep
, checksumFinalize
);
594 "SELECT 'count(*): ', count(*) FROM wordcount;\n"
595 "SELECT 'sum(cnt): ', sum(cnt) FROM wordcount;\n"
596 "SELECT 'max(cnt): ', max(cnt) FROM wordcount;\n"
597 "SELECT 'avg(cnt): ', avg(cnt) FROM wordcount;\n"
598 "SELECT 'sum(cnt=1):', sum(cnt=1) FROM wordcount;\n"
599 "SELECT 'top 10: ', group_concat(word, ', ') FROM "
600 "(SELECT word FROM wordcount ORDER BY cnt DESC, word LIMIT 10);\n"
601 "SELECT 'checksum: ', checksum(word, cnt) FROM "
602 "(SELECT word, cnt FROM wordcount ORDER BY word);\n"
603 "PRAGMA integrity_check;\n",
606 } /* End the --all loop */
608 /* Close the input file after the last read */
609 if( zFileToRead
) fclose(in
);
611 /* In --all mode, so the total time */
612 if( iMode
==MODE_ALL
&& showTimer
){
613 fprintf(pTimer
, "%3d.%03d wordcount --all\n", (int)(totalTime
/1000),
614 (int)(totalTime
%1000));
617 /* Database connection statistics printed after both prepared statements
618 ** have been finalized */
620 sqlite3_db_status(db
, SQLITE_DBSTATUS_LOOKASIDE_USED
, &iCur
, &iHiwtr
, 0);
621 printf("%s Lookaside Slots Used: %d (max %d)\n", zTag
, iCur
,iHiwtr
);
622 sqlite3_db_status(db
, SQLITE_DBSTATUS_LOOKASIDE_HIT
, &iCur
, &iHiwtr
, 0);
623 printf("%s Successful lookasides: %d\n", zTag
, iHiwtr
);
624 sqlite3_db_status(db
, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
, &iCur
,&iHiwtr
,0);
625 printf("%s Lookaside size faults: %d\n", zTag
, iHiwtr
);
626 sqlite3_db_status(db
, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
, &iCur
,&iHiwtr
,0);
627 printf("%s Lookaside OOM faults: %d\n", zTag
, iHiwtr
);
628 sqlite3_db_status(db
, SQLITE_DBSTATUS_CACHE_USED
, &iCur
, &iHiwtr
, 0);
629 printf("%s Pager Heap Usage: %d bytes\n", zTag
, iCur
);
630 sqlite3_db_status(db
, SQLITE_DBSTATUS_CACHE_HIT
, &iCur
, &iHiwtr
, 1);
631 printf("%s Page cache hits: %d\n", zTag
, iCur
);
632 sqlite3_db_status(db
, SQLITE_DBSTATUS_CACHE_MISS
, &iCur
, &iHiwtr
, 1);
633 printf("%s Page cache misses: %d\n", zTag
, iCur
);
634 sqlite3_db_status(db
, SQLITE_DBSTATUS_CACHE_WRITE
, &iCur
, &iHiwtr
, 1);
635 printf("%s Page cache writes: %d\n", zTag
, iCur
);
636 sqlite3_db_status(db
, SQLITE_DBSTATUS_SCHEMA_USED
, &iCur
, &iHiwtr
, 0);
637 printf("%s Schema Heap Usage: %d bytes\n", zTag
, iCur
);
638 sqlite3_db_status(db
, SQLITE_DBSTATUS_STMT_USED
, &iCur
, &iHiwtr
, 0);
639 printf("%s Statement Heap Usage: %d bytes\n", zTag
, iCur
);
644 /* Global memory usage statistics printed after the database connection
645 ** has closed. Memory usage should be zero at this point. */
647 sqlite3_status(SQLITE_STATUS_MEMORY_USED
, &iCur
, &iHiwtr
, 0);
648 printf("%s Memory Used (bytes): %d (max %d)\n", zTag
,iCur
,iHiwtr
);
649 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT
, &iCur
, &iHiwtr
, 0);
650 printf("%s Outstanding Allocations: %d (max %d)\n",zTag
,iCur
,iHiwtr
);
651 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW
, &iCur
, &iHiwtr
, 0);
652 printf("%s Pcache Overflow Bytes: %d (max %d)\n",zTag
,iCur
,iHiwtr
);
653 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE
, &iCur
, &iHiwtr
, 0);
654 printf("%s Largest Allocation: %d bytes\n",zTag
,iHiwtr
);
655 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE
, &iCur
, &iHiwtr
, 0);
656 printf("%s Largest Pcache Allocation: %d bytes\n",zTag
,iHiwtr
);