Additional test cases and documentation updates. (CVS 717)

FossilOrigin-Name: 048b16c111693727482642e2a19a74a91458fc80
This commit is contained in:
drh 2002-08-15 11:48:13 +00:00
parent 3d037a91a5
commit 310ae7be1e
7 changed files with 180 additions and 61 deletions

View File

@ -1,5 +1,5 @@
C Fixes\sand\stest\simprovements\sresulting\sfrom\scode\scoverage\stesting.\s(CVS\s716)
D 2002-08-15T01:26:09
C Additional\stest\scases\sand\sdocumentation\supdates.\s(CVS\s717)
D 2002-08-15T11:48:13
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -77,7 +77,7 @@ F test/lock.test f1b55dc61632e99d241643cc8e7c03774f09f623
F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85
F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd
F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e
F test/misc1.test 064d7fbbe41285a381ce21832fed41ed245a6a2e
F test/misc1.test 834dce8b6db65c4921d59a4d449b87f40442ab87
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd
@ -127,17 +127,17 @@ 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 fb87b825b9032b9aa941694c5c9c5aee9424467e
F www/c_interface.tcl 70548ff5f73c6adcdb7aeced929ebb30a99f5807
F www/changes.tcl df6f06b1aa97ef285c744bf19ec3efddf707b05f
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/datatypes.tcl ac58cd17bd96cbf1dc228dfb965f88e3e8d45c6b
F www/datatypes.tcl a555ff9f5121aab9d7cffcec4c1d8c86ad79c4ee
F www/download.tcl 29aa6679ca29621d10613f60ebbbda18f4b91c49
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/faq.tcl 234cd80a771f63c778b0a86784589f4eaae2b381
F www/faq.tcl 9262ad6f7f25ab253a9771ab1fbd48a1a14f2957
F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e
F www/index.tcl 9af69527a26895ec56ad920d4c51541c3e5643a6
F www/lang.tcl 902f677258ee63dd8f6677b54118f354a1d824b6
F www/lang.tcl a2785964e80627381e953849e227a3ff2a38cb09
F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
F www/omitted.tcl 7a6d6598e6a6a09bf54a02e0aff0f29e407d9f11
F www/opcode.tcl 33c5f2061a05c5d227c72b84c080b3bf74c74f8b
@ -145,7 +145,7 @@ F www/speed.tcl 7fc83f1b018e1ecc451838449542c3079ed12425
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P 07f6020bb56d6d1bffdd936017f61cfae5bd134b
R 9cedd757d76753c6b434284c8a29f442
P 66a0f6a8e25e3eeed78eba4b63b097f921c79d99
R cf9944ebe55162967e3e3ce76c6f7260
U drh
Z 60f9f150ddc50216dbbd17469130080e
Z 8cc0e2bc226abcbf418a7651cce9d7b1

View File

@ -1 +1 @@
66a0f6a8e25e3eeed78eba4b63b097f921c79d99
048b16c111693727482642e2a19a74a91458fc80

View File

@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc1.test,v 1.12 2002/08/13 23:02:58 drh Exp $
# $Id: misc1.test,v 1.13 2002/08/15 11:48:13 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -320,4 +320,47 @@ do_test misc1-11.2 {
lappend rc $msg
} {0 3}
# Make sure string comparisons really do compare strings in format4+.
# Similar tests in the format3.test file show that for format3 and earlier
# all comparisions where numeric if either operand looked like a number.
#
do_test misc1-12.1 {
execsql {SELECT '0'=='0.0'}
} {0}
do_test misc1-12.2 {
execsql {SELECT '0'==0.0}
} {1}
do_test misc1-12.3 {
execsql {SELECT '12345678901234567890'=='12345678901234567891'}
} {0}
do_test misc1-12.4 {
execsql {
CREATE TABLE t6(a INT UNIQUE, b TEXT UNIQUE);
INSERT INTO t6 VALUES('0','0.0');
SELECT * FROM t6;
}
} {0 0.0}
do_test misc1-12.5 {
execsql {
INSERT OR IGNORE INTO t6 VALUES(0.0,'x');
SELECT * FROM t6;
}
} {0 0.0}
do_test misc1-12.6 {
execsql {
INSERT OR IGNORE INTO t6 VALUES('y',0);
SELECT * FROM t6;
}
} {0 0.0 y 0}
do_test misc1-12.7 {
execsql {
CREATE TABLE t7(x INTEGER, y TEXT, z);
INSERT INTO t7 VALUES(0,0,1);
INSERT INTO t7 VALUES(0.0,0,2);
INSERT INTO t7 VALUES(0,0.0,3);
INSERT INTO t7 VALUES(0.0,0.0,4);
SELECT DISTINCT x, y FROM t7 ORDER BY z;
}
} {0 0 0 0.0}
finish_test

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: c_interface.tcl,v 1.33 2002/08/02 10:36:10 drh Exp $}
set rcsid {$Id: c_interface.tcl,v 1.34 2002/08/15 11:48:14 drh Exp $}
puts {<html>
<head>
@ -410,7 +410,7 @@ for the most recent INSERT statement using the
<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
that were later undo by a ROLLBACK or ABORT. But rows that are
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
@ -425,7 +425,7 @@ is necessary, use "<b>DELETE FROM table WHERE 1</b>" instead.</p>
<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 write it into memory obtained from malloc(). This
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>
@ -433,7 +433,7 @@ entire result of a database query with a single function call.</p>
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
beginning of the array that contains the names of each column of the
beginning of the array that contains the name of each column of the
result.</p>
<p>As an example, consider the following query:</p>
@ -619,7 +619,7 @@ additional arguments are attached to the end of the function call.</p>
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
printf routines automatically allocate (and later free)
printf routines automatically allocate (and later frees)
as much memory as is
necessary to hold the SQL statements generated.</p>

View File

@ -1,7 +1,7 @@
#
# Run this script to generated a datatypes.html output file
#
set rcsid {$Id: datatypes.tcl,v 1.2 2002/08/14 03:03:58 drh Exp $}
set rcsid {$Id: datatypes.tcl,v 1.3 2002/08/15 11:48:14 drh Exp $}
puts {<html>
<head>
@ -184,10 +184,70 @@ TEXT
<p>
The search for these strings in the type declaration is case insensitive,
of course. If any of the above strings occur anywhere in the type
declaration, then the datatype of the column is text. Otherwise the
datatype is numeric. Note in particular that the datatype for columns
declaration, then the datatype of the column is text. Notice that
the type "VARCHAR" contains "CHAR" as a substring so it is considered
text.</p>
<p>If none of the strings above occur anywhere in the type declaration,
then the datatype is numeric. Note in particular that the datatype for columns
with an empty type declaration is numeric.
</p>
<h2>5.0 &nbsp; Examples</h2>
<p>
Consider the following two command sequences:
</p>
<blockquote><pre>
CREATE TABLE t1(a INTEGER UNIQUE); CREATE TABLE t2(b TEXT UNIQUE);
INSERT INTO t1 VALUES('0'); INSERT INTO t2 VALUES(0);
INSERT INTO t1 VALUES('0.0'); INSERT INTO t2 VALUES(0.0);
</pre></blockquote>
<p>In the sequence on the left, the second insert will fail. In this case,
the strings '0' and '0.0' are treated as numbers since they are being
inserted into a numeric column but 0==0.0 which violates the uniqueness
constraint. However, the second insert in the right-hand sequence works. In
this case, the constants 0 and 0.0 are treated a strings which means that
they are distinct.</p>
<p>SQLite always converts numbers into double-precision (64-bit) floats
for comparison purposes. This means that a long sequence of digits that
differ only in digits of far to the right will compare equal if they
are in a numeric column but will compare unequal if they are in a text
column. We have:</p>
<blockquote><pre>
INSERT INTO t1 INSERT INTO t2
VALUES('12345678901234567890'); VALUES(12345678901234567890);
INSERT INTO t1 INSERT INTO t2
VALUES('12345678901234567891'); VALUES(12345678901234567891);
</pre></blockquote>
<p>As before, the second insert on the left will fail because the comparison
will convert both strings into floating-point number first and the only
difference in the strings is in the 20-th digit which exceeds the resolution
of a 64-bit float. In contrast, the second insert on the right will work
because in that case, the numbers being inserted are strings and are
compared using memcmp().</p>
<p>
Numeric and text types make a difference for the DISTINCT keyword too:
</p>
<blockquote><pre>
CREATE TABLE t3(a INTEGER); CREATE TABLE t4(b TEXT);
INSERT INTO t3 VALUES('0'); INSERT INTO t4 VALUES(0);
INSERT INTO t3 VALUES('0.0'); INSERT INTO t4 VALUES(0.0);
SELECT DISTINCT * FROM t3; SELECT DISTINCT * FROM t4;
</pre></blockquote>
<p>
The SELECT statement on the left returns a single row since '0' and '0.0'
are treated as numbers and are therefore indistinct. But the SELECT
statement on the right returns two rows since 0 and 0.0 are treated
a strings which are different.</p>
}
puts {

View File

@ -1,7 +1,7 @@
#
# Run this script to generated a faq.html output file
#
set rcsid {$Id: faq.tcl,v 1.16 2002/08/14 12:56:56 drh Exp $}
set rcsid {$Id: faq.tcl,v 1.17 2002/08/15 11:48:14 drh Exp $}
puts {<html>
<head>
@ -79,6 +79,9 @@ faq {
<p>An exception to this rule is a column of type INTEGER PRIMARY KEY.
Such columns must hold an integer. An attempt to put a non-integer
value into an INTEGER PRIMARY KEY column will generate an error.</p>
<p>There is a page on <a href="datatypes.html">datatypes in SQLite</a>
that explains this concept further.</p>
}
faq {
@ -88,65 +91,78 @@ faq {
inserted into any column. You can put arbitrary length strings into
integer columns, floating point numbers in boolean columns, or dates
in character columns. The datatype you assign to a column in the
CREATE TABLE command is (mostly) ignored. Every column is able to hold
CREATE TABLE command does not restrict what data can be put into
that column. Every column is able to hold
an arbitrary length string. (There is one exception: Columns of
type INTEGER PRIMARY KEY may only hold an integer. An error will result
if you try to put anything other than an integer into an
INTEGER PRIMARY KEY column.)</p>
<p>Because SQLite ignores data types, you can omit the data type definition
from columns in CREATE TABLE statements. For example, instead of saying
<blockquote><pre>
CREATE TABLE t1(
f1 int,
f2 varchar(10),
f3 boolean
);
<p>The datatype does effect how values are compared, however. For
columns with a numeric type (such as "integer") any string that looks
like a number is treated as a number for comparison and sorting purposes.
Consider these two command sequences:</p>
<blockquote><pre>
CREATE TABLE t1(a INTEGER UNIQUE); CREATE TABLE t2(b TEXT UNIQUE);
INSERT INTO t1 VALUES('0'); INSERT INTO t2 VALUES(0);
INSERT INTO t1 VALUES('0.0'); INSERT INTO t2 VALUES(0.0);
</pre></blockquote>
You can save yourself a lot of typing and formatting by omitting the
data type declarations, like this:
<blockquote><pre>
CREATE TABLE t1(f1,f2,f3);
</pre></blockquote>
</p>
<p>In the sequence on the left, the second insert will fail. In this case,
the strings '0' and '0.0' are treated as numbers since they are being
inserted into a numeric column and 0==0.0 which violates the uniqueness
constraint. But the second insert in the right-hand sequence works. In
this case, the constants 0 and 0.0 are treated a strings which means that
they are distinct.</p>
<p>There is a page on <a href="datatypes.html">datatypes in SQLite</a>
that explains this concept further.</p>
}
faq {
Why does SQLite think that the expression '0'=='00' is TRUE?
} {
<p>This is a consequence of SQLite being typeless. All data is stored
internally as a null-terminated string. There is no concept of
separate data types for strings and numbers.</p>
<p>As of version 2.7.0, it doesn't.</p>
<p>When doing a comparison, SQLite looks at the string on both sides of
the comparison operator. If both strings look like pure numeric
values (with no extra punctuation or spacing) then the strings are
converted to floating point numbers using <b>atof()</b> and the results
are compared. The results of <b>atof("0")</b> and <b>atof("00")</b>
are both 0.0, so those two strings are considered to be equal.</p>
<p>But if one of the two values being compared is stored in a column that
has a numeric type, the the other value is treated as a number, not a
string and the result succeeds. For example:</p>
<p>If only one string in a comparison is a pure numeric, then that string
is assumed to be less than the other. Of neither string is a pure numeric,
then <b>strcmp()</b> is used for the comparison.</p>
<blockquote><pre>
CREATE TABLE t3(a INTEGER, b TEXT);
INSERT INTO t3 VALUES(0,0);
SELECT count(*) FROM t3 WHERE a=='00';
</pre></blockquote>
<p>The SELECT in the above series of commands returns 1. The "a" column
is numeric so in the WHERE clause the string '00' is converted into a
number for comparison against "a". 0==00 so the test is true. Now
consider a different SELECT:</p>
<blockquote><pre>
SELECT count(*) FROM t3 WHERE b=='00';
</pre></blockquote>
<p>In this case the answer is 0. B is a text column so a text comparison
is done against '00'. '0'!='00' so the WHERE clause returns FALSE and
the count is zero.</p>
<p>There is a page on <a href="datatypes.html">datatypes in SQLite</a>
that explains this concept further.</p>
}
faq {
Why doesn't SQLite allow me to use '0' and '0.0' as the primary
key on two different rows of the same table?
} {
<p>Every row much have a unique primary key.
But SQLite thinks that <b>'0'</b> and <b>'0.0'</b> are the
<p>Your primary key must have a numeric type. Change the datatype of
your primary key to TEXT and it should work.</p>
<p>Every row must have a unique primary key. For a column with a
numeric type, SQLite thinks that <b>'0'</b> and <b>'0.0'</b> are the
same value because they compare equal to one another numerically.
(See the previous question.) Hence the values are not unique.</p>
<p>You can work around this issue in two ways:</p>
<ol>
<li><p>Remove the <b>primary key</b> clause from the CREATE TABLE.</p></li>
<li><p>Prepend a space to the beginning of every value you use for
the primary key. The initial
space will mean that the entries are not pure numerics and hence
will be compared as strings using <b>strcmp()</b>.</p></li>
</ol>
}
faq {

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.42 2002/08/14 00:08:13 drh Exp $}
set rcsid {$Id: lang.tcl,v 1.43 2002/08/15 11:48:14 drh Exp $}
puts {<html>
<head>
@ -283,7 +283,7 @@ for use by the engine.</p>
<p>Each column definition is the name of the column followed by the
datatype for that column, then one or more optional column constraints.
SQLite is <a href="datatypes.html">typeless</a>.
The datatype for the column does not constraint what data may be put
The datatype for the column does not restrict what data may be put
in that column.
All information is stored as null-terminated strings.
The UNIQUE constraint causes an index to be created on the specified