]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Split the implementation of COPY, PRAGMA, and ATTACH into separate
authordrh <drh@noemail.net>
Sun, 6 Apr 2003 21:08:24 +0000 (21:08 +0000)
committerdrh <drh@noemail.net>
Sun, 6 Apr 2003 21:08:24 +0000 (21:08 +0000)
source code files. (CVS 902)

FossilOrigin-Name: 73359037ea639abb066c74db9c19e84bf1104006

Makefile.in
main.mk
manifest
manifest.uuid
src/attach.c [new file with mode: 0644]
src/build.c
src/copy.c [new file with mode: 0644]
src/pragma.c [new file with mode: 0644]
src/vacuum.c [new file with mode: 0644]

index b98fef19d12de64278be23f6784b4c2e27b3a2f8..398d593bbc0e95fe57a9485d86d46d22315a993f 100644 (file)
@@ -62,18 +62,22 @@ ENCODING = @ENCODING@
 
 # Object files for the SQLite library.
 #
-LIBOBJ = auth.lo btree.lo build.lo delete.lo expr.lo func.lo hash.lo insert.lo \
-         main.lo opcodes.lo os.lo pager.lo parse.lo printf.lo random.lo \
-         select.lo table.lo tokenize.lo update.lo util.lo vacuum.lo vdbe.lo \
+LIBOBJ = attach.lo auth.lo btree.lo build.lo copy.lo \
+         delete.lo expr.lo func.lo hash.lo insert.lo \
+         main.lo opcodes.lo os.lo pager.lo parse.lo pragma.lo \
+         printf.lo random.lo select.lo table.lo tokenize.lo \
+         update.lo util.lo vacuum.lo vdbe.lo \
          where.lo trigger.lo
 
 # All of the source code files.
 #
 SRC = \
+  $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
   $(TOP)/src/btree.h \
   $(TOP)/src/build.c \
+  $(TOP)/src/copy.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
   $(TOP)/src/func.c \
@@ -85,6 +89,7 @@ SRC = \
   $(TOP)/src/pager.c \
   $(TOP)/src/pager.h \
   $(TOP)/src/parse.y \
+  $(TOP)/src/pragma.c \
   $(TOP)/src/printf.c \
   $(TOP)/src/random.c \
   $(TOP)/src/select.c \
@@ -241,6 +246,9 @@ vdbe.lo:    $(TOP)/src/vdbe.c $(HDR)
 where.lo:      $(TOP)/src/where.c $(HDR)
        $(LIBTOOL) $(TCC) -c $(TOP)/src/where.c
 
+copy.lo:       $(TOP)/src/copy.c $(HDR)
+       $(LIBTOOL) $(TCC) -c $(TOP)/src/copy.c
+
 delete.lo:     $(TOP)/src/delete.c $(HDR)
        $(LIBTOOL) $(TCC) -c $(TOP)/src/delete.c
 
@@ -277,9 +285,15 @@ vacuum.lo: $(TOP)/src/vacuum.c $(HDR)
 tclsqlite.lo:  $(TOP)/src/tclsqlite.c $(HDR)
        $(LIBTOOL) $(TCC) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
 
+pragma.lo:     $(TOP)/src/pragma.c $(HDR)
+       $(LIBTOOL) $(TCC) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
+
 printf.lo:     $(TOP)/src/printf.c $(HDR)
        $(LIBTOOL) $(TCC) $(TCL_FLAGS) -c $(TOP)/src/printf.c
 
+attach.lo:     $(TOP)/src/attach.c $(HDR)
+       $(LIBTOOL) $(TCC) $(TCL_FLAGS) -c $(TOP)/src/attach.c
+
 auth.lo:       $(TOP)/src/auth.c $(HDR)
        $(LIBTOOL) $(TCC) $(TCL_FLAGS) -c $(TOP)/src/auth.c
 
diff --git a/main.mk b/main.mk
index 61db1b46b1865b515ca5349e7b220fb13ba1575d..6d10475aa63f7dd979fb3f91f7245709d9f2e8bc 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -54,18 +54,21 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
 
 # Object files for the SQLite library.
 #
-LIBOBJ = auth.o btree.o build.o delete.o expr.o func.o hash.o insert.o \
-         main.o opcodes.o os.o pager.o parse.o printf.o random.o \
+LIBOBJ = attach.o auth.o btree.o build.o copy.o delete.o \
+         expr.o func.o hash.o insert.o \
+         main.o opcodes.o os.o pager.o parse.o pragma.o printf.o random.o \
          select.o table.o tokenize.o trigger.o update.o util.o \
          vacuum.o vdbe.o where.o tclsqlite.o
 
 # All of the source code files.
 #
 SRC = \
+  $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
   $(TOP)/src/btree.h \
   $(TOP)/src/build.c \
+  $(TOP)/src/copy.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
   $(TOP)/src/func.c \
@@ -77,6 +80,7 @@ SRC = \
   $(TOP)/src/pager.c \
   $(TOP)/src/pager.h \
   $(TOP)/src/parse.y \
+  $(TOP)/src/pragma.c \
   $(TOP)/src/printf.c \
   $(TOP)/src/random.c \
   $(TOP)/src/select.c \
@@ -236,6 +240,9 @@ vdbe.o:     $(TOP)/src/vdbe.c $(HDR)
 where.o:       $(TOP)/src/where.c $(HDR)
        $(TCCX) -c $(TOP)/src/where.c
 
+copy.o:        $(TOP)/src/copy.c $(HDR)
+       $(TCCX) -c $(TOP)/src/copy.c
+
 delete.o:      $(TOP)/src/delete.c $(HDR)
        $(TCCX) -c $(TOP)/src/delete.c
 
@@ -266,9 +273,15 @@ update.o:  $(TOP)/src/update.c $(HDR)
 tclsqlite.o:   $(TOP)/src/tclsqlite.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c
 
+pragma.o:      $(TOP)/src/pragma.c $(HDR)
+       $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/pragma.c
+
 printf.o:      $(TOP)/src/printf.c $(HDR)
        $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/printf.c
 
+attach.o:      $(TOP)/src/attach.c $(HDR)
+       $(TCCX) -c $(TOP)/src/attach.c
+
 auth.o:        $(TOP)/src/auth.c $(HDR)
        $(TCCX) -c $(TOP)/src/auth.c
 
index 63ad9f2c47edeff14687790246aaa948df04a844..79e87278a72891cc7bc9f89ede757ee4194d889b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,6 +1,6 @@
-C Move\sthe\simplementation\sof\sVACUUM\sinto\sa\sseparate\ssource\sfile.\s(CVS\s901)
-D 2003-04-06T20:52:32
-F Makefile.in 5b084c4a4abf08fa5cdebe78ccebf6310198139c
+C Split\sthe\simplementation\sof\sCOPY,\sPRAGMA,\sand\sATTACH\sinto\sseparate\nsource\scode\sfiles.\s(CVS\s902)
+D 2003-04-06T21:08:24
+F Makefile.in 935bf18ecefa32f780acdc1660852403468f0058
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
 F VERSION e5b03976c56deafa24511d6ef17d64a28679e9bd
@@ -14,15 +14,17 @@ F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F libtool bbbea7d79c23323e4100103836028e4fad0d9242
 F ltmain.sh abfb9387049fff6996afc6e325736597795baf11
-F main.mk 931fdcd4fc6ac4d4e6eb5ce975ad2fb4995ccbcc
+F main.mk 08739679174d858a0f6ced3117ce8dcfdafa540a
 F publish.sh 86b5e8535830a2588f62ce1d5d1ef00e1dede23a
 F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
 F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
 F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
+F src/attach.c 1e429791ee28427403938388ede9fea2caef17b2
 F src/auth.c f37bfc9451b8c1fa52f34adff474560018892729
 F src/btree.c 3b0e0f09886bc83fa183df367d6a1b7077da9c46
 F src/btree.h 5cb871546bd6fa58396a6f033e2b29b388241e1b
-F src/build.c da21ffe7daeea576ebfbeb2f96ac0f99fa6b9a09
+F src/build.c f0c774c4c4ec7d79d1021de7d941863faeb77fd6
+F src/copy.c ddd204d5dddac09d71a07f4ceded4c9926d5512b
 F src/delete.c 58d698779a6b7f819718ecd45b310a9de8537088
 F src/encode.c faf03741efe921755ec371cf4a6984536de00042
 F src/expr.c b8daee83f837b24a22d889200bdd74973ca2d8db
@@ -37,6 +39,7 @@ F src/os.h aa52f0c9da321ff6134d19f2ca959e18e33615d0
 F src/pager.c df4c81350cbd80c1ab48341ae0768ba78d99ad49
 F src/pager.h e3702f7d384921f6cd5ce0b3ed589185433e9f6c
 F src/parse.y 3be47fa18323aa2e3364fc42bf7a6ba5b3cc0a81
+F src/pragma.c 927fc036580eea38ae05c5f0da75fd4ee340f6f0
 F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e
 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c 14e2e2a512f4edfc75fb310ebcb502ff3ee87402
@@ -54,6 +57,7 @@ F src/tokenize.c 675b4718d17c69fe7609dc8e85e426ef002be811
 F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3
 F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a
 F src/util.c 8953c612a036e30f24c1c1f5a1498176173daa37
+F src/vacuum.c 6b9ebf0ef5761b06ce86672574c71b1e9098ef9c
 F src/vdbe.c 540c480912e11e23f5c08a31b8b3594df016f4d1
 F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
 F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127
@@ -157,7 +161,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 185d8dc8d0c26cef36aeba6992823e5124af4056
-R 7a927220f0e77fb63a637996080a8eec
+P b123c165fd3d0a5a86ee8a7baa669105dafb481a
+R 351f9d3f3ae1d413356658b3a79e309f
 U drh
-Z 2542fde3715240ecd80028ec8868e426
+Z 8dcf477abd69457b6da834133632d978
index 286173916ee67f3f144604e87ca824245f15891e..84f4d174de2796c11283e231882f6cb8418fd40b 100644 (file)
@@ -1 +1 @@
-b123c165fd3d0a5a86ee8a7baa669105dafb481a
\ No newline at end of file
+73359037ea639abb066c74db9c19e84bf1104006
\ No newline at end of file
diff --git a/src/attach.c b/src/attach.c
new file mode 100644 (file)
index 0000000..a2ffc28
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code.  In place of
+** 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.
+**
+*************************************************************************
+** This file contains code used to implement the ATTACH and DETACH commands.
+**
+** $Id: attach.c,v 1.1 2003/04/06 21:08:24 drh Exp $
+*/
+#include "sqliteInt.h"
+
+/*
+** This routine is called by the parser to process an ATTACH statement:
+**
+**     ATTACH DATABASE filename AS dbname
+**
+** The pFilename and pDbname arguments are the tokens that define the
+** filename and dbname in the ATTACH statement.
+*/
+void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){
+  Db *aNew;
+  int rc, i;
+  char *zFile, *zName;
+  sqlite *db;
+
+  if( pParse->explain ) return;
+  db = pParse->db;
+  if( db->file_format<4 ){
+    sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
+       "older format master database", 0);
+    pParse->rc = SQLITE_ERROR;
+    return;
+  }
+  if( db->nDb>=MAX_ATTACHED+2 ){
+    sqliteErrorMsg(pParse, "too many attached databases - max %d", 
+       MAX_ATTACHED);
+    pParse->rc = SQLITE_ERROR;
+    return;
+  }
+  if( db->aDb==db->aDbStatic ){
+    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
+    if( aNew==0 ) return;
+    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
+  }else{
+    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
+    if( aNew==0 ) return;
+  }
+  db->aDb = aNew;
+  aNew = &db->aDb[db->nDb++];
+  memset(aNew, 0, sizeof(*aNew));
+  sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
+  sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
+  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
+  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
+  
+  zName = 0;
+  sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
+  if( zName==0 ) return;
+  sqliteDequote(zName);
+  for(i=0; i<db->nDb; i++){
+    if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
+      sqliteErrorMsg(pParse, "database %z is already in use", zName);
+      db->nDb--;
+      pParse->rc = SQLITE_ERROR;
+      return;
+    }
+  }
+  aNew->zName = zName;
+  zFile = 0;
+  sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
+  if( zFile==0 ) return;
+  sqliteDequote(zFile);
+  rc = sqliteBtreeOpen(zFile, 0, MAX_PAGES, &aNew->pBt);
+  if( rc ){
+    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
+  }
+  sqliteFree(zFile);
+  db->flags &= ~SQLITE_Initialized;
+  if( pParse->nErr ) return;
+  rc = sqliteInit(pParse->db, &pParse->zErrMsg);
+  if( rc ){
+    sqliteResetInternalSchema(db, 0);
+    pParse->nErr++;
+    pParse->rc = SQLITE_ERROR;
+  }
+}
+
+/*
+** This routine is called by the parser to process a DETACH statement:
+**
+**    DETACH DATABASE dbname
+**
+** The pDbname argument is the name of the database in the DETACH statement.
+*/
+void sqliteDetach(Parse *pParse, Token *pDbname){
+  int i;
+  sqlite *db;
+
+  if( pParse->explain ) return;
+  db = pParse->db;
+  for(i=0; i<db->nDb; i++){
+    if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
+    if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
+    if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
+  }
+  if( i>=db->nDb ){
+    sqliteErrorMsg(pParse, "no such database: %T", pDbname);
+    return;
+  }
+  if( i<2 ){
+    sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
+    return;
+  }
+  sqliteBtreeClose(db->aDb[i].pBt);
+  db->aDb[i].pBt = 0;
+  sqliteResetInternalSchema(db, i);
+  db->nDb--;
+  if( i<db->nDb ){
+    db->aDb[i] = db->aDb[db->nDb];
+    memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
+    sqliteResetInternalSchema(db, i);
+  }
+}
index 55720f3c9f865c204f77b2d7e445e16367e966b2..10750aad9955240a03d7b94bfea196fb4553f949 100644 (file)
 **     CREATE INDEX
 **     DROP INDEX
 **     creating ID lists
-**     COPY
 **     BEGIN TRANSACTION
 **     COMMIT
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.142 2003/04/06 20:52:32 drh Exp $
+** $Id: build.c,v 1.143 2003/04/06 21:08:24 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1980,106 +1979,6 @@ void sqliteSrcListDelete(SrcList *pList){
   sqliteFree(pList);
 }
 
-/*
-** The COPY command is for compatibility with PostgreSQL and specificially
-** for the ability to read the output of pg_dump.  The format is as
-** follows:
-**
-**    COPY table FROM file [USING DELIMITERS string]
-**
-** "table" is an existing table name.  We will read lines of code from
-** file to fill this table with data.  File might be "stdin".  The optional
-** delimiter string identifies the field separators.  The default is a tab.
-*/
-void sqliteCopy(
-  Parse *pParse,       /* The parser context */
-  SrcList *pTableName, /* The name of the table into which we will insert */
-  Token *pFilename,    /* The file from which to obtain information */
-  Token *pDelimiter,   /* Use this as the field delimiter */
-  int onError          /* What to do if a constraint fails */
-){
-  Table *pTab;
-  int i;
-  Vdbe *v;
-  int addr, end;
-  Index *pIdx;
-  char *zFile = 0;
-  sqlite *db = pParse->db;
-
-
-  if( sqlite_malloc_failed  ) goto copy_cleanup;
-  assert( pTableName->nSrc==1 );
-  pTab = sqliteSrcListLookup(pParse, pTableName);
-  if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ) goto copy_cleanup;
-  zFile = sqliteStrNDup(pFilename->z, pFilename->n);
-  sqliteDequote(zFile);
-  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
-      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
-    goto copy_cleanup;
-  }
-  v = sqliteGetVdbe(pParse);
-  if( v ){
-    sqliteBeginWriteOperation(pParse, 1, pTab->iDb==1);
-    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
-    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
-    sqliteVdbeDequoteP3(v, addr);
-    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-    sqliteVdbeAddOp(v, OP_OpenWrite, 0, pTab->tnum);
-    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
-    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-      assert( pIdx->iDb==1 || pIdx->iDb==pTab->iDb );
-      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
-      sqliteVdbeAddOp(v, OP_OpenWrite, i, pIdx->tnum);
-      sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
-    }
-    if( db->flags & SQLITE_CountRows ){
-      sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
-    }
-    end = sqliteVdbeMakeLabel(v);
-    addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
-    if( pDelimiter ){
-      sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
-      sqliteVdbeDequoteP3(v, addr);
-    }else{
-      sqliteVdbeChangeP3(v, addr, "\t", 1);
-    }
-    if( pTab->iPKey>=0 ){
-      sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
-      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
-    }else{
-      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
-    }
-    for(i=0; i<pTab->nCol; i++){
-      if( i==pTab->iPKey ){
-        /* The integer primary key column is filled with NULL since its
-        ** value is always pulled from the record number */
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-      }else{
-        sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
-      }
-    }
-    sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, 0, 0, onError, addr);
-    sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0);
-    if( (db->flags & SQLITE_CountRows)!=0 ){
-      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
-    }
-    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
-    sqliteVdbeResolveLabel(v, end);
-    sqliteVdbeAddOp(v, OP_Noop, 0, 0);
-    sqliteEndWriteOperation(pParse);
-    if( db->flags & SQLITE_CountRows ){
-      sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
-      sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
-      sqliteVdbeAddOp(v, OP_Callback, 1, 0);
-    }
-  }
-  
-copy_cleanup:
-  sqliteSrcListDelete(pTableName);
-  sqliteFree(zFile);
-  return;
-}
-
 /*
 ** Begin a transaction
 */
@@ -2205,567 +2104,3 @@ void sqliteEndWriteOperation(Parse *pParse){
     sqliteVdbeAddOp(v, OP_Commit, 0, 0);
   }
 }
-
-
-/*
-** Interpret the given string as a boolean value.
-*/
-static int getBoolean(char *z){
-  static char *azTrue[] = { "yes", "on", "true" };
-  int i;
-  if( z[0]==0 ) return 0;
-  if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
-    return atoi(z);
-  }
-  for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
-    if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
-  }
-  return 0;
-}
-
-/*
-** Interpret the given string as a safety level.  Return 0 for OFF,
-** 1 for ON or NORMAL and 2 for FULL.
-**
-** Note that the values returned are one less that the values that
-** should be passed into sqliteBtreeSetSafetyLevel().  The is done
-** to support legacy SQL code.  The safety level used to be boolean
-** and older scripts may have used numbers 0 for OFF and 1 for ON.
-*/
-static int getSafetyLevel(char *z){
-  static const struct {
-    const char *zWord;
-    int val;
-  } aKey[] = {
-    { "no",    0 },
-    { "off",   0 },
-    { "false", 0 },
-    { "yes",   1 },
-    { "on",    1 },
-    { "true",  1 },
-    { "full",  2 },
-  };
-  int i;
-  if( z[0]==0 ) return 1;
-  if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
-    return atoi(z);
-  }
-  for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
-    if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
-  }
-  return 1;
-}
-
-/*
-** Process a pragma statement.  
-**
-** Pragmas are of this form:
-**
-**      PRAGMA id = value
-**
-** The identifier might also be a string.  The value is a string, and
-** identifier, or a number.  If minusFlag is true, then the value is
-** a number that was preceded by a minus sign.
-*/
-void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
-  char *zLeft = 0;
-  char *zRight = 0;
-  sqlite *db = pParse->db;
-  Vdbe *v = sqliteGetVdbe(pParse);
-  if( v==0 ) return;
-
-  zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
-  sqliteDequote(zLeft);
-  if( minusFlag ){
-    zRight = 0;
-    sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
-  }else{
-    zRight = sqliteStrNDup(pRight->z, pRight->n);
-    sqliteDequote(zRight);
-  }
-  if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight) ){
-    sqliteFree(zLeft);
-    sqliteFree(zRight);
-    return;
-  }
-  /*
-  **  PRAGMA default_cache_size
-  **  PRAGMA default_cache_size=N
-  **
-  ** The first form reports the current persistent setting for the
-  ** page cache size.  The value returned is the maximum number of
-  ** pages in the page cache.  The second form sets both the current
-  ** page cache size value and the persistent page cache size value
-  ** stored in the database file.
-  **
-  ** The default cache size is stored in meta-value 2 of page 1 of the
-  ** database file.  The cache size is actually the absolute value of
-  ** this memory location.  The sign of meta-value 2 determines the
-  ** synchronous setting.  A negative value means synchronous is off
-  ** and a positive value means synchronous is on.
-  */
-  if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
-    static VdbeOp getCacheSize[] = {
-      { OP_ReadCookie,  0, 2,        0},
-      { OP_AbsValue,    0, 0,        0},
-      { OP_Dup,         0, 0,        0},
-      { OP_Integer,     0, 0,        0},
-      { OP_Ne,          0, 6,        0},
-      { OP_Integer,     MAX_PAGES,0, 0},
-      { OP_ColumnName,  0, 0,        "cache_size"},
-      { OP_Callback,    1, 0,        0},
-    };
-    if( pRight->z==pLeft->z ){
-      sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
-    }else{
-      int addr;
-      int size = atoi(zRight);
-      if( size<0 ) size = -size;
-      sqliteBeginWriteOperation(pParse, 0, 0);
-      sqliteVdbeAddOp(v, OP_Integer, size, 0);
-      sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
-      addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-      sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
-      sqliteVdbeAddOp(v, OP_Negative, 0, 0);
-      sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
-      sqliteEndWriteOperation(pParse);
-      db->cache_size = db->cache_size<0 ? -size : size;
-      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
-    }
-  }else
-
-  /*
-  **  PRAGMA cache_size
-  **  PRAGMA cache_size=N
-  **
-  ** The first form reports the current local setting for the
-  ** page cache size.  The local setting can be different from
-  ** the persistent cache size value that is stored in the database
-  ** file itself.  The value returned is the maximum number of
-  ** pages in the page cache.  The second form sets the local
-  ** page cache size value.  It does not change the persistent
-  ** cache size stored on the disk so the cache size will revert
-  ** to its default value when the database is closed and reopened.
-  ** N should be a positive integer.
-  */
-  if( sqliteStrICmp(zLeft,"cache_size")==0 ){
-    static VdbeOp getCacheSize[] = {
-      { OP_ColumnName,  0, 0,        "cache_size"},
-      { OP_Callback,    1, 0,        0},
-    };
-    if( pRight->z==pLeft->z ){
-      int size = db->cache_size;;
-      if( size<0 ) size = -size;
-      sqliteVdbeAddOp(v, OP_Integer, size, 0);
-      sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
-    }else{
-      int size = atoi(zRight);
-      if( size<0 ) size = -size;
-      if( db->cache_size<0 ) size = -size;
-      db->cache_size = size;
-      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
-    }
-  }else
-
-  /*
-  **  PRAGMA default_synchronous
-  **  PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
-  **
-  ** The first form returns the persistent value of the "synchronous" setting
-  ** that is stored in the database.  This is the synchronous setting that
-  ** is used whenever the database is opened unless overridden by a separate
-  ** "synchronous" pragma.  The second form changes the persistent and the
-  ** local synchronous setting to the value given.
-  **
-  ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
-  ** to make sure data is committed to disk.  Write operations are very fast,
-  ** but a power failure can leave the database in an inconsistent state.
-  ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
-  ** make sure data is being written to disk.  The risk of corruption due to
-  ** a power loss in this mode is negligible but non-zero.  If synchronous
-  ** is FULL, extra fsync()s occur to reduce the risk of corruption to near
-  ** zero, but with a write performance penalty.  The default mode is NORMAL.
-  */
-  if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
-    static VdbeOp getSync[] = {
-      { OP_ColumnName,  0, 0,        "synchronous"},
-      { OP_ReadCookie,  0, 3,        0},
-      { OP_Dup,         0, 0,        0},
-      { OP_If,          0, 0,        0},  /* 3 */
-      { OP_ReadCookie,  0, 2,        0},
-      { OP_Integer,     0, 0,        0},
-      { OP_Lt,          0, 5,        0},
-      { OP_AddImm,      1, 0,        0},
-      { OP_Callback,    1, 0,        0},
-      { OP_Halt,        0, 0,        0},
-      { OP_AddImm,     -1, 0,        0},  /* 10 */
-      { OP_Callback,    1, 0,        0}
-    };
-    if( pRight->z==pLeft->z ){
-      int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
-      sqliteVdbeChangeP2(v, addr+3, addr+10);
-    }else{
-      int addr;
-      int size = db->cache_size;
-      if( size<0 ) size = -size;
-      sqliteBeginWriteOperation(pParse, 0, 0);
-      sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
-      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-      addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
-      sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
-      sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
-      sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
-      db->safety_level = getSafetyLevel(zRight)+1;
-      if( db->safety_level==1 ){
-        sqliteVdbeAddOp(v, OP_Negative, 0, 0);
-        size = -size;
-      }
-      sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
-      sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
-      sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
-      sqliteEndWriteOperation(pParse);
-      db->cache_size = size;
-      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
-      sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
-    }
-  }else
-
-  /*
-  **   PRAGMA synchronous
-  **   PRAGMA synchronous=OFF|ON|NORMAL|FULL
-  **
-  ** Return or set the local value of the synchronous flag.  Changing
-  ** the local value does not make changes to the disk file and the
-  ** default value will be restored the next time the database is
-  ** opened.
-  */
-  if( sqliteStrICmp(zLeft,"synchronous")==0 ){
-    static VdbeOp getSync[] = {
-      { OP_ColumnName,  0, 0,        "synchronous"},
-      { OP_Callback,    1, 0,        0},
-    };
-    if( pRight->z==pLeft->z ){
-      sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
-      sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
-    }else{
-      int size = db->cache_size;
-      if( size<0 ) size = -size;
-      db->safety_level = getSafetyLevel(zRight)+1;
-      if( db->safety_level==1 ) size = -size;
-      db->cache_size = size;
-      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
-      sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
-    if( getBoolean(zRight) ){
-      always_code_trigger_setup = 1;
-    }else{
-      always_code_trigger_setup = 0;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "vdbe_trace")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_VdbeTrace;
-    }else{
-      db->flags &= ~SQLITE_VdbeTrace;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "full_column_names")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_FullColNames;
-    }else{
-      db->flags &= ~SQLITE_FullColNames;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "show_datatypes")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_ReportTypes;
-    }else{
-      db->flags &= ~SQLITE_ReportTypes;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "result_set_details")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_ResultDetails;
-    }else{
-      db->flags &= ~SQLITE_ResultDetails;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "count_changes")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_CountRows;
-    }else{
-      db->flags &= ~SQLITE_CountRows;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "empty_result_callbacks")==0 ){
-    if( getBoolean(zRight) ){
-      db->flags |= SQLITE_NullCallback;
-    }else{
-      db->flags &= ~SQLITE_NullCallback;
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "table_info")==0 ){
-    Table *pTab;
-    pTab = sqliteFindTable(db, zRight, 0);
-    if( pTab ){
-      static VdbeOp tableInfoPreface[] = {
-        { OP_ColumnName,  0, 0,       "cid"},
-        { OP_ColumnName,  1, 0,       "name"},
-        { OP_ColumnName,  2, 0,       "type"},
-        { OP_ColumnName,  3, 0,       "notnull"},
-        { OP_ColumnName,  4, 0,       "dflt_value"},
-      };
-      int i;
-      sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
-      sqliteViewGetColumnNames(pParse, pTab);
-      for(i=0; i<pTab->nCol; i++){
-        sqliteVdbeAddOp(v, OP_Integer, i, 0);
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-        sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zName, P3_STATIC);
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-        sqliteVdbeChangeP3(v, -1, 
-           pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", P3_STATIC);
-        sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-        sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zDflt, P3_STATIC);
-        sqliteVdbeAddOp(v, OP_Callback, 5, 0);
-      }
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "index_info")==0 ){
-    Index *pIdx;
-    Table *pTab;
-    pIdx = sqliteFindIndex(db, zRight, 0);
-    if( pIdx ){
-      static VdbeOp tableInfoPreface[] = {
-        { OP_ColumnName,  0, 0,       "seqno"},
-        { OP_ColumnName,  1, 0,       "cid"},
-        { OP_ColumnName,  2, 0,       "name"},
-      };
-      int i;
-      pTab = pIdx->pTable;
-      sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
-      for(i=0; i<pIdx->nColumn; i++){
-        int cnum = pIdx->aiColumn[i];
-        sqliteVdbeAddOp(v, OP_Integer, i, 0);
-        sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-        assert( pTab->nCol>cnum );
-        sqliteVdbeChangeP3(v, -1, pTab->aCol[cnum].zName, P3_STATIC);
-        sqliteVdbeAddOp(v, OP_Callback, 3, 0);
-      }
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "index_list")==0 ){
-    Index *pIdx;
-    Table *pTab;
-    pTab = sqliteFindTable(db, zRight, 0);
-    if( pTab ){
-      v = sqliteGetVdbe(pParse);
-      pIdx = pTab->pIndex;
-    }
-    if( pTab && pIdx ){
-      int i = 0; 
-      static VdbeOp indexListPreface[] = {
-        { OP_ColumnName,  0, 0,       "seq"},
-        { OP_ColumnName,  1, 0,       "name"},
-        { OP_ColumnName,  2, 0,       "unique"},
-      };
-
-      sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
-      while(pIdx){
-        sqliteVdbeAddOp(v, OP_Integer, i, 0);
-        sqliteVdbeAddOp(v, OP_String, 0, 0);
-        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
-        sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
-        sqliteVdbeAddOp(v, OP_Callback, 3, 0);
-        ++i;
-        pIdx = pIdx->pNext;
-      }
-    }
-  }else
-
-  if( sqliteStrICmp(zLeft, "database_list")==0 ){
-    int i;
-    static VdbeOp indexListPreface[] = {
-      { OP_ColumnName,  0, 0,       "seq"},
-      { OP_ColumnName,  1, 0,       "name"},
-    };
-
-    sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
-    for(i=0; i<db->nDb; i++){
-      if( db->aDb[i].pBt==0 ) continue;
-      assert( db->aDb[i].zName!=0 );
-      sqliteVdbeAddOp(v, OP_Integer, i, 0);
-      sqliteVdbeAddOp(v, OP_String, 0, 0);
-      sqliteVdbeChangeP3(v, -1, db->aDb[i].zName, P3_STATIC);
-      sqliteVdbeAddOp(v, OP_Callback, 2, 0);
-    }
-  }else
-
-#ifndef NDEBUG
-  if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
-    extern void sqliteParserTrace(FILE*, char *);
-    if( getBoolean(zRight) ){
-      sqliteParserTrace(stdout, "parser: ");
-    }else{
-      sqliteParserTrace(0, 0);
-    }
-  }else
-#endif
-
-  if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
-    static VdbeOp checkDb[] = {
-      { OP_SetInsert,   0, 0,        "2"},
-      { OP_Integer,     0, 0,        0},   
-      { OP_OpenRead,    0, 2,        0},
-      { OP_Rewind,      0, 7,        0},
-      { OP_Column,      0, 3,        0},    /* 4 */
-      { OP_SetInsert,   0, 0,        0},
-      { OP_Next,        0, 4,        0},
-      { OP_IntegrityCk, 0, 0,        0},    /* 7 */
-      { OP_ColumnName,  0, 0,        "integrity_check"},
-      { OP_Callback,    1, 0,        0},
-      { OP_SetInsert,   1, 0,        "2"},
-      { OP_Integer,     1, 0,        0},
-      { OP_OpenRead,    1, 2,        0},
-      { OP_Rewind,      1, 17,       0},
-      { OP_Column,      1, 3,        0},    /* 14 */
-      { OP_SetInsert,   1, 0,        0},
-      { OP_Next,        1, 14,       0},
-      { OP_IntegrityCk, 1, 1,        0},    /* 17 */
-      { OP_Callback,    1, 0,        0},
-    };
-    sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
-  }else
-
-  {}
-  sqliteFree(zLeft);
-  sqliteFree(zRight);
-}
-
-/*
-** This routine is called by the parser to process an ATTACH statement:
-**
-**     ATTACH DATABASE filename AS dbname
-**
-** The pFilename and pDbname arguments are the tokens that define the
-** filename and dbname in the ATTACH statement.
-*/
-void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){
-  Db *aNew;
-  int rc, i;
-  char *zFile, *zName;
-  sqlite *db;
-
-  if( pParse->explain ) return;
-  db = pParse->db;
-  if( db->file_format<4 ){
-    sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
-       "older format master database", 0);
-    pParse->rc = SQLITE_ERROR;
-    return;
-  }
-  if( db->nDb>=MAX_ATTACHED+2 ){
-    sqliteErrorMsg(pParse, "too many attached databases - max %d", 
-       MAX_ATTACHED);
-    pParse->rc = SQLITE_ERROR;
-    return;
-  }
-  if( db->aDb==db->aDbStatic ){
-    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
-    if( aNew==0 ) return;
-    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
-  }else{
-    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
-    if( aNew==0 ) return;
-  }
-  db->aDb = aNew;
-  aNew = &db->aDb[db->nDb++];
-  memset(aNew, 0, sizeof(*aNew));
-  sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
-  sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
-  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
-  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
-  
-  zName = 0;
-  sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
-  if( zName==0 ) return;
-  sqliteDequote(zName);
-  for(i=0; i<db->nDb; i++){
-    if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
-      sqliteErrorMsg(pParse, "database %z is already in use", zName);
-      db->nDb--;
-      pParse->rc = SQLITE_ERROR;
-      return;
-    }
-  }
-  aNew->zName = zName;
-  zFile = 0;
-  sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
-  if( zFile==0 ) return;
-  sqliteDequote(zFile);
-  rc = sqliteBtreeOpen(zFile, 0, MAX_PAGES, &aNew->pBt);
-  if( rc ){
-    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
-  }
-  sqliteFree(zFile);
-  db->flags &= ~SQLITE_Initialized;
-  if( pParse->nErr ) return;
-  rc = sqliteInit(pParse->db, &pParse->zErrMsg);
-  if( rc ){
-    sqliteResetInternalSchema(db, 0);
-    pParse->nErr++;
-    pParse->rc = SQLITE_ERROR;
-  }
-}
-
-/*
-** This routine is called by the parser to process a DETACH statement:
-**
-**    DETACH DATABASE dbname
-**
-** The pDbname argument is the name of the database in the DETACH statement.
-*/
-void sqliteDetach(Parse *pParse, Token *pDbname){
-  int i;
-  sqlite *db;
-
-  if( pParse->explain ) return;
-  db = pParse->db;
-  for(i=0; i<db->nDb; i++){
-    if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
-    if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
-    if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
-  }
-  if( i>=db->nDb ){
-    sqliteErrorMsg(pParse, "no such database: %T", pDbname);
-    return;
-  }
-  if( i<2 ){
-    sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
-    return;
-  }
-  sqliteBtreeClose(db->aDb[i].pBt);
-  db->aDb[i].pBt = 0;
-  sqliteResetInternalSchema(db, i);
-  db->nDb--;
-  if( i<db->nDb ){
-    db->aDb[i] = db->aDb[db->nDb];
-    memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
-    sqliteResetInternalSchema(db, i);
-  }
-}
diff --git a/src/copy.c b/src/copy.c
new file mode 100644 (file)
index 0000000..90fe200
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code.  In place of
+** 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.
+**
+*************************************************************************
+** This file contains code used to implement the COPY command.
+**
+** $Id: copy.c,v 1.1 2003/04/06 21:08:24 drh Exp $
+*/
+#include "sqliteInt.h"
+
+/*
+** The COPY command is for compatibility with PostgreSQL and specificially
+** for the ability to read the output of pg_dump.  The format is as
+** follows:
+**
+**    COPY table FROM file [USING DELIMITERS string]
+**
+** "table" is an existing table name.  We will read lines of code from
+** file to fill this table with data.  File might be "stdin".  The optional
+** delimiter string identifies the field separators.  The default is a tab.
+*/
+void sqliteCopy(
+  Parse *pParse,       /* The parser context */
+  SrcList *pTableName, /* The name of the table into which we will insert */
+  Token *pFilename,    /* The file from which to obtain information */
+  Token *pDelimiter,   /* Use this as the field delimiter */
+  int onError          /* What to do if a constraint fails */
+){
+  Table *pTab;
+  int i;
+  Vdbe *v;
+  int addr, end;
+  Index *pIdx;
+  char *zFile = 0;
+  sqlite *db = pParse->db;
+
+
+  if( sqlite_malloc_failed  ) goto copy_cleanup;
+  assert( pTableName->nSrc==1 );
+  pTab = sqliteSrcListLookup(pParse, pTableName);
+  if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ) goto copy_cleanup;
+  zFile = sqliteStrNDup(pFilename->z, pFilename->n);
+  sqliteDequote(zFile);
+  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
+      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
+    goto copy_cleanup;
+  }
+  v = sqliteGetVdbe(pParse);
+  if( v ){
+    sqliteBeginWriteOperation(pParse, 1, pTab->iDb==1);
+    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
+    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
+    sqliteVdbeDequoteP3(v, addr);
+    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+    sqliteVdbeAddOp(v, OP_OpenWrite, 0, pTab->tnum);
+    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
+    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+      assert( pIdx->iDb==1 || pIdx->iDb==pTab->iDb );
+      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
+      sqliteVdbeAddOp(v, OP_OpenWrite, i, pIdx->tnum);
+      sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
+    }
+    if( db->flags & SQLITE_CountRows ){
+      sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
+    }
+    end = sqliteVdbeMakeLabel(v);
+    addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
+    if( pDelimiter ){
+      sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
+      sqliteVdbeDequoteP3(v, addr);
+    }else{
+      sqliteVdbeChangeP3(v, addr, "\t", 1);
+    }
+    if( pTab->iPKey>=0 ){
+      sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
+      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
+    }else{
+      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
+    }
+    for(i=0; i<pTab->nCol; i++){
+      if( i==pTab->iPKey ){
+        /* The integer primary key column is filled with NULL since its
+        ** value is always pulled from the record number */
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+      }else{
+        sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
+      }
+    }
+    sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, 0, 0, onError, addr);
+    sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0);
+    if( (db->flags & SQLITE_CountRows)!=0 ){
+      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);  /* Increment row count */
+    }
+    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
+    sqliteVdbeResolveLabel(v, end);
+    sqliteVdbeAddOp(v, OP_Noop, 0, 0);
+    sqliteEndWriteOperation(pParse);
+    if( db->flags & SQLITE_CountRows ){
+      sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
+      sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
+      sqliteVdbeAddOp(v, OP_Callback, 1, 0);
+    }
+  }
+  
+copy_cleanup:
+  sqliteSrcListDelete(pTableName);
+  sqliteFree(zFile);
+  return;
+}
diff --git a/src/pragma.c b/src/pragma.c
new file mode 100644 (file)
index 0000000..f92d559
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code.  In place of
+** 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.
+**
+*************************************************************************
+** This file contains code used to implement the PRAGMA command.
+**
+** $Id: pragma.c,v 1.1 2003/04/06 21:08:24 drh Exp $
+*/
+#include "sqliteInt.h"
+
+/*
+** Interpret the given string as a boolean value.
+*/
+static int getBoolean(char *z){
+  static char *azTrue[] = { "yes", "on", "true" };
+  int i;
+  if( z[0]==0 ) return 0;
+  if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
+    return atoi(z);
+  }
+  for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
+    if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
+  }
+  return 0;
+}
+
+/*
+** Interpret the given string as a safety level.  Return 0 for OFF,
+** 1 for ON or NORMAL and 2 for FULL.
+**
+** Note that the values returned are one less that the values that
+** should be passed into sqliteBtreeSetSafetyLevel().  The is done
+** to support legacy SQL code.  The safety level used to be boolean
+** and older scripts may have used numbers 0 for OFF and 1 for ON.
+*/
+static int getSafetyLevel(char *z){
+  static const struct {
+    const char *zWord;
+    int val;
+  } aKey[] = {
+    { "no",    0 },
+    { "off",   0 },
+    { "false", 0 },
+    { "yes",   1 },
+    { "on",    1 },
+    { "true",  1 },
+    { "full",  2 },
+  };
+  int i;
+  if( z[0]==0 ) return 1;
+  if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
+    return atoi(z);
+  }
+  for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
+    if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
+  }
+  return 1;
+}
+
+/*
+** Process a pragma statement.  
+**
+** Pragmas are of this form:
+**
+**      PRAGMA id = value
+**
+** The identifier might also be a string.  The value is a string, and
+** identifier, or a number.  If minusFlag is true, then the value is
+** a number that was preceded by a minus sign.
+*/
+void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
+  char *zLeft = 0;
+  char *zRight = 0;
+  sqlite *db = pParse->db;
+  Vdbe *v = sqliteGetVdbe(pParse);
+  if( v==0 ) return;
+
+  zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
+  sqliteDequote(zLeft);
+  if( minusFlag ){
+    zRight = 0;
+    sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
+  }else{
+    zRight = sqliteStrNDup(pRight->z, pRight->n);
+    sqliteDequote(zRight);
+  }
+  if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight) ){
+    sqliteFree(zLeft);
+    sqliteFree(zRight);
+    return;
+  }
+  /*
+  **  PRAGMA default_cache_size
+  **  PRAGMA default_cache_size=N
+  **
+  ** The first form reports the current persistent setting for the
+  ** page cache size.  The value returned is the maximum number of
+  ** pages in the page cache.  The second form sets both the current
+  ** page cache size value and the persistent page cache size value
+  ** stored in the database file.
+  **
+  ** The default cache size is stored in meta-value 2 of page 1 of the
+  ** database file.  The cache size is actually the absolute value of
+  ** this memory location.  The sign of meta-value 2 determines the
+  ** synchronous setting.  A negative value means synchronous is off
+  ** and a positive value means synchronous is on.
+  */
+  if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
+    static VdbeOp getCacheSize[] = {
+      { OP_ReadCookie,  0, 2,        0},
+      { OP_AbsValue,    0, 0,        0},
+      { OP_Dup,         0, 0,        0},
+      { OP_Integer,     0, 0,        0},
+      { OP_Ne,          0, 6,        0},
+      { OP_Integer,     MAX_PAGES,0, 0},
+      { OP_ColumnName,  0, 0,        "cache_size"},
+      { OP_Callback,    1, 0,        0},
+    };
+    if( pRight->z==pLeft->z ){
+      sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
+    }else{
+      int addr;
+      int size = atoi(zRight);
+      if( size<0 ) size = -size;
+      sqliteBeginWriteOperation(pParse, 0, 0);
+      sqliteVdbeAddOp(v, OP_Integer, size, 0);
+      sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
+      addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
+      sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
+      sqliteVdbeAddOp(v, OP_Negative, 0, 0);
+      sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
+      sqliteEndWriteOperation(pParse);
+      db->cache_size = db->cache_size<0 ? -size : size;
+      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
+    }
+  }else
+
+  /*
+  **  PRAGMA cache_size
+  **  PRAGMA cache_size=N
+  **
+  ** The first form reports the current local setting for the
+  ** page cache size.  The local setting can be different from
+  ** the persistent cache size value that is stored in the database
+  ** file itself.  The value returned is the maximum number of
+  ** pages in the page cache.  The second form sets the local
+  ** page cache size value.  It does not change the persistent
+  ** cache size stored on the disk so the cache size will revert
+  ** to its default value when the database is closed and reopened.
+  ** N should be a positive integer.
+  */
+  if( sqliteStrICmp(zLeft,"cache_size")==0 ){
+    static VdbeOp getCacheSize[] = {
+      { OP_ColumnName,  0, 0,        "cache_size"},
+      { OP_Callback,    1, 0,        0},
+    };
+    if( pRight->z==pLeft->z ){
+      int size = db->cache_size;;
+      if( size<0 ) size = -size;
+      sqliteVdbeAddOp(v, OP_Integer, size, 0);
+      sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
+    }else{
+      int size = atoi(zRight);
+      if( size<0 ) size = -size;
+      if( db->cache_size<0 ) size = -size;
+      db->cache_size = size;
+      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
+    }
+  }else
+
+  /*
+  **  PRAGMA default_synchronous
+  **  PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
+  **
+  ** The first form returns the persistent value of the "synchronous" setting
+  ** that is stored in the database.  This is the synchronous setting that
+  ** is used whenever the database is opened unless overridden by a separate
+  ** "synchronous" pragma.  The second form changes the persistent and the
+  ** local synchronous setting to the value given.
+  **
+  ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
+  ** to make sure data is committed to disk.  Write operations are very fast,
+  ** but a power failure can leave the database in an inconsistent state.
+  ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
+  ** make sure data is being written to disk.  The risk of corruption due to
+  ** a power loss in this mode is negligible but non-zero.  If synchronous
+  ** is FULL, extra fsync()s occur to reduce the risk of corruption to near
+  ** zero, but with a write performance penalty.  The default mode is NORMAL.
+  */
+  if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
+    static VdbeOp getSync[] = {
+      { OP_ColumnName,  0, 0,        "synchronous"},
+      { OP_ReadCookie,  0, 3,        0},
+      { OP_Dup,         0, 0,        0},
+      { OP_If,          0, 0,        0},  /* 3 */
+      { OP_ReadCookie,  0, 2,        0},
+      { OP_Integer,     0, 0,        0},
+      { OP_Lt,          0, 5,        0},
+      { OP_AddImm,      1, 0,        0},
+      { OP_Callback,    1, 0,        0},
+      { OP_Halt,        0, 0,        0},
+      { OP_AddImm,     -1, 0,        0},  /* 10 */
+      { OP_Callback,    1, 0,        0}
+    };
+    if( pRight->z==pLeft->z ){
+      int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
+      sqliteVdbeChangeP2(v, addr+3, addr+10);
+    }else{
+      int addr;
+      int size = db->cache_size;
+      if( size<0 ) size = -size;
+      sqliteBeginWriteOperation(pParse, 0, 0);
+      sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
+      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
+      addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
+      sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
+      sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
+      sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
+      db->safety_level = getSafetyLevel(zRight)+1;
+      if( db->safety_level==1 ){
+        sqliteVdbeAddOp(v, OP_Negative, 0, 0);
+        size = -size;
+      }
+      sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
+      sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
+      sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
+      sqliteEndWriteOperation(pParse);
+      db->cache_size = size;
+      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
+      sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
+    }
+  }else
+
+  /*
+  **   PRAGMA synchronous
+  **   PRAGMA synchronous=OFF|ON|NORMAL|FULL
+  **
+  ** Return or set the local value of the synchronous flag.  Changing
+  ** the local value does not make changes to the disk file and the
+  ** default value will be restored the next time the database is
+  ** opened.
+  */
+  if( sqliteStrICmp(zLeft,"synchronous")==0 ){
+    static VdbeOp getSync[] = {
+      { OP_ColumnName,  0, 0,        "synchronous"},
+      { OP_Callback,    1, 0,        0},
+    };
+    if( pRight->z==pLeft->z ){
+      sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
+      sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
+    }else{
+      int size = db->cache_size;
+      if( size<0 ) size = -size;
+      db->safety_level = getSafetyLevel(zRight)+1;
+      if( db->safety_level==1 ) size = -size;
+      db->cache_size = size;
+      sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
+      sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
+    if( getBoolean(zRight) ){
+      always_code_trigger_setup = 1;
+    }else{
+      always_code_trigger_setup = 0;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "vdbe_trace")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_VdbeTrace;
+    }else{
+      db->flags &= ~SQLITE_VdbeTrace;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "full_column_names")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_FullColNames;
+    }else{
+      db->flags &= ~SQLITE_FullColNames;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "show_datatypes")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_ReportTypes;
+    }else{
+      db->flags &= ~SQLITE_ReportTypes;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "result_set_details")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_ResultDetails;
+    }else{
+      db->flags &= ~SQLITE_ResultDetails;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "count_changes")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_CountRows;
+    }else{
+      db->flags &= ~SQLITE_CountRows;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "empty_result_callbacks")==0 ){
+    if( getBoolean(zRight) ){
+      db->flags |= SQLITE_NullCallback;
+    }else{
+      db->flags &= ~SQLITE_NullCallback;
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "table_info")==0 ){
+    Table *pTab;
+    pTab = sqliteFindTable(db, zRight, 0);
+    if( pTab ){
+      static VdbeOp tableInfoPreface[] = {
+        { OP_ColumnName,  0, 0,       "cid"},
+        { OP_ColumnName,  1, 0,       "name"},
+        { OP_ColumnName,  2, 0,       "type"},
+        { OP_ColumnName,  3, 0,       "notnull"},
+        { OP_ColumnName,  4, 0,       "dflt_value"},
+      };
+      int i;
+      sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
+      sqliteViewGetColumnNames(pParse, pTab);
+      for(i=0; i<pTab->nCol; i++){
+        sqliteVdbeAddOp(v, OP_Integer, i, 0);
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+        sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zName, P3_STATIC);
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+        sqliteVdbeChangeP3(v, -1, 
+           pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", P3_STATIC);
+        sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+        sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zDflt, P3_STATIC);
+        sqliteVdbeAddOp(v, OP_Callback, 5, 0);
+      }
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "index_info")==0 ){
+    Index *pIdx;
+    Table *pTab;
+    pIdx = sqliteFindIndex(db, zRight, 0);
+    if( pIdx ){
+      static VdbeOp tableInfoPreface[] = {
+        { OP_ColumnName,  0, 0,       "seqno"},
+        { OP_ColumnName,  1, 0,       "cid"},
+        { OP_ColumnName,  2, 0,       "name"},
+      };
+      int i;
+      pTab = pIdx->pTable;
+      sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
+      for(i=0; i<pIdx->nColumn; i++){
+        int cnum = pIdx->aiColumn[i];
+        sqliteVdbeAddOp(v, OP_Integer, i, 0);
+        sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+        assert( pTab->nCol>cnum );
+        sqliteVdbeChangeP3(v, -1, pTab->aCol[cnum].zName, P3_STATIC);
+        sqliteVdbeAddOp(v, OP_Callback, 3, 0);
+      }
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "index_list")==0 ){
+    Index *pIdx;
+    Table *pTab;
+    pTab = sqliteFindTable(db, zRight, 0);
+    if( pTab ){
+      v = sqliteGetVdbe(pParse);
+      pIdx = pTab->pIndex;
+    }
+    if( pTab && pIdx ){
+      int i = 0; 
+      static VdbeOp indexListPreface[] = {
+        { OP_ColumnName,  0, 0,       "seq"},
+        { OP_ColumnName,  1, 0,       "name"},
+        { OP_ColumnName,  2, 0,       "unique"},
+      };
+
+      sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
+      while(pIdx){
+        sqliteVdbeAddOp(v, OP_Integer, i, 0);
+        sqliteVdbeAddOp(v, OP_String, 0, 0);
+        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
+        sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
+        sqliteVdbeAddOp(v, OP_Callback, 3, 0);
+        ++i;
+        pIdx = pIdx->pNext;
+      }
+    }
+  }else
+
+  if( sqliteStrICmp(zLeft, "database_list")==0 ){
+    int i;
+    static VdbeOp indexListPreface[] = {
+      { OP_ColumnName,  0, 0,       "seq"},
+      { OP_ColumnName,  1, 0,       "name"},
+    };
+
+    sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
+    for(i=0; i<db->nDb; i++){
+      if( db->aDb[i].pBt==0 ) continue;
+      assert( db->aDb[i].zName!=0 );
+      sqliteVdbeAddOp(v, OP_Integer, i, 0);
+      sqliteVdbeAddOp(v, OP_String, 0, 0);
+      sqliteVdbeChangeP3(v, -1, db->aDb[i].zName, P3_STATIC);
+      sqliteVdbeAddOp(v, OP_Callback, 2, 0);
+    }
+  }else
+
+#ifndef NDEBUG
+  if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
+    extern void sqliteParserTrace(FILE*, char *);
+    if( getBoolean(zRight) ){
+      sqliteParserTrace(stdout, "parser: ");
+    }else{
+      sqliteParserTrace(0, 0);
+    }
+  }else
+#endif
+
+  if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
+    static VdbeOp checkDb[] = {
+      { OP_SetInsert,   0, 0,        "2"},
+      { OP_Integer,     0, 0,        0},   
+      { OP_OpenRead,    0, 2,        0},
+      { OP_Rewind,      0, 7,        0},
+      { OP_Column,      0, 3,        0},    /* 4 */
+      { OP_SetInsert,   0, 0,        0},
+      { OP_Next,        0, 4,        0},
+      { OP_IntegrityCk, 0, 0,        0},    /* 7 */
+      { OP_ColumnName,  0, 0,        "integrity_check"},
+      { OP_Callback,    1, 0,        0},
+      { OP_SetInsert,   1, 0,        "2"},
+      { OP_Integer,     1, 0,        0},
+      { OP_OpenRead,    1, 2,        0},
+      { OP_Rewind,      1, 17,       0},
+      { OP_Column,      1, 3,        0},    /* 14 */
+      { OP_SetInsert,   1, 0,        0},
+      { OP_Next,        1, 14,       0},
+      { OP_IntegrityCk, 1, 1,        0},    /* 17 */
+      { OP_Callback,    1, 0,        0},
+    };
+    sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
+  }else
+
+  {}
+  sqliteFree(zLeft);
+  sqliteFree(zRight);
+}
diff --git a/src/vacuum.c b/src/vacuum.c
new file mode 100644 (file)
index 0000000..cb8b404
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+** 2003 April 6
+**
+** The author disclaims copyright to this source code.  In place of
+** 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.
+**
+*************************************************************************
+** This file contains code used to implement the VACUUM command.
+**
+** Most of the code in this file may be omitted by defining the
+** SQLITE_OMIT_VACUUM macro.
+**
+** $Id: vacuum.c,v 1.1 2003/04/06 21:08:24 drh Exp $
+*/
+#include "sqliteInt.h"
+
+
+/*
+** The non-standard VACUUM command is used to clean up the database,
+** collapse free space, etc.  It is modelled after the VACUUM command
+** in PostgreSQL.
+**
+** In version 1.0.x of SQLite, the VACUUM command would call
+** gdbm_reorganize() on all the database tables.  But beginning
+** with 2.0.0, SQLite no longer uses GDBM so this command has
+** become a no-op.
+*/
+void sqliteVacuum(Parse *pParse, Token *pTableName){
+#ifndef SQLITE_OMIT_VACUUM
+  /* Do nothing */
+#endif
+}