From: drh
Date: Sat, 24 Nov 2001 00:31:46 +0000 (+0000)
Subject: Fix comparison functions so that they are consistent with the order
X-Git-Tag: version-3.6.10~5716
X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a7c73905d0c881368787ebe70816c2e99039587;p=thirdparty%2Fsqlite.git
Fix comparison functions so that they are consistent with the order
of elements in indices. Fix the handling of large integers. (CVS 317)
FossilOrigin-Name: fc2aae04578c305304a45ec6b76d3ab216cc7526
---
diff --git a/Makefile.in b/Makefile.in
index 3840766f80..d43b85453f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -270,6 +270,9 @@ tclsqlite.html: $(TOP)/www/tclsqlite.tcl
speed.html: $(TOP)/www/speed.tcl
tclsh $(TOP)/www/speed.tcl >speed.html
+faq.html: $(TOP)/www/faq.tcl
+ tclsh $(TOP)/www/faq.tcl >faq.html
+
download.html: $(TOP)/www/download.tcl
tclsh $(TOP)/www/download.tcl >download.html
@@ -290,7 +293,8 @@ DOC = \
mingw.html \
tclsqlite.html \
download.html \
- speed.html
+ speed.html \
+ faq.html
doc: $(DOC)
mkdir -p doc
diff --git a/Makefile.template b/Makefile.template
index e9486371dc..ae3cd7c2ad 100644
--- a/Makefile.template
+++ b/Makefile.template
@@ -329,6 +329,9 @@ tclsqlite.html: $(TOP)/www/tclsqlite.tcl
speed.html: $(TOP)/www/speed.tcl
tclsh $(TOP)/www/speed.tcl >speed.html
+faq.html: $(TOP)/www/faq.tcl
+ tclsh $(TOP)/www/faq.tcl >faq.html
+
download.html: $(TOP)/www/download.tcl
tclsh $(TOP)/www/download.tcl >download.html
@@ -349,7 +352,8 @@ DOC = \
mingw.html \
tclsqlite.html \
download.html \
- speed.html
+ speed.html \
+ faq.html
doc: $(DOC)
mkdir -p doc
diff --git a/VERSION b/VERSION
index eca07e4c1a..ac2cdeba01 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2
+2.1.3
diff --git a/manifest b/manifest
index b8ea46634f..2c5187780a 100644
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Version\s2.1.2\s(CVS\s459)
-D 2001-11-23T00:30:00
-F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
-F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a
+C Fix\scomparison\sfunctions\sso\sthat\sthey\sare\sconsistent\swith\sthe\sorder\nof\selements\sin\sindices.\s\sFix\sthe\shandling\sof\slarge\sintegers.\s(CVS\s317)
+D 2001-11-24T00:31:46
+F Makefile.in 352fed589f09dd94347e0bb391d047118ebd6105
+F Makefile.template b6c3d3ba089e97e3a721e967f3151350f36cb42b
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
-F VERSION c5cc20339d1ecb09a252aeef3d5417cd4d802473
+F VERSION e6864ec01e9107b1044207a2556c4e96c3457007
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
@@ -23,7 +23,7 @@ F src/btree.c d40fa46c8c578f1d166f4ea70d7a9d365399e0f3
F src/btree.h 0250a0a577a98cc64ddf1582d50c08b8d2451650
F src/build.c 2e21d425328e7c8bd6ade235e9eef51bf6fa870f
F src/delete.c 5d93a21c1388cfb1359bda01c072f25583a2f4f2
-F src/expr.c 53515a7ba787bf4f0b3f73be30eb86aadb6f1b90
+F src/expr.c 6b25c5bb1e750af2e2217c0134a7aa1fc0b11444
F src/hash.c 6f1a7712ae3aac8351662969aec5693740a2fbf7
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
F src/insert.c 3526be771a01035198bef28d8f370cbcab94f46d
@@ -37,7 +37,7 @@ F src/parse.y 5295f393f41ea89958287e5738e6c12c7cd67482
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
F src/select.c fa1c7144a9ad7ce3f16373b443bc25e764af4be7
-F src/shell.c 18e9f1cac7ec8af763f8fc71dfd81e2edee24008
+F src/shell.c 175f4e942286bcafefc5bd44346deb94394615b1
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 934de9112747ad8d8e7d5fec44876246b24ca5a3
F src/sqliteInt.h 1d812fd1eed0008d31f7e31293f058bb6dbe3f09
@@ -48,21 +48,21 @@ F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
F src/tokenize.c 830e9ef684334070a26583d94770bb869e2727bf
F src/update.c 365f6fafe75f6816a598e76031b0a757d91c003d
-F src/util.c 265cff871a6079b95878c738bc2da3420cca1375
+F src/util.c 13dcd870ee0e424f5427e8178480ca1b1833a706
F src/vdbe.c f1afb7a82016be2cb4cea24cf98dbb5af0ea7214
F src/vdbe.h cd4c8647051a0c22c0e133c375f1cd17bb8b1e06
F src/where.c 05d27a01e53c20b8cd10589b7e789b2a64367988
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
-F test/bigrow.test 1f098f85586d2117bdb3412d27eba45252bc8a6e
+F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/btree.test 6ab4dc5f595905a276ef588fad3c9236dc07a47b
F test/btree2.test 08e9485619265cbaf5d11bd71f357cdc26bb87e0
F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895
F test/copy.test 768e6f1701a07d08090e1ca7f7dcce0a7a72b43e
F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
-F test/expr.test b4171c84b767f7b7e94dbce4824ba8e981a1c72f
+F test/expr.test d350ef5b21cc26599357fb93d15b8a5f7b524769
F test/func.test 9012f7fc5369422c890e93549aa61d762e0c8bb3
F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
-F test/index.test c2c3088648d106a5a612a14cb346998a4ff77bfa
+F test/index.test c8a471243bbf878974b99baf5badd59407237cf3
F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
F test/insert2.test d6901ca931e308fea7fca8c95ebe7dc957cc9fc2
F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
@@ -104,11 +104,12 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb
F www/c_interface.tcl d446234c1d3ed747fcefd30e972a19f2b2fc0e05
-F www/changes.tcl f1a09dfa633183121d7d4255f4cadadc84dc034d
+F www/changes.tcl 0a54872839461f49b7300b36571d342f0ef0d4fb
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/index.tcl fa0ee4b5343fd216ee5db0285501e45484189484
+F www/faq.tcl 55c7fbb5490d045a3e8223e41b51d8b93310b52c
+F www/index.tcl 7e1afccc37548b7107f666105749bfe7d99d267b
F www/lang.tcl f0e953bfeaaba4c33117ec4bca639dd71ba0e13e
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
F www/opcode.tcl 7989ed328316454c7030dcdb60f09ae1e017286d
@@ -116,7 +117,7 @@ F www/speed.tcl 212a91d555384e01873160d6a189f1490c791bc2
F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
F www/vdbe.tcl eb4e1768cffa266cbbb7133488022a7a6cb278d9
-P 8a984667113564f2bac7412165b6ff8b7e3e8f70
-R c4b924c66bb520eb6ed8e5503bdf1605
+P f14835df32b4a16c840b8827f0c17f0e6d526312
+R 4107b50dd67a5b31593969d21ca32f97
U drh
-Z 1a9449aaa1a79f5e52fef176b1356165
+Z 70fea61a18707bc0d908d9bbb2153332
diff --git a/manifest.uuid b/manifest.uuid
index 8837d3cfdd..72d566e314 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-f14835df32b4a16c840b8827f0c17f0e6d526312
\ No newline at end of file
+fc2aae04578c305304a45ec6b76d3ab216cc7526
\ No newline at end of file
diff --git a/src/expr.c b/src/expr.c
index 8e2045bf87..fc7e7f83e8 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.33 2001/11/08 00:45:21 drh Exp $
+** $Id: expr.c,v 1.34 2001/11/24 00:31:46 drh Exp $
*/
#include "sqliteInt.h"
@@ -511,8 +511,8 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
break;
}
case TK_INTEGER: {
- int i = atoi(pExpr->token.z);
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
+ sqliteVdbeAddOp(v, OP_String, 0, 0);
+ sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
break;
}
case TK_FLOAT: {
@@ -576,11 +576,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
}
case TK_UMINUS: {
assert( pExpr->pLeft );
- if( pExpr->pLeft->op==TK_INTEGER ){
- int i = atoi(pExpr->pLeft->token.z);
- sqliteVdbeAddOp(v, OP_Integer, -i, 0);
- break;
- }else if( pExpr->pLeft->op==TK_FLOAT ){
+ if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
Token *p = &pExpr->pLeft->token;
char *z = sqliteMalloc( p->n + 2 );
sprintf(z, "-%.*s", p->n, p->z);
diff --git a/src/shell.c b/src/shell.c
index e9fc698455..4db83d7b77 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
-** $Id: shell.c,v 1.38 2001/11/09 22:41:45 drh Exp $
+** $Id: shell.c,v 1.39 2001/11/24 00:31:46 drh Exp $
*/
#include
#include
@@ -556,9 +556,9 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
p->showHeader = 1;
p->colWidth[0] = 4;
p->colWidth[1] = 12;
- p->colWidth[2] = 5;
- p->colWidth[3] = 5;
- p->colWidth[4] = 40;
+ p->colWidth[2] = 10;
+ p->colWidth[3] = 10;
+ p->colWidth[4] = 35;
}else
if( c=='h' && strncmp(azArg[0], "header", n)==0 && nArg>1 ){
diff --git a/src/util.c b/src/util.c
index ddb7cfa96b..166660a1e1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.32 2001/11/21 02:21:12 drh Exp $
+** $Id: util.c,v 1.33 2001/11/24 00:31:46 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -426,13 +426,18 @@ int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
return N<0 ? 0 : *a - *b;
}
-/* Notes on string comparisions.
+/*
+** The sortStrCmp() function below is used to order elements according
+** to the ORDER BY clause of a SELECT. The sort order is a little different
+** from what one might expect. This note attempts to describe what is
+** going on.
**
** We want the main string comparision function used for sorting to
** sort both numbers and alphanumeric words into the correct sequence.
** The same routine should do both without prior knowledge of which
** type of text the input represents. It should even work for strings
-** which are a mixture of text and numbers.
+** which are a mixture of text and numbers. (It does not work for
+** numeric substrings in exponential notation, however.)
**
** To accomplish this, we keep track of a state number while scanning
** the two strings. The states are as follows:
@@ -525,9 +530,10 @@ static const unsigned char stateMachine[] = {
};
/* This routine does a comparison of two strings. Case is used only
-** if useCase!=0. Numbers compare in numerical order.
+** if useCase!=0. Numeric substrings compare in numerical order for the
+** most part but this routine does not understand exponential notation.
*/
-static int privateStrCmp(const char *atext, const char *btext, int useCase){
+static int sortStrCmp(const char *atext, const char *btext, int useCase){
register unsigned char *a, *b, *map, ca, cb;
int result;
register int cclass = 0;
@@ -599,129 +605,69 @@ static int privateStrCmp(const char *atext, const char *btext, int useCase){
}
/*
-** Do a comparison of pure numerics. If either string is not a pure
-** numeric, then return 0. Otherwise return 1 and set *pResult to be
-** negative, zero or positive if the first string are numerially less than
-** equal to, or greater than the second.
+** Return TRUE if z is a pure numeric string. Return FALSE if the
+** string contains any character which is not part of a number.
+**
+** Am empty string is considered numeric.
*/
-static int privateCompareNum(const char *a, const char *b, int *pResult){
- char *endPtr;
- double rA, rB;
- int isNumA, isNumB;
- if( isdigit(*a) || ((*a=='-' || *a=='+') && isdigit(a[1])) ){
- rA = strtod(a, &endPtr);
- isNumA = *endPtr==0;
- }else{
- isNumA = 0;
+static int isNum(const char *z){
+ if( *z=='-' || *z=='+' ) z++;
+ if( !isdigit(*z) ){
+ return *z==0;
}
- if( isdigit(*b) || ((*b=='-' || *b=='+') && isdigit(b[1])) ){
- rB = strtod(b, &endPtr);
- isNumB = *endPtr==0;
- }else{
- isNumB = 0;
- }
- if( isNumB==0 && isNumA==0 ) return 0;
- if( isNumA!=isNumB ){
- *pResult = isNumA - isNumB;
- }else if( rArB ){
- *pResult = 1;
- }else{
- *pResult = 0;
+ z++;
+ while( isdigit(*z) ){ z++; }
+ if( *z=='.' ){
+ z++;
+ if( !isdigit(*z) ) return 0;
+ while( isdigit(*z) ){ z++; }
+ if( *z=='e' || *z=='E' ){
+ z++;
+ if( *z=='+' || *z=='-' ) z++;
+ if( !isdigit(*z) ) return 0;
+ while( isdigit(*z) ){ z++; }
+ }
}
- return 1;
+ return *z==0;
}
/* This comparison routine is what we use for comparison operations
-** in an SQL expression. (Ex: name<'Hello' or value<5). Compare two
-** strings. Use case only as a tie-breaker. Numbers compare in
-** numerical order.
+** in an SQL expression. (Ex: name<'Hello' or value<5).
+**
+** Numerical strings compare in numerical order. Numerical strings
+** are always less than non-numeric strings. Non-numeric strings
+** compare in lexigraphical order (the same order as strcmp()).
+**
+** This is NOT the comparison function used for sorting. The sort
+** order is a little bit different. See sqliteSortCompare below
+** for additional information.
*/
int sqliteCompare(const char *atext, const char *btext){
int result;
- if( !privateCompareNum(atext, btext, &result) || result==0 ){
- result = privateStrCmp(atext, btext, 0);
- if( result==0 ) result = privateStrCmp(atext, btext, 1);
- }
- return result;
-}
-
-/*
-** If you compile just this one file with the -DTEST_COMPARE=1 option,
-** it generates a program to test the comparisons routines.
-*/
-#ifdef TEST_COMPARE
-#include
-#include
-int sortCmp(const char **a, const char **b){
- return sqliteCompare(*a, *b);
-}
-int main(int argc, char **argv){
- int i, j, k, n, cnt;
- static char *azStr[] = {
- "abc", "aBc", "abcd", "aBcd",
- "123", "124", "1234", "-123", "-124", "-1234", "+124",
- "123.45", "123.456", "123.46", "-123.45", "-123.46", "-123.456",
- "x9", "x10", "x-9", "x-10", "X9", "X10",
- "1.234e+02", "+123", "1.23E2", "1.2345e+2", "-1.2345e2", "+w"
- };
- n = sizeof(azStr)/sizeof(azStr[0]);
- qsort(azStr, n, sizeof(azStr[0]), sortCmp);
- for(i=0; i0;
- }else{
- success = (x2>=0 && x3>=0) || x2<0;
- }
- if( !success ){
- printf("Failed! \"%s\" vs \"%s\" vs \"%s\"\n", a, b, c);
- i = j = k = n+1;
- }
- cnt++;
+ int isNumA = isNum(atext);
+ int isNumB = isNum(btext);
+ if( isNumA ){
+ if( !isNumB ){
+ result = -1;
+ }else{
+ double rA, rB;
+ rA = atof(atext);
+ rB = atof(btext);
+ if( rArB ){
+ result = +1;
+ }else{
+ result = 0;
}
}
+ }else if( isNumB ){
+ result = +1;
+ }else {
+ result = strcmp(atext, btext);
}
- if( i", and ">=" operators
+** of expressions. The operators compare non-numeric strings in
+** lexigraphical order. This routine does the additional processing
+** to sort substrings of digits into numerical order and to use case
+** only as a tie-breaker.
*/
int sqliteSortCompare(const char *a, const char *b){
int len;
int res = 0;
+ int isNumA, isNumB;
while( res==0 && *a && *b ){
- res = sqliteCompare(&a[1], &b[1]);
- if( res==0 ){
- len = strlen(a) + 1;
- a += len;
- b += len;
+ isNumA = isNum(&a[1]);
+ isNumB = isNum(&b[1]);
+ if( isNumA ){
+ double rA, rB;
+ if( !isNumB ){
+ res = -1;
+ break;
+ }
+ rA = atof(&a[1]);
+ rB = atof(&b[1]);
+ if( rArB ){
+ res = +1;
+ break;
+ }
+ }else if( isNumB ){
+ res = +1;
+ break;
+ }else{
+ res = sortStrCmp(&a[1],&b[1],0);
+ if( res==0 ){
+ res = sortStrCmp(&a[1],&b[1],1);
+ }
+ if( res!=0 ){
+ break;
+ }
}
+ len = strlen(&a[1]) + 2;
+ a += len;
+ b += len;
}
if( *a=='-' ) res = -res;
return res;
}
/*
-** Some powers of 64. These numbers and their recipricals should
-** all have exact representations in the floating point format.
+** Some powers of 64. These constants are needed in the
+** sqliteRealToSortable() routine below.
*/
#define _64e3 (64.0 * 64.0 * 64.0)
#define _64e4 (64.0 * 64.0 * 64.0 * 64.0)
diff --git a/test/bigrow.test b/test/bigrow.test
index ce1150c44b..7a7d9ccaeb 100644
--- a/test/bigrow.test
+++ b/test/bigrow.test
@@ -12,7 +12,7 @@
# focus of this file is stressing the library by putting large amounts
# of data in a single row of a table.
#
-# $Id: bigrow.test,v 1.3 2001/11/12 13:10:53 drh Exp $
+# $Id: bigrow.test,v 1.4 2001/11/24 00:31:47 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -90,7 +90,7 @@ do_test bigrow-1.8 {
} {abc}
do_test bigrow-1.9 {
execsql "SELECT b FROM t1 WHERE a!='$::big1' ORDER BY a"
-} {B 2}
+} {2 B}
# Try doing some indexing on big columns
#
diff --git a/test/expr.test b/test/expr.test
index c275e4a4d9..23c92fa103 100644
--- a/test/expr.test
+++ b/test/expr.test
@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing expressions.
#
-# $Id: expr.test,v 1.16 2001/10/13 02:59:09 drh Exp $
+# $Id: expr.test,v 1.17 2001/11/24 00:31:47 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -73,6 +73,15 @@ test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0}
test_expr expr-1.44 {i1=1} {~i1} {-2}
test_expr expr-1.45 {i1=1, i2=3} {i1<>i2} {4}
+test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1i2} 1
+test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1i2} 1
+test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1i2} 0
test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
@@ -123,9 +132,11 @@ test_expr expr-3.22 {t1='abc', t2='xyz'} {t1!=t2} 1
test_expr expr-3.23 {t1='xyz', t2='abc'} {t1!=t2} 1
test_expr expr-3.24 {t1='abc', t2='abc'} {t1!=t2} 0
test_expr expr-3.25 {t1=NULL, t2='hi'} {t1 isnull} 1
+test_expr expr-3.25b {t1=NULL, t2='hi'} {t1 is null} 1
test_expr expr-3.26 {t1=NULL, t2='hi'} {t2 isnull} 0
test_expr expr-3.27 {t1=NULL, t2='hi'} {t1 notnull} 0
test_expr expr-3.28 {t1=NULL, t2='hi'} {t2 notnull} 1
+test_expr expr-3.28b {t1=NULL, t2='hi'} {t2 is not null} 1
test_expr expr-3.29 {t1='xyz', t2='abc'} {t1||t2} {xyzabc}
test_expr expr-3.30 {t1=NULL, t2='abc'} {t1||t2} {abc}
test_expr expr-3.31 {t1='xyz', t2=NULL} {t1||t2} {xyz}
@@ -133,8 +144,14 @@ test_expr expr-3.32 {t1='xyz', t2='abc'} {t1||' hi '||t2} {{xyz hi abc}}
test_expr expr-4.1 {t1='abc', t2='Abc'} {t1t2} 1
-test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1t2} 0
+test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1t2} 1
+test_expr expr-4.5 {t1='0', t2='0.0'} {t1==t2} 1
+test_expr expr-4.6 {t1='0.000', t2='0.0'} {t1==t2} 1
+test_expr expr-4.7 {t1=' 0.000', t2=' 0.0'} {t1==t2} 0
+test_expr expr-4.8 {t1='0.0', t2='abc'} {t1t2} 0
test_expr expr-5.1 {t1='abc', t2='xyz'} {t1 LIKE t2} 0
test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1
diff --git a/test/index.test b/test/index.test
index 359c821d41..43a39ef15d 100644
--- a/test/index.test
+++ b/test/index.test
@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE INDEX statement.
#
-# $Id: index.test,v 1.16 2001/11/23 00:24:12 drh Exp $
+# $Id: index.test,v 1.17 2001/11/24 00:31:47 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -331,4 +331,54 @@ do_test index-11.1 {
concat [execsql {SELECT c FROM t3 WHERE b==10}] $sqlite_search_count
} {0.10 3}
+# Numeric strings should compare as if they were numbers. So even if the
+# strings are not character-by-character the same, if they represent the
+# same number they should compare equal to one another. Verify that this
+# is true in indices.
+#
+do_test index-12.1 {
+ execsql {
+ CREATE TABLE t4(a,b);
+ INSERT INTO t4 VALUES('0.0',1);
+ INSERT INTO t4 VALUES('0.00',2);
+ INSERT INTO t4 VALUES('abc',3);
+ INSERT INTO t4 VALUES('-1.0',4);
+ INSERT INTO t4 VALUES('+1.0',5);
+ INSERT INTO t4 VALUES('0',6);
+ INSERT INTO t4 VALUES('00000',7);
+ SELECT a FROM t4 ORDER BY b;
+ }
+} {0.0 0.00 abc -1.0 +1.0 0 00000}
+do_test index-12.2 {
+ execsql {
+ SELECT a FROM t4 WHERE a==0 ORDER BY b
+ }
+} {0.0 0.00 0 00000}
+do_test index-12.3 {
+ execsql {
+ SELECT a FROM t4 WHERE a<0.5 ORDER BY b
+ }
+} {0.0 0.00 -1.0 0 00000}
+do_test index-12.4 {
+ execsql {
+ SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
+ }
+} {0.0 0.00 abc +1.0 0 00000}
+do_test index-12.5 {
+ execsql {
+ CREATE INDEX t4i1 ON t4(a);
+ SELECT a FROM t4 WHERE a==0 ORDER BY b
+ }
+} {0.0 0.00 0 00000}
+do_test index-12.6 {
+ execsql {
+ SELECT a FROM t4 WHERE a<0.5 ORDER BY b
+ }
+} {0.0 0.00 -1.0 0 00000}
+do_test index-12.7 {
+ execsql {
+ SELECT a FROM t4 WHERE a>-0.5 ORDER BY b
+ }
+} {0.0 0.00 abc +1.0 0 00000}
+
finish_test
diff --git a/www/changes.tcl b/www/changes.tcl
index 9b19247fe4..c76ad91bcd 100644
--- a/www/changes.tcl
+++ b/www/changes.tcl
@@ -17,6 +17,14 @@ proc chng {date desc} {
puts "
"
}
+chng {2001 Nov 23 (2.1.3)} {
+Fix the behavior of comparison operators
+ (ex: "<", "==", etc.)
+ so that they are consistent with the order of entries in an index.
+Correct handling of integers in SQL expressions that are larger than
+ what can be represented by the machine integer.
+}
+
chng {2001 Nov 22 (2.1.2)} {
Changes to support 64-bit architectures.
Fix a bug in the locking protocol.
diff --git a/www/faq.tcl b/www/faq.tcl
new file mode 100644
index 0000000000..d300a7a397
--- /dev/null
+++ b/www/faq.tcl
@@ -0,0 +1,165 @@
+#
+# Run this script to generated a faq.html output file
+#
+puts {
+
+ SQLite Frequently Asked Questions
+
+
+Frequently Asked Questions
+}
+
+set cnt 1
+proc faq {question answer} {
+ set ::faq($::cnt) [list [string trim $question] [string trim $answer]]
+ incr ::cnt
+}
+
+#############
+# Enter questions and answers here.
+
+faq {
+ How do I create an AUTOINCREMENT field.
+} {
+ SQLite does not support AUTOINCREMENT. If you need a unique key for
+ a new entry in a table, you can create an auxiliary table
+ with a single entry that holds the next available value for that key.
+ Like this:
+
+CREATE TABLE counter(cnt);
+INSERT INTO counter VALUES(1);
+
+ Once you have a counter set up, you can generate a unique key as follows:
+
+BEGIN TRANSACTION;
+SELECT cnt FROM counter;
+UPDATE counter SET cnt=cnt+1;
+COMMIT;
+
+ There are other ways of simulating the effect of AUTOINCREMENT but
+ this approach seems to be the easiest and most efficient.
+}
+
+faq {
+ SQLite lets me insert a string into a database column of type integer!
+} {
+ This is a feature, not a bug. SQLite is typeless. Any data can be
+ 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
+ an arbitrary length string.
+
+ Because SQLite ignores data types, you can omit the data type definition
+ from columns in CREATE TABLE statements. For example, instead of saying
+
+CREATE TABLE t1(
+ f1 int,
+ f2 varchar(10),
+ f3 boolean
+);
+
+ You can save yourself a lot of typing and formatting by omitting the
+ data type declarations, like this:
+
+CREATE TABLE t1(f1,f2,f3);
+
+
+}
+
+faq {
+ Why does SQLite think that the expression '0'=='00' is TRUE?
+} {
+ 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.
+
+ 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 atof() and the results
+ are compared. The results of atof("0") and atof("00")
+ are both 0.0, so those two strings are considered to be equal.
+
+ 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 strcmp() is used for the comparison.
+}
+
+faq {
+ The second INSERT in the following sequence of commands returns with
+ constraint error.
+
+ CREATE TABLE t(s varchar(10) primary key);
+ INSERT INTO t VALUES('0');
+ INSERT INTO t VALUES('0.0');
+
+ Why is this?
+} {
+ Because column s is a primary key, all values of s must
+ be unique. But SQLite thinks that '0' and '0.0' are the
+ same value because they compare equal to one another numerically.
+ (See the previous question.) Hence the values are not unique and the
+ constraint fails.
+
+ You can work around this issue in several ways:
+
+ Remove the primary key clause from the CREATE TABLE so that
+ s can contain more than one entry with the same value.
+ If you need an index on the s column then create it separately.
+
+ Prepend a space to the beginning of every s value. The initial
+ space will mean that the entries are not pure numerics and hence
+ will be compared as strings using strcmp().
+
+}
+
+faq {
+ My linux box is not able to read an SQLite database that was created
+ on my SparcStation.
+} {
+ The x86 processor on your windows box is little-endian (meaning that
+ the least signification byte of integers comes first) but the Sparc is
+ big-endian (the most significant bytes comes first). SQLite databases
+ created on a little-endian architecture cannot be used on a big-endian
+ machine and vice versa.
+
+ If you need to move the database from one machine to another, you'll
+ have to do an ASCII dump of the database on the source machine and then
+ reconstruct the database at the destination machine. The following is
+ a typical command for transferring an SQLite databases between two
+ machines:
+
+echo .dump | sqlite from.db | ssh sparc 'sqlite to.db'
+
+ The command above assumes the name of the destination machine is
+ sparc and that you have SSH running on both the source and
+ destination. An alternative approach is to save the output of the first
+ sqlite command in a temporary file, move the temporary file
+ to the destination machine, then run the second sqlite command
+ while redirecting input from the temporary file.
+}
+
+# End of questions and answers.
+#############
+
+puts {}
+for {set i 1} {$i<$cnt} {incr i} {
+ puts " - ($i)
"
+ puts " - [lindex $faq($i) 0]
"
+}
+puts {
}
+
+for {set i 1} {$i<$cnt} {incr i} {
+ puts ""
+ puts "($i) [lindex $faq($i) 0]
\n"
+ puts "[lindex $faq($i) 1]
\n"
+}
+
+puts {
+
+
+Back to the SQLite Home Page
+
+
+}
diff --git a/www/index.tcl b/www/index.tcl
index 4dd9c9b309..d7718da096 100644
--- a/www/index.tcl
+++ b/www/index.tcl
@@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.47 2001/11/12 12:43:22 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.48 2001/11/24 00:31:47 drh Exp $}
puts {
SQLite: An SQL Database Engine In A C Library
@@ -105,6 +105,7 @@ newer versions of SQLite.
The following documentation is currently available: