/ Check-in [586acc85]
Login

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

Overview
Comment:Fix typos in comments in test code. (Oops. This check-in also picked up some unrelated changes to documentation.) (CVS 2175)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 586acc85b170f84d6e0dbd2e293da19551242f5a
User & Date: drh 2005-01-03 01:33:00
Context
2005-01-03
02:26
Allow GROUP BY on aggregate queries only. Ticket #1039. (CVS 2176) check-in: 8ef2c644 user: drh tags: trunk
01:33
Fix typos in comments in test code. (Oops. This check-in also picked up some unrelated changes to documentation.) (CVS 2175) check-in: 586acc85 user: drh tags: trunk
01:28
Fix a typo in a comment. No code changes. Ticket #1052. (CVS 2174) check-in: 9fb1402f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to test/all.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.22 2004/08/31 13:45:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {memleak_check}

if {[file exists ./sqlite_test_count]} {
................................................................................
  }
  if {[info exists Leak]} {
    lappend LeakList $Leak
  }
}

# Do one last test to look for a memory leak in the library.  This will
# only work if SQLite is compiled with the -DMEMORY_DEBUG=1 flag.
#
if {$LeakList!=""} {
  puts -nonewline memory-leak-test...
  incr ::nTest
  foreach x $LeakList {
    if {$x!=[lindex $LeakList 0]} {
       puts " failed!"







|







 







|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.23 2005/01/03 01:33:00 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {memleak_check}

if {[file exists ./sqlite_test_count]} {
................................................................................
  }
  if {[info exists Leak]} {
    lappend LeakList $Leak
  }
}

# Do one last test to look for a memory leak in the library.  This will
# only work if SQLite is compiled with the -DSQLITE_DEBUG=1 flag.
#
if {$LeakList!=""} {
  puts -nonewline memory-leak-test...
  incr ::nTest
  foreach x $LeakList {
    if {$x!=[lindex $LeakList 0]} {
       puts " failed!"

Changes to test/malloc.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.11 2004/11/20 19:18:01 drh Exp $

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

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {
   puts "Skipping malloc tests: not compiled with -DMEMORY_DEBUG..."
   finish_test
   return
}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-1.$i {
     sqlite_malloc_fail 0







|




|







|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DSQLITE_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.12 2005/01/03 01:33:00 drh Exp $

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

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {
   puts "Skipping malloc tests: not compiled with -DSQLITE_DEBUG..."
   finish_test
   return
}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-1.$i {
     sqlite_malloc_fail 0

Changes to test/tester.tcl.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.42 2004/11/14 04:04:18 drh Exp $

# Make sure tclsqlite3 was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite3 -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
................................................................................
    if {$nErr>=$maxErr} {puts "*** Giving up..."; finalize_testing}
  } else {
    puts " Ok"
  }
}

# The procedure uses the special "sqlite_malloc_stat" command
# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
# to see how many malloc()s have not been free()ed.  The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
  if {[info command sqlite_malloc_stat]!=""} {







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.43 2005/01/03 01:33:00 drh Exp $

# Make sure tclsqlite3 was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite3 -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
................................................................................
    if {$nErr>=$maxErr} {puts "*** Giving up..."; finalize_testing}
  } else {
    puts " Ok"
  }
}

# The procedure uses the special "sqlite_malloc_stat" command
# (which is only available if SQLite is compiled with -DSQLITE_DEBUG=1)
# to see how many malloc()s have not been free()ed.  The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
  if {[info command sqlite_malloc_stat]!=""} {

Changes to tool/memleak.awk.

1
2
3
4
5
6
7
8
9
10
#
# This script looks for memory leaks by analyzing the output of "sqlite" 
# when compiled with the MEMORY_DEBUG=2 option.
#
/[0-9]+ malloc / {
  mem[$6] = $0
}
/[0-9]+ realloc / {
  mem[$8] = "";
  mem[$10] = $0


|







1
2
3
4
5
6
7
8
9
10
#
# This script looks for memory leaks by analyzing the output of "sqlite" 
# when compiled with the SQLITE_DEBUG=2 option.
#
/[0-9]+ malloc / {
  mem[$6] = $0
}
/[0-9]+ realloc / {
  mem[$8] = "";
  mem[$10] = $0

Changes to www/capi3.tcl.

1
2
3
4
5
6
7
8
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
set rcsid {$Id: capi3.tcl,v 1.6 2004/06/30 13:28:33 danielk1977 Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>

<h3>1.0 Overview</h3>

................................................................................
</p>

<blockquote><pre>
   int sqlite3_step(sqlite3_stmt*);
</pre></blockquote>

<p>
The sqlite3_step() routine return SQLITE3_ROW if it is returning a single
row of the result set, or SQLITE3_DONE if execution has completed, either
normally or due to an error.  It might also return SQLITE3_BUSY if it is
unable to open the database file.  If the return value is SQLITE3_ROW, then
the following routines can be used to extract information about that row
of the result set:
</p>

<blockquote><pre>
   const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
   int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
................................................................................
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   #define SQLITE3_UTF8     1
   #define SQLITE3_UTF16    2
   #define SQLITE3_UTF16BE  3
   #define SQLITE3_UTF16LE  4
   #define SQLITE3_ANY      5
</pre></blockquote>

<p>
The nArg parameter specifies the number of arguments to the function.
A value of 0 indicates that any number of arguments is allowed.  The
eTextRep parameter specifies what representation text values are expected
to be in for arguments to this function.  The value of this parameter should
................................................................................
      void(*)(void*,sqlite3*,int eTextRep,const void*));
</pre></blockquote>

<p>
The sqlite3_create_collation() function specifies a collating sequence name
and a comparison function to implement that collating sequence.  The
comparison function is only used for comparing text values.  The eTextRep
parameter is one of SQLITE3_UTF8, SQLITE3_UTF16LE, SQLITE3_UTF16BE, or
SQLITE3_ANY to specify which text representation the comparison function works
with.  Separate comparison functions can exist for the same collating
sequence for each of the UTF-8, UTF-16LE and UTF-16BE text representations.
The sqlite3_create_collation16() works like sqlite3_create_collation() except
that the collation name is specified in UTF-16 host byte order instead of
in UTF-8.
</p>

|







 







|
|
|
|







 







|
|
|
|
|







 







|
|







1
2
3
4
5
6
7
8
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
set rcsid {$Id: capi3.tcl,v 1.7 2005/01/03 01:33:00 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>

<h3>1.0 Overview</h3>

................................................................................
</p>

<blockquote><pre>
   int sqlite3_step(sqlite3_stmt*);
</pre></blockquote>

<p>
The sqlite3_step() routine return SQLITE_ROW if it is returning a single
row of the result set, or SQLITE_DONE if execution has completed, either
normally or due to an error.  It might also return SQLITE_BUSY if it is
unable to open the database file.  If the return value is SQLITE_ROW, then
the following routines can be used to extract information about that row
of the result set:
</p>

<blockquote><pre>
   const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
   int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
................................................................................
     int nArg,
     int eTextRep,
     void*,
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
     void (*xStep)(sqlite3_context*,int,sqlite3_value**),
     void (*xFinal)(sqlite3_context*)
   );
   #define SQLITE_UTF8     1
   #define SQLITE_UTF16    2
   #define SQLITE_UTF16BE  3
   #define SQLITE_UTF16LE  4
   #define SQLITE_ANY      5
</pre></blockquote>

<p>
The nArg parameter specifies the number of arguments to the function.
A value of 0 indicates that any number of arguments is allowed.  The
eTextRep parameter specifies what representation text values are expected
to be in for arguments to this function.  The value of this parameter should
................................................................................
      void(*)(void*,sqlite3*,int eTextRep,const void*));
</pre></blockquote>

<p>
The sqlite3_create_collation() function specifies a collating sequence name
and a comparison function to implement that collating sequence.  The
comparison function is only used for comparing text values.  The eTextRep
parameter is one of SQLITE_UTF8, SQLITE_UTF16LE, SQLITE_UTF16BE, or
SQLITE_ANY to specify which text representation the comparison function works
with.  Separate comparison functions can exist for the same collating
sequence for each of the UTF-8, UTF-16LE and UTF-16BE text representations.
The sqlite3_create_collation16() works like sqlite3_create_collation() except
that the collation name is specified in UTF-16 host byte order instead of
in UTF-8.
</p>

Changes to www/docs.tcl.

1
2
3
4
5
6
7
8
9
10
11
..
14
15
16
17
18
19
20






21
22
23
24
25
26
27
..
55
56
57
58
59
60
61

62
63
64
65
66
67
68
# This script generates the "docs.html" page that describes various
# sources of documentation available for SQLite.
#
set rcsid {$Id: docs.tcl,v 1.8 2004/11/20 06:05:56 danielk1977 Exp $}
source common.tcl
header {SQLite Documentation}
puts {
<h2>Available Documentation</h2>
<table width="100%" cellpadding="5">
}

................................................................................
  regsub -all { +} $name {\&nbsp;} name
  puts "<a href=\"$url\">$name</a></td>"
  puts {<td width="10"></td>}
  puts {<td align="top" align="left">}
  puts $desc
  puts {</td></tr>}
}







doc {SQLite In 5 Minutes Or Less} {quickstart.html} {
  A very quick introduction to programming with SQLite.
}

doc {SQL Syntax} {lang.html} {
  This document describes the SQL language that is understood by
................................................................................
doc {Locking And Concurrency<br>In SQLite Version 3} {lockingv3.html} {
  A description of how the new locking code in version 3 increases
  concurrancy and decreases the problem of writer starvation.
}

doc {Version 2 DataTypes } {datatypes.html} {
  A description of how SQLite version 2 handles SQL datatypes.

}
doc {Version 3 DataTypes } {datatype3.html} {
  SQLite version 3 introduces the concept of manifest typing, where the
  type of a value is associated with the value itself, not the column that
  it is stored in.
  This page describes data typing for SQLite version 3 in further detail.
}



|







 







>
>
>
>
>
>







 







>







1
2
3
4
5
6
7
8
9
10
11
..
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# This script generates the "docs.html" page that describes various
# sources of documentation available for SQLite.
#
set rcsid {$Id: docs.tcl,v 1.9 2005/01/03 01:33:00 drh Exp $}
source common.tcl
header {SQLite Documentation}
puts {
<h2>Available Documentation</h2>
<table width="100%" cellpadding="5">
}

................................................................................
  regsub -all { +} $name {\&nbsp;} name
  puts "<a href=\"$url\">$name</a></td>"
  puts {<td width="10"></td>}
  puts {<td align="top" align="left">}
  puts $desc
  puts {</td></tr>}
}

doc {Appropriate Uses For SQLite} {whentouse.html} {
  This document describes situations where SQLite is an approriate
  database engine to use versus situations where a client/server
  database engine might be a better choice.
}

doc {SQLite In 5 Minutes Or Less} {quickstart.html} {
  A very quick introduction to programming with SQLite.
}

doc {SQL Syntax} {lang.html} {
  This document describes the SQL language that is understood by
................................................................................
doc {Locking And Concurrency<br>In SQLite Version 3} {lockingv3.html} {
  A description of how the new locking code in version 3 increases
  concurrancy and decreases the problem of writer starvation.
}

doc {Version 2 DataTypes } {datatypes.html} {
  A description of how SQLite version 2 handles SQL datatypes.
  Short summary:  Everything is a string.
}
doc {Version 3 DataTypes } {datatype3.html} {
  SQLite version 3 introduces the concept of manifest typing, where the
  type of a value is associated with the value itself, not the column that
  it is stored in.
  This page describes data typing for SQLite version 3 in further detail.
}

Changes to www/whentouse.tcl.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
..
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

#
# Run this TCL script to generate HTML for the goals.html file.
#
set rcsid {$Id: whentouse.tcl,v 1.2 2004/10/10 17:24:55 drh Exp $}

puts {<html>
<head><title>Appropriate Uses of SQLite</title></head>
<body bgcolor=white>

<h1 align=center>Appropriate Uses Of SQLite</h1>
}
puts "<p align=center>
(This page was last modified on [lrange $rcsid 3 4] UTC)
</p>"

puts {
<p>
SQLite is different from most other SQL database engines in that its
primary design goal is to be simple:
</p>

................................................................................
<li><p><b>Websites</b></p>

<p>SQLite usually will work great as the database engine for low to
medium traffic websites (which is to say, 99.9% of all websites).
The amount of web traffic that SQLite can handle depends, of course,
on how heavily the website uses its database.  Generally
speaking, any site that gets fewer than a 100000 hits/day should work

fine.  The 100000 hits/day figure is a conservative estimate, not a
hard upper bound.
SQLite has been demonstrated to work with 10 times that amount
of traffic.</p>
</li>

<li><p><b>Embedded devices and applications</b></p>

................................................................................

<li><p><b>Application File Format</b></p>

<p>
SQLite has been used with great success as the on-disk file format
for desktop applications such as financial analysis tools, CAD
packages, record keeping programs, and so forth.  The traditional
File/Open operation does an sqlite_open() and executes a
BEGIN TRANSACTION to get exclusive access to the content.  File/Save
does a COMMIT followed by another BEGIN TRANSACTION.  The use
of transactions guarantees that updates to the application file are atomic,
durable, isolated, and consistent.
</p>

<p>
................................................................................
in surprising little code.
</p>
</li>

<li><p><b>Replacement for <i>ad hoc</i> disk files</b></p>

<p>Many programs use fopen(), fread(), and fwrite() to create and
manage files of data in home-grown formats.  SQLite works well as a

replacement for these <i>ad hoc</i> data files.</p>
</li>

<li><p><b>Internal or temporary databases</b></p>

<p>
For programs that have a lot of data that must be sifted and sorted
in diverse ways, it is often easier and quicker to load the data into
an in-memory SQLite database and use query with joins and ORDER BY
clauses to extract the data in the form and order needed rather than
to try to code the same operations manually.
Using an SQL database internally in this way also gives the program
greater flexibility since new columns and indices can be added without
having to recode every query.
</p>
</li>

<li><p><b>Command-line dataset analysis tool</b></p>

<p>
Experienced SQL users can employ
the command-line <b>sqlite</b> program to analyze miscellaneous
datasets. Raw data can be imported using the COPY command, then that
data can be sliced and diced to generate a myriad of summary
reports.  Possible uses include website log analysis, sports
statistics analysis, compilation of programming metrics, and
analysis of experimental results.
</p>

<p>
You can also do the same thing with a enterprise client/server
database, of course.  The advantages to using SQLite in this situation
are that SQLite is much easier to set up and the resulting database 
is a single file that you can store on a floppy disk or email to
a colleague.
</p>
</li>

<li><p><b>Stand-in for an enterprise database during demos or testing</b></p>

<p>
If you are writing a client application for an enterprise database engine,
................................................................................
if any process is reading from any part of the database, all other
processes are prevented from writing any other part of the database.
Similarly, if any one process is writing to any part of the database,
all other processes are prevented from reading any other part of the
database.
For many situations, this is not a problem.  Each application
does its database work quickly and moves on, and no lock lasts for more
than a few dozen milliseconds.  But there are some problems that require
more concurrency, and those problems will need to seek a different
solution.
</p>
</li>

</ul>

}


puts {
<p><hr /></p>
<p>
<a href="index.html"><img src="/goback.jpg" border=0 />
Back to the SQLite home page</a>
</p>

</body></html>}




|
<
<
<
<
>
|
<
<
<
<







 







>
|







 







|







 







|
>








|













|










|
|







 







|
|







<
<
<
<
<
<
<
<
<
<
>
1
2
3
4




5
6




7
8
9
10
11
12
13
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251










252
#
# Run this TCL script to generate HTML for the goals.html file.
#
set rcsid {$Id: whentouse.tcl,v 1.3 2005/01/03 01:33:00 drh Exp $}




source common.tcl
header {Appropriate Uses For SQLite}





puts {
<p>
SQLite is different from most other SQL database engines in that its
primary design goal is to be simple:
</p>

................................................................................
<li><p><b>Websites</b></p>

<p>SQLite usually will work great as the database engine for low to
medium traffic websites (which is to say, 99.9% of all websites).
The amount of web traffic that SQLite can handle depends, of course,
on how heavily the website uses its database.  Generally
speaking, any site that gets fewer than a 100000 hits/day should work
fine with SQLite.
The 100000 hits/day figure is a conservative estimate, not a
hard upper bound.
SQLite has been demonstrated to work with 10 times that amount
of traffic.</p>
</li>

<li><p><b>Embedded devices and applications</b></p>

................................................................................

<li><p><b>Application File Format</b></p>

<p>
SQLite has been used with great success as the on-disk file format
for desktop applications such as financial analysis tools, CAD
packages, record keeping programs, and so forth.  The traditional
File/Open operation does an sqlite3_open() and executes a
BEGIN TRANSACTION to get exclusive access to the content.  File/Save
does a COMMIT followed by another BEGIN TRANSACTION.  The use
of transactions guarantees that updates to the application file are atomic,
durable, isolated, and consistent.
</p>

<p>
................................................................................
in surprising little code.
</p>
</li>

<li><p><b>Replacement for <i>ad hoc</i> disk files</b></p>

<p>Many programs use fopen(), fread(), and fwrite() to create and
manage files of data in home-grown formats.  SQLite works 
particularly well as a
replacement for these <i>ad hoc</i> data files.</p>
</li>

<li><p><b>Internal or temporary databases</b></p>

<p>
For programs that have a lot of data that must be sifted and sorted
in diverse ways, it is often easier and quicker to load the data into
an in-memory SQLite database and use queries with joins and ORDER BY
clauses to extract the data in the form and order needed rather than
to try to code the same operations manually.
Using an SQL database internally in this way also gives the program
greater flexibility since new columns and indices can be added without
having to recode every query.
</p>
</li>

<li><p><b>Command-line dataset analysis tool</b></p>

<p>
Experienced SQL users can employ
the command-line <b>sqlite</b> program to analyze miscellaneous
datasets. Raw data can be imported from CSV files, then that
data can be sliced and diced to generate a myriad of summary
reports.  Possible uses include website log analysis, sports
statistics analysis, compilation of programming metrics, and
analysis of experimental results.
</p>

<p>
You can also do the same thing with a enterprise client/server
database, of course.  The advantages to using SQLite in this situation
are that SQLite is much easier to set up and the resulting database 
is a single file that you can store on a floppy disk or flash-memory stick
or email to a colleague.
</p>
</li>

<li><p><b>Stand-in for an enterprise database during demos or testing</b></p>

<p>
If you are writing a client application for an enterprise database engine,
................................................................................
if any process is reading from any part of the database, all other
processes are prevented from writing any other part of the database.
Similarly, if any one process is writing to any part of the database,
all other processes are prevented from reading any other part of the
database.
For many situations, this is not a problem.  Each application
does its database work quickly and moves on, and no lock lasts for more
than a few dozen milliseconds.  But there are some applications that require
more concurrency, and those applications may need to seek a different
solution.
</p>
</li>

</ul>

}










footer $rcsid