/ Check-in [585ed5eb]
Login
Overview
Comment:Bug fix: sqlite_exec() would sometimes return SQLITE_PROTOCOL when it should have returned SQLITE_BUSY. There was also a deadlock that the previous bug was masking. (CVS 322)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:585ed5ebf1c1afc8ae1d569b121208018d8ecd49
User & Date: drh 2001-12-05 00:21:20
Context
2001-12-05
00:22
Version 2.1.4 (CVS 323) check-in: 003f967e user: drh tags: trunk
00:21
Bug fix: sqlite_exec() would sometimes return SQLITE_PROTOCOL when it should have returned SQLITE_BUSY. There was also a deadlock that the previous bug was masking. (CVS 322) check-in: 585ed5eb user: drh tags: trunk
2001-11-25
13:18
Add the ability to do a single .command as the second argument to the command-line shell. (CVS 321) check-in: 653f37c3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
671
672
673
674
675
676
677


















678
679
680
681
682
683
684
...
721
722
723
724
725
726
727
728


729
730
731
732
733
734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763
** a legal notice, here is a blessing:
**
**    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.
**
*************************************************************************
** $Id: btree.c,v 1.41 2001/11/23 00:24:12 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
  return rc;

page1_init_failed:
  sqlitepager_unref(pBt->page1);
  pBt->page1 = 0;
  return rc;
}



















/*
** Create a new database by initializing the first two pages of the
** file.
*/
static int newDatabase(Btree *pBt){
  MemPage *pRoot;
................................................................................
  if( pBt->inTrans ) return SQLITE_ERROR;
  if( pBt->page1==0 ){
    rc = lockBtree(pBt);
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }
  if( !sqlitepager_isreadonly(pBt->pPager) ){


    rc = sqlitepager_write(pBt->page1);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    rc = newDatabase(pBt);
  }

  pBt->inTrans = 1;
  return rc;
}

/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which 
** has the effect of releasing the read lock.
**
** If there are any outstanding cursors, this routine is a no-op.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
  if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
    sqlitepager_unref(pBt->page1);
    pBt->page1 = 0;
    pBt->inTrans = 0;
  }

}

/*
** Commit the transaction currently in progress.
**
** This will release the write lock on the database file.  If there
** are no active cursors, it also releases the read lock.
*/
int sqliteBtreeCommit(Btree *pBt){







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>
>
|
|
<
<


>
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<

>









5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
...
739
740
741
742
743
744
745
746
747
748
749
750


751
752
753
754

755











756




757
758
759
760
761
762
763
764
765
766
767
** a legal notice, here is a blessing:
**
**    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.
**
*************************************************************************
** $Id: btree.c,v 1.42 2001/12/05 00:21:20 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
  return rc;

page1_init_failed:
  sqlitepager_unref(pBt->page1);
  pBt->page1 = 0;
  return rc;
}

/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which 
** has the effect of releasing the read lock.
**
** If there are any outstanding cursors, this routine is a no-op.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
  if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
    sqlitepager_unref(pBt->page1);
    pBt->page1 = 0;
    pBt->inTrans = 0;
  }
}

/*
** Create a new database by initializing the first two pages of the
** file.
*/
static int newDatabase(Btree *pBt){
  MemPage *pRoot;
................................................................................
  if( pBt->inTrans ) return SQLITE_ERROR;
  if( pBt->page1==0 ){
    rc = lockBtree(pBt);
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }
  if( sqlitepager_isreadonly(pBt->pPager) ){
    return SQLITE_READONLY;
  }
  rc = sqlitepager_write(pBt->page1);
  if( rc==SQLITE_OK ){


    rc = newDatabase(pBt);
  }
  if( rc==SQLITE_OK ){
    pBt->inTrans = 1;

  }else{











    unlockBtreeIfUnused(pBt);




  }
  return rc;
}

/*
** Commit the transaction currently in progress.
**
** This will release the write lock on the database file.  If there
** are no active cursors, it also releases the read lock.
*/
int sqliteBtreeCommit(Btree *pBt){

Changes to src/build.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.57 2001/11/22 00:01:27 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
static void changeCookie(sqlite *db){
  if( db->next_cookie==db->schema_cookie ){
    db->next_cookie = db->schema_cookie + sqliteRandomByte(db) + 1;
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.







|







 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.58 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
static void changeCookie(sqlite *db){
  if( db->next_cookie==db->schema_cookie ){
    db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.50 2001/11/23 00:24:12 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
................................................................................

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  db->nextRowid = sqliteRandomInteger(db);
  
  /* Open the backend database driver */
  rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        if( pzErrMsg ){







|







 







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.51 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
................................................................................

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  db->nextRowid = sqliteRandomInteger();
  
  /* Open the backend database driver */
  rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        if( pzErrMsg ){

Changes to src/os.h.

55
56
57
58
59
60
61
62
63
64
65
66
67
int sqliteOsSync(OsFile);
int sqliteOsTruncate(OsFile, int size);
int sqliteOsFileSize(OsFile, int *pSize);
int sqliteOsLock(OsFile, int wrlock);
int sqliteOsUnlock(OsFile);
int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms);
void sqliteOsEnterMutex();
void sqliteOsLeaveMutex();



#endif /* _SQLITE_OS_H_ */







|
|




55
56
57
58
59
60
61
62
63
64
65
66
67
int sqliteOsSync(OsFile);
int sqliteOsTruncate(OsFile, int size);
int sqliteOsFileSize(OsFile, int *pSize);
int sqliteOsLock(OsFile, int wrlock);
int sqliteOsUnlock(OsFile);
int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms);
void sqliteOsEnterMutex(void);
void sqliteOsLeaveMutex(void);



#endif /* _SQLITE_OS_H_ */

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
951
952
953
954
955
956
957


958
959
960
961

962
963
964




965
966
967
968
969
970
971
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.31 2001/11/22 00:01:27 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "os.h"
#include <assert.h>
#include <string.h>

................................................................................
      sqliteOsClose(pPager->jfd);
      sqliteOsDelete(pPager->zJournal);
      pPager->journalOpen = 0;
      return SQLITE_BUSY;
    }
    sqliteOsUnlock(pPager->fd);
    if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){


      sqliteFree(pPager->aInJournal);
      sqliteOsClose(pPager->jfd);
      sqliteOsDelete(pPager->zJournal);
      pPager->journalOpen = 0;

      pPager->state = SQLITE_UNLOCK;
      pPager->errMask |= PAGER_ERR_LOCK;
      return SQLITE_PROTOCOL;




    }
    pPager->state = SQLITE_WRITELOCK;
    sqlitepager_pagecount(pPager);
    pPager->origDbSize = pPager->dbSize;
    rc = sqliteOsWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
    if( rc==SQLITE_OK ){
      rc = sqliteOsWrite(pPager->jfd, &pPager->dbSize, sizeof(Pgno));







|







 







>
>




>
|
|
|
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.32 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "os.h"
#include <assert.h>
#include <string.h>

................................................................................
      sqliteOsClose(pPager->jfd);
      sqliteOsDelete(pPager->zJournal);
      pPager->journalOpen = 0;
      return SQLITE_BUSY;
    }
    sqliteOsUnlock(pPager->fd);
    if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
      sqliteOsUnlock(pPager->fd);
      rc = sqliteOsLock(pPager->fd, 0);
      sqliteFree(pPager->aInJournal);
      sqliteOsClose(pPager->jfd);
      sqliteOsDelete(pPager->zJournal);
      pPager->journalOpen = 0;
      if( rc ){
        pPager->state = SQLITE_UNLOCK;
        pPager->errMask |= PAGER_ERR_LOCK;
        return SQLITE_PROTOCOL;
      }else{
        pPager->state = SQLITE_READLOCK;
        return SQLITE_BUSY;
      }
    }
    pPager->state = SQLITE_WRITELOCK;
    sqlitepager_pagecount(pPager);
    pPager->origDbSize = pPager->dbSize;
    rc = sqliteOsWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
    if( rc==SQLITE_OK ){
      rc = sqliteOsWrite(pPager->jfd, &pPager->dbSize, sizeof(Pgno));

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
515
516
517
518
519
520
521
522
523
524
525
526
527
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.71 2001/11/22 00:01:27 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
int sqliteExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqliteExprResolveIds(Parse*, IdList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte();
int sqliteRandomInteger();
void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);







|







 







|
|




7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
515
516
517
518
519
520
521
522
523
524
525
526
527
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.72 2001/12/05 00:21:20 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
int sqliteExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqliteExprResolveIds(Parse*, IdList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void);
int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);

Changes to www/changes.tcl.

13
14
15
16
17
18
19
20




21
22

23
24
25
26
27
28
29


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Nov ?? (2.1.4)} {




<li>Add the ability to put a single .command in the second argument
    of the sqlite shell</li>

}

chng {2001 Nov 23 (2.1.3)} {
<li>Fix the behavior of comparison operators 
    (ex: "<b>&lt</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







|
>
>
>
>


>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Dec 4 (2.1.4)} {
<li>Sometime <b>sqlite_exec()</b> would return SQLITE_PROTOCOL when it
    should have returned SQLITE_BUSY.</li>
<li>The fix to the previous bug uncovered a deadlock which was also
    fixed.</li>
<li>Add the ability to put a single .command in the second argument
    of the sqlite shell</li>
<li>Updates to the FAQ</li>
}

chng {2001 Nov 23 (2.1.3)} {
<li>Fix the behavior of comparison operators 
    (ex: "<b>&lt</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

Changes to www/faq.tcl.

1
2
3
4
5
6
7
8
9
10
11
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
229
230
231
232
233
234
235
























236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
#
# Run this script to generated a faq.html output file
#
set rcsid {$Id: faq.tcl,v 1.2 2001/11/24 13:23:05 drh Exp $}

puts {<html>
<head>
  <title>SQLite Frequently Asked Questions</title>
</head>
<body bgcolor="white">
<h1 align="center">Frequently Asked Questions</h1>
................................................................................

  <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>

................................................................................
  </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
................................................................................
  <p>The SQLITE_MASTER table is read-only.  You cannot change this table
  using UPDATE, INSERT, or DELETE.  The table is automatically updated by
  CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands.</p>

  <p>Temporary tables do not appear in the SQLITE_MASTER table.  At this time
  there is no way to get a listing of temporary tables and indices.</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>}



|







 







|
|





<







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|


|

|



>






1
2
3
4
5
6
7
8
9
10
11
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
228
229
230
231
232
233
234
235
236
237
238
239
240
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#
# Run this script to generated a faq.html output file
#
set rcsid {$Id: faq.tcl,v 1.3 2001/12/05 00:21:21 drh Exp $}

puts {<html>
<head>
  <title>SQLite Frequently Asked Questions</title>
</head>
<body bgcolor="white">
<h1 align="center">Frequently Asked Questions</h1>
................................................................................

  <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 {
  Why does the second INSERT in the following sequence of commands throw
  a constraint exception?
  <blockquote>
     CREATE TABLE t(s varchar(10) primary key);<br>
     INSERT INTO t VALUES('0');<br>
     INSERT INTO t VALUES('0.0');<br>
  </blockquote>

} {
  <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>

................................................................................
  </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 linux 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
................................................................................
  <p>The SQLITE_MASTER table is read-only.  You cannot change this table
  using UPDATE, INSERT, or DELETE.  The table is automatically updated by
  CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands.</p>

  <p>Temporary tables do not appear in the SQLITE_MASTER table.  At this time
  there is no way to get a listing of temporary tables and indices.</p>
}

faq {
  Is there any known size limits to SQLite databases.
} {
  <p>Internally, SQLite can handle databases up to 2^40 bytes (1 terabyte)
  in size.  But the backend interface to POSIX and Win32 limits files to
  2^31 (2 gigabytes).</p>

  <p>SQLite arbitrarily limits the amount of data in one row to 1 megabyte.
  There is a single #define in the source code that can be changed to raise
  this limit as high as 16 megabytes if desired.</p>

  <p>There is a theoretical limit of about 2^32 (4 billion) rows
  in a single table, but there
  is no way to test this limit without exceeding the maximum file size, so
  it is not really an issue.  There is also a theoretical limit of about 2^32
  tables and indices, but again it is not really possible to reach this
  limit due to the file size constraint.</p>

  <p>The name and "CREATE TABLE" statement for a table must fit entirely
  within a 1-megabyte row of the SQLITE_MASTER table.  Other than this,
  there are no constraints on the length of the name of a table, or on the
  number of columns, etc.  Indices are similarly unconstrained.</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>}

for {set i 1} {$i<$cnt} {incr i} {
  puts "<A NAME=\"q$i\"><HR />"
  puts "<P><B>($i) [lindex $faq($i) 0]</B></P>\n"
  puts "<BLOCKQUOTE>[lindex $faq($i) 1]</BLOCKQUOTE></LI>\n"
}

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

</body></html>}