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
mingw.html \
tclsqlite.html \
download.html \
- speed.html
+ speed.html \
+ faq.html
doc: $(DOC)
mkdir -p doc
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
mingw.html \
tclsqlite.html \
download.html \
- speed.html
+ speed.html \
+ faq.html
doc: $(DOC)
mkdir -p doc
-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
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
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
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
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
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
-f14835df32b4a16c840b8827f0c17f0e6d526312
\ No newline at end of file
+fc2aae04578c305304a45ec6b76d3ab216cc7526
\ No newline at end of file
** 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"
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: {
}
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);
** 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 <stdlib.h>
#include <string.h>
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 ){
** 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 <stdarg.h>
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:
};
/* 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;
}
/*
-** 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( rA<rB ){
- *pResult = -1;
- }else if( rA>rB ){
- *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 <stdlib.h>
-#include <stdio.h>
-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; i<n; i++){
- printf("%s\n", azStr[i]);
- }
- printf("Sanity1...");
- fflush(stdout);
- cnt = 0;
- for(i=0; i<n-1; i++){
- char *a = azStr[i];
- for(j=i+1; j<n; j++){
- char *b = azStr[j];
- if( sqliteCompare(a,b) != -sqliteCompare(b,a) ){
- printf("Failed! \"%s\" vs \"%s\"\n", a, b);
- i = j = n;
- }
- cnt++;
- }
- }
- if( i<n ){
- printf(" OK (%d)\n", cnt);
- }
- printf("Sanity2...");
- fflush(stdout);
- cnt = 0;
- for(i=0; i<n; i++){
- char *a = azStr[i];
- for(j=0; j<n; j++){
- char *b = azStr[j];
- for(k=0; k<n; k++){
- char *c = azStr[k];
- int x1, x2, x3, success;
- x1 = sqliteCompare(a,b);
- x2 = sqliteCompare(b,c);
- x3 = sqliteCompare(a,c);
- if( x1==0 ){
- success = x2==x3;
- }else if( x1<0 ){
- success = (x2<=0 && x3<=0) || x2>0;
- }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( rA<rB ){
+ result = -1;
+ }else if( rA>rB ){
+ result = +1;
+ }else{
+ result = 0;
}
}
+ }else if( isNumB ){
+ result = +1;
+ }else {
+ result = strcmp(atext, btext);
}
- if( i<n+1 ){
- printf(" OK (%d)\n", cnt);
- }
- return 0;
+ return result;
}
-#endif
/*
** This routine is used for sorting. Each key is a list of one or more
** Every string begins with either a "+" or "-" character. If the
** character is "-" then the return value is negated. This is done
** to implement a sort in descending order.
+**
+** For sorting purposes, pur numeric strings (strings for which the
+** isNum() function above returns TRUE) always compare less than strings
+** that are not pure numerics. Within non-numeric strings, substrings
+** of digits compare in numerical order. Finally, case is used only
+** to break a tie.
+**
+** Note that the sort order imposed by the rules above is different
+** from the ordering defined by the "<", "<=", ">", 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( rA<rB ){
+ res = -1;
+ break;
+ }
+ if( rA>rB ){
+ 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)
# 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
} {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
#
# 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
test_expr expr-1.44 {i1=1} {~i1} {-2}
test_expr expr-1.45 {i1=1, i2=3} {i1<<i2} {8}
test_expr expr-1.46 {i1=32, i2=3} {i1>>i2} {4}
+test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1<i2} 0
+test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0
+test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1
+test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1<i2} 0
+test_expr expr-1.51 {i1=99999999999, i2=99999999998} {i1=i2} 0
+test_expr expr-1.52 {i1=99999999999, i2=99999999998} {i1>i2} 1
+test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1<i2} 0
+test_expr expr-1.54 {i1=099999999999, i2=99999999999} {i1=i2} 1
+test_expr expr-1.55 {i1=099999999999, i2=99999999999} {i1>i2} 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
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}
test_expr expr-4.1 {t1='abc', t2='Abc'} {t1<t2} 0
test_expr expr-4.2 {t1='abc', t2='Abc'} {t1>t2} 1
-test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1<t2} 1
-test_expr expr-4.4 {t1='abc', t2='Bbc'} {t1>t2} 0
+test_expr expr-4.3 {t1='abc', t2='Bbc'} {t1<t2} 0
+test_expr expr-4.4 {t1='abc', t2='Bbc'} {t1>t2} 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'} {t1<t2} 1
+test_expr expr-4.9 {t1='0.0', t2='abc'} {t1==t2} 0
+test_expr expr-4.10 {t1='0.0', t2='abc'} {t1>t2} 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
# 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
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
puts "<DD><P><UL>$desc</UL></P></DD>"
}
+chng {2001 Nov 23 (2.1.3)} {
+<li>Fix the behavior of comparison operators
+ (ex: "<b><</b>", "<b>==</b>", etc.)
+ so that they are consistent with the order of entries in an index.</li>
+<li>Correct handling of integers in SQL expressions that are larger than
+ what can be represented by the machine integer.</li>
+}
+
chng {2001 Nov 22 (2.1.2)} {
<li>Changes to support 64-bit architectures.</li>
<li>Fix a bug in the locking protocol.</li>
--- /dev/null
+#
+# Run this script to generated a faq.html output file
+#
+puts {<html>
+<head>
+ <title>SQLite Frequently Asked Questions</title>
+</head>
+<body bgcolor="white">
+<h1 align="center">Frequently Asked Questions</h1>
+}
+
+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:
+<blockquote><pre>
+CREATE TABLE counter(cnt);
+INSERT INTO counter VALUES(1);
+</pre></blockquote>
+ Once you have a counter set up, you can generate a unique key as follows:
+<blockquote><pre>
+BEGIN TRANSACTION;
+SELECT cnt FROM counter;
+UPDATE counter SET cnt=cnt+1;
+COMMIT;
+</pre></blockquote>
+ 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!
+} {
+ <p>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.</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
+);
+</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>
+}
+
+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>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>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>
+}
+
+faq {
+ The second INSERT in the following sequence of commands returns with
+ constraint error.
+ <blockquote>
+ CREATE TABLE t(s varchar(10) primary key);<br>
+ INSERT INTO t VALUES('0');<br>
+ INSERT INTO t VALUES('0.0');<br>
+ </blockquote>
+ Why is this?
+} {
+ <p>Because column <b>s</b> is a primary key, all values of <b>s</b> must
+ be unique. But 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 and the
+ constraint fails.</p>
+
+ <p>You can work around this issue in several ways:</p>
+ <ol>
+ <li><p>Remove the <b>primary key</b> clause from the CREATE TABLE so that
+ <b>s</b> can contain more than one entry with the same value.
+ If you need an index on the <b>s</b> column then create it separately.
+ </p></li>
+ <li><p>Prepend a space to the beginning of every <b>s</b> value. 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 {
+ My linux box is not able to read an SQLite database that was created
+ on my SparcStation.
+} {
+ <p>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.</p>
+
+ <p>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:
+<blockquote><pre>
+echo .dump | sqlite from.db | ssh sparc 'sqlite to.db'
+</pre></blockquote>
+ The command above assumes the name of the destination machine is
+ <b>sparc</b> and that you have SSH running on both the source and
+ destination. An alternative approach is to save the output of the first
+ <b>sqlite</b> command in a temporary file, move the temporary file
+ to the destination machine, then run the second <b>sqlite</b> command
+ while redirecting input from the temporary file.</p>
+}
+
+# End of questions and answers.
+#############
+
+puts {<DL COMPACT>}
+for {set i 1} {$i<$cnt} {incr i} {
+ puts " <DT><A HREF=\"#q$i\">($i)</A></DT>"
+ puts " <DD>[lindex $faq($i) 0]</DD>"
+}
+puts {</DL><HR />}
+
+for {set i 1} {$i<$cnt} {incr i} {
+ puts "<A NAME=\"q$i\">"
+ puts "<P><B>($i) [lindex $faq($i) 0]</B></P>\n"
+ puts "<BLOCKQUOTE>[lindex $faq($i) 1]</BLOCKQUOTE>\n"
+}
+
+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>}
#
# 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 {<html>
<head><title>SQLite: An SQL Database Engine In A C Library</title></head>
<p>The following documentation is currently available:</p>
<p><ul>
+<li><a href="faq.html">Frequently Asked Questions</a> are available online.</li>
<li>Information on the <a href="sqlite.html">sqlite</a>
command-line utility.</li>
<li>The <a href="lang.html">SQL Language</a> subset understood by SQLite.</li>