$(TOP)/src/expr.c \
$(TOP)/src/insert.c \
$(TOP)/src/main.c \
+ $(TOP)/src/os.c \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
-C Version\sto\s2.0.0\s(CVS\s251)
-D 2001-09-16T13:36:41
-F Makefile.in 81e1c96b0d148042d851b40cbd3e26ecc5472aa6
+C Add\sa\snew\scolumn\sin\sthe\sSQLITE_MASTER\stable\sto\srecord\sthe\sroot\spage\nnumber\sof\sprimary\skey\sindices.\s(CVS\s252)
+D 2001-09-17T20:25:58
+F Makefile.in a7053596881af6f2590a816ad4eb8fbbf20724a7
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 3861a21803fcd9eb92a403027b0da2bb7add4de1
F configure aad857a97ca28a584228869186eb4cd7dbebbb3a x
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c 39da79b5a656870aa3ab72d40374fb38bd1bd12d
F src/btree.h fcb08daab59fd81023204ac71955233e218443c2
-F src/build.c c311b8d11bfd44a9b260c1a53946e2e091138e23
+F src/build.c 072d6cf5b894c47d3fb8c11580eaa1a24528bca8
F src/delete.c ca7ca9bf8b613730821c4a755030d1a020b5e067
F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d
F src/insert.c b34860ea58525754f18bde652f74161295ca2455
-F src/main.c 1523c790c243f886271e0c45eaa487951793cd46
+F src/main.c 71ca839b90869c8c13db52fd08b0d0e80dae3288
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
+F src/os.c 2e0daeca8a8c75f122d41f894698f5e1b258b69c
+F src/os.h 3b21772e76df0f3998c5a968a2a0d23b9d4551fe
F src/pager.c 3871a5d34808b703e2d8ae2799fda208aa204051
F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 2bcf47bb8e6afd8bc10aebd555fa07b73905bee4
F src/shell.c 8e573138074e0b9526fca59b3eac22bdf18ecc03
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 689401a6cfb4c2344e67d80fa6bb0d74c87e6e31
-F src/sqliteInt.h 2e118ca917aa1b91932f9b9b6f36128218c73963
+F src/sqliteInt.h 667126497697d58a114d9db492f38c99eadb36d7
F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac
F src/tclsqlite.c 04a35d04f06046acc3944121dc6c36717f7f36d5
F src/test1.c 3892caa5372789a6d17329dd595724e1f06cb6de
F test/expr.test b3475005ea19d53bf8c4573fb6e4a4498be5b434
F test/func.test dfee65686b8ba06071c2f007243a25c96ce82cf2
F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
-F test/index.test 9a03f1944916b0583486f87c60571f2dee2b5d29
+F test/index.test e43e952b482c2afe938f1f31b71e2b33d43893a9
F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
F test/insert2.test 252d7130d8cc20f649b31a4f503cd87e660abda8
F test/lock.test 5b4d969ab92c88f8dc10d1b870a2e5fe51ee7f5f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
-P 4e926efe2b59adfec4086eb1d2ba830238facb4c
-R b664d11dd53bb094e12afd54030b7627
+P c67f6db681784f8511ccf208cde1c29d9ee73742
+R ec078dd1e4ad61f2004b7bba1a6425b5
U drh
-Z ae4e84a6e126186214dee2d7ef388846
+Z 211dfb1506c70a3bba4b90be9db7543f
-c67f6db681784f8511ccf208cde1c29d9ee73742
\ No newline at end of file
+602ea4f9f641070592c788ce22859b849739b42e
\ No newline at end of file
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.36 2001/09/16 00:13:26 drh Exp $
+** $Id: build.c,v 1.37 2001/09/17 20:25:58 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* If the initFlag is 1 it means we are reading the SQL off the
** "sqlite_master" table on the disk. So do not write to the disk
- ** again. Extract the table number from the pParse->newTnum field.
+ ** again. Extract the root page number for the table from the
+ ** pParse->newTnum field. (The page number should have been put
+ ** there by the sqliteOpenCb routine.) If the table has a primary
+ ** key, the root page of the index associated with the primary key
+ ** should be in pParse->newKnum.
*/
if( pParse->initFlag ){
p->tnum = pParse->newTnum;
+ if( p->pIndex ){
+ p->pIndex->tnum = pParse->newKnum;
+ }
}
- /* If not initializing, then create the table on disk.
+ /* If not initializing, then create a record for the new table
+ ** in the SQLITE_MASTER table of the database.
*/
if( !pParse->initFlag ){
- static VdbeOp addTable[] = {
- { OP_Open, 0, 2, MASTER_NAME},
- { OP_NewRecno, 0, 0, 0},
- { OP_String, 0, 0, "table" },
- { OP_String, 0, 0, 0}, /* 3 */
- { OP_CreateTable, 0, 0, 0},
- { OP_String, 0, 0, 0}, /* 5 */
- { OP_String, 0, 0, 0}, /* 6 */
- { OP_MakeRecord, 5, 0, 0},
- { OP_Put, 0, 0, 0},
- { OP_SetCookie, 0, 0, 0}, /* 9 */
- };
int n, base;
Vdbe *v;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;
- base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
- sqliteVdbeChangeP3(v, base+3, p->zName, 0);
+ sqliteVdbeAddOp(v, OP_Open, 0, 2, MASTER_NAME, 0);
+ sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
+ sqliteVdbeAddOp(v, OP_String, 0, 0, "table", 0);
+ sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
+ sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
+ sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0);
sqliteVdbeTableRootAddr(v, &p->tnum);
- sqliteVdbeChangeP3(v, base+5, p->zName, 0);
- sqliteVdbeChangeP3(v, base+6, pParse->sFirstToken.z, n);
- changeCookie(db);
- sqliteVdbeChangeP1(v, base+9, db->next_cookie);
- sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
if( p->pIndex ){
/* If the table has a primary key, create an index in the database
- ** for that key. */
+ ** for that key and record the root page of the index in the "knum"
+ ** column of of the SQLITE_MASTER table.
+ */
Index *pIndex = p->pIndex;
assert( pIndex->pNext==0 );
assert( pIndex->tnum==0 );
sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0),
sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
+ }else{
+ /* If the table does not have a primary key, the "knum" column is
+ ** fill with a NULL value.
+ */
+ sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
}
+ base = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0);
+ sqliteVdbeChangeP3(v, base, pParse->sFirstToken.z, n);
+ sqliteVdbeAddOp(v, OP_MakeRecord, 6, 0, 0, 0);
+ sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
+ changeCookie(db);
+ sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
+ sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
}
{ OP_String, 0, 0, 0}, /* 2 */
{ OP_Next, 0, ADDR(9), 0}, /* 3 */
{ OP_Dup, 0, 0, 0},
- { OP_Column, 0, 3, 0},
+ { OP_Column, 0, 2, 0},
{ OP_Ne, 0, ADDR(3), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Goto, 0, ADDR(3), 0},
** Find the table that is to be indexed. Return early if not found.
*/
if( pTable!=0 ){
+ assert( pName!=0 );
pTab = sqliteTableFromToken(pParse, pTable);
}else{
+ assert( pName==0 );
pTab = pParse->pNewTable;
}
if( pTab==0 || pParse->nErr ) goto exit_create_index;
/*
** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
+ ** index or table with the same name. If pName==0 it means that we are
+ ** dealing with a primary key, which has no name, so this step can be
+ ** skipped.
*/
if( pName ){
zName = sqliteTableNameFromToken(pName);
+ if( zName==0 ) goto exit_create_index;
+ if( sqliteFindIndex(db, zName) ){
+ sqliteSetString(&pParse->zErrMsg, "index ", zName,
+ " already exists", 0);
+ pParse->nErr++;
+ goto exit_create_index;
+ }
+ if( sqliteFindTable(db, zName) ){
+ sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
+ zName, 0);
+ pParse->nErr++;
+ goto exit_create_index;
+ }
}else{
zName = 0;
- sqliteSetString(&zName, pTab->zName, "__primary_key", 0);
- }
- if( zName==0 ) goto exit_create_index;
- if( sqliteFindIndex(db, zName) ){
- sqliteSetString(&pParse->zErrMsg, "index ", zName,
- " already exists", 0);
- pParse->nErr++;
- goto exit_create_index;
- }
- if( sqliteFindTable(db, zName) ){
- sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
- zName, 0);
- pParse->nErr++;
- goto exit_create_index;
+ sqliteSetString(&zName, pTab->zName, " (primary key)", 0);
+ if( zName==0 ) goto exit_create_index;
}
/* If pList==0, it means this routine was called to make a primary
}
/* Link the new Index structure to its table and to the other
- ** in-memory database structures.
+ ** in-memory database structures. Note that primary key indices
+ ** do not appear in the index hash table.
*/
if( pParse->explain==0 ){
- h = sqliteHashNoCase(pIndex->zName, 0) % N_HASH;
- pIndex->pHash = db->apIdxHash[h];
- db->apIdxHash[h] = pIndex;
+ if( pName!=0 ){
+ h = sqliteHashNoCase(pIndex->zName, 0) % N_HASH;
+ pIndex->pHash = db->apIdxHash[h];
+ db->apIdxHash[h] = pIndex;
+ }
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
db->flags |= SQLITE_InternChanges;
{ OP_NewRecno, 2, 0, 0},
{ OP_String, 0, 0, "index"},
{ OP_String, 0, 0, 0}, /* 3 */
+ { OP_String, 0, 0, 0}, /* 4 */
{ OP_CreateIndex, 1, 0, 0},
{ OP_Dup, 0, 0, 0},
- { OP_Open, 1, 0, 0}, /* 6 */
- { OP_String, 0, 0, 0}, /* 7 */
- { OP_String, 0, 0, 0}, /* 8 */
- { OP_MakeRecord, 5, 0, 0},
+ { OP_Open, 1, 0, 0}, /* 7 */
+ { OP_Null, 0, 0, 0},
+ { OP_String, 0, 0, 0}, /* 9 */
+ { OP_MakeRecord, 6, 0, 0},
{ OP_Put, 2, 0, 0},
- { OP_SetCookie, 0, 0, 0}, /* 11 */
+ { OP_SetCookie, 0, 0, 0}, /* 12 */
{ OP_Close, 2, 0, 0},
};
int n;
n = (int)pEnd->z - (int)pStart->z + 1;
base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
+ sqliteVdbeChangeP3(v, base+4, pTab->zName, 0);
sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
- sqliteVdbeChangeP3(v, base+6, pIndex->zName, 0);
- sqliteVdbeChangeP3(v, base+7, pTab->zName, 0);
- sqliteVdbeChangeP3(v, base+8, pStart->z, n);
+ sqliteVdbeChangeP3(v, base+7, pIndex->zName, 0);
+ sqliteVdbeChangeP3(v, base+9, pStart->z, n);
changeCookie(db);
- sqliteVdbeChangeP1(v, base+11, db->next_cookie);
+ sqliteVdbeChangeP1(v, base+12, db->next_cookie);
}
sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
lbl1 = sqliteVdbeMakeLabel(v);
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.37 2001/09/16 00:13:27 drh Exp $
+** $Id: main.c,v 1.38 2001/09/17 20:25:58 drh Exp $
*/
#include "sqliteInt.h"
#if defined(HAVE_USLEEP) && HAVE_USLEEP
** database. Each callback contains the following information:
**
** argv[0] = "meta" or "table" or "index"
-** argv[1] = table or index name
-** argv[2] = root page number for table or index
-** argv[3] = SQL create statement for the table or index
+** argv[1] = table or index name or meta statement type.
+** argv[2] = root page number for table or index. NULL for meta.
+** argv[3] = root page number of primary key for tables or NULL.
+** argv[4] = SQL create statement for the table or index
**
*/
static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
Parse sParse;
int nErr = 0;
- assert( argc==4 );
+/* TODO: Do some validity checks on all fields. In particular,
+** make sure fields do not contain NULLs. */
+
+ assert( argc==5 );
switch( argv[0][0] ){
case 'm': { /* Meta information */
if( strcmp(argv[1],"file-format")==0 ){
- db->file_format = atoi(argv[3]);
+ db->file_format = atoi(argv[4]);
}else if( strcmp(argv[1],"schema-cookie")==0 ){
- db->schema_cookie = atoi(argv[3]);
+ db->schema_cookie = atoi(argv[4]);
db->next_cookie = db->schema_cookie;
}
break;
sParse.db = db;
sParse.initFlag = 1;
sParse.newTnum = atoi(argv[2]);
- nErr = sqliteRunParser(&sParse, argv[3], 0);
+ sParse.newKnum = argv[3] ? atoi(argv[3]) : 0;
+ nErr = sqliteRunParser(&sParse, argv[4], 0);
break;
}
default: {
"CREATE TABLE " MASTER_NAME " (\n"
" type text,\n"
" name text,\n"
- " tnum integer,\n"
" tbl_name text,\n"
+ " tnum integer,\n"
+ " knum integer,\n"
" sql text\n"
")"
;
** CREATE TABLE sqlite_master (
** type text, -- Either "table" or "index" or "meta"
** name text, -- Name of table or index
- ** tnum integer, -- The integer page number of root page
** tbl_name text, -- Associated table
+ ** tnum integer, -- The integer page number of root page
+ ** knum integer, -- Root page of primary key, or NULL
** sql text -- The CREATE statement for this object
** );
**
static VdbeOp initProg[] = {
{ OP_Open, 0, 2, 0},
{ OP_Rewind, 0, 0, 0},
- { OP_Next, 0, 12, 0}, /* 2 */
+ { OP_Next, 0, 13, 0}, /* 2 */
{ OP_Column, 0, 0, 0},
{ OP_String, 0, 0, "meta"},
{ OP_Ne, 0, 2, 0},
{ OP_Column, 0, 0, 0},
{ OP_Column, 0, 1, 0},
- { OP_Column, 0, 2, 0},
- { OP_Column, 0, 4, 0},
- { OP_Callback, 4, 0, 0},
+ { OP_Column, 0, 3, 0},
+ { OP_Null, 0, 0, 0},
+ { OP_Column, 0, 5, 0},
+ { OP_Callback, 5, 0, 0},
{ OP_Goto, 0, 2, 0},
- { OP_Rewind, 0, 0, 0}, /* 12 */
- { OP_Next, 0, 23, 0}, /* 13 */
+ { OP_Rewind, 0, 0, 0}, /* 13 */
+ { OP_Next, 0, 25, 0}, /* 14 */
{ OP_Column, 0, 0, 0},
{ OP_String, 0, 0, "table"},
- { OP_Ne, 0, 13, 0},
+ { OP_Ne, 0, 14, 0},
{ OP_Column, 0, 0, 0},
{ OP_Column, 0, 1, 0},
- { OP_Column, 0, 2, 0},
+ { OP_Column, 0, 3, 0},
{ OP_Column, 0, 4, 0},
- { OP_Callback, 4, 0, 0},
- { OP_Goto, 0, 13, 0},
- { OP_Rewind, 0, 0, 0}, /* 23 */
- { OP_Next, 0, 34, 0}, /* 24 */
+ { OP_Column, 0, 5, 0},
+ { OP_Callback, 5, 0, 0},
+ { OP_Goto, 0, 14, 0},
+ { OP_Rewind, 0, 0, 0}, /* 25 */
+ { OP_Next, 0, 37, 0}, /* 26 */
{ OP_Column, 0, 0, 0},
{ OP_String, 0, 0, "index"},
- { OP_Ne, 0, 24, 0},
+ { OP_Ne, 0, 26, 0},
{ OP_Column, 0, 0, 0},
{ OP_Column, 0, 1, 0},
- { OP_Column, 0, 2, 0},
- { OP_Column, 0, 4, 0},
- { OP_Callback, 4, 0, 0},
- { OP_Goto, 0, 24, 0},
- { OP_String, 0, 0, "meta"}, /* 34 */
+ { OP_Column, 0, 3, 0},
+ { OP_Null, 0, 0, 0},
+ { OP_Column, 0, 5, 0},
+ { OP_Callback, 5, 0, 0},
+ { OP_Goto, 0, 26, 0},
+ { OP_String, 0, 0, "meta"}, /* 37 */
{ OP_String, 0, 0, "schema-cookie"},
- { OP_String, 0, 0, ""},
+ { OP_Null, 0, 0, 0},
+ { OP_Null, 0, 0, 0},
{ OP_ReadCookie,0,0, 0},
- { OP_Callback, 4, 0, 0},
+ { OP_Callback, 5, 0, 0},
{ OP_Close, 0, 0, 0},
{ OP_Halt, 0, 0, 0},
};
}
if( rc==SQLITE_OK ){
Table *pTab;
- char *azArg[5];
+ char *azArg[6];
azArg[0] = "table";
azArg[1] = MASTER_NAME;
azArg[2] = "2";
- azArg[3] = master_schema;
- azArg[4] = 0;
- sqliteOpenCb(db, 4, azArg, 0);
+ azArg[3] = 0;
+ azArg[4] = master_schema;
+ azArg[5] = 0;
+ sqliteOpenCb(db, 5, azArg, 0);
pTab = sqliteFindTable(db, MASTER_NAME);
if( pTab ){
pTab->readOnly = 1;
--- /dev/null
+/*
+** 2001 September 16
+**
+** 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 that is specific to particular operating
+** systems. The purpose of this file is to provide a uniform abstract
+** on which the rest of SQLite can operate.
+*/
+#include "sqliteInt.h"
+#include "os.h"
+
+#if OS_UNIX
+# include <fcntl.h>
+# include <sys/stat.h>
+# include <unistd.h>
+# include <time.h>
+#endif
+#if OS_WIN
+# include <winbase.h>
+#endif
+
+
+/*
+** Attempt to open a file for both reading and writing. If that
+** fails, try opening it read-only. If the file does not exist,
+** try to create it.
+**
+** On success, a handle for the open file is written to *pResult
+** and *pReadonly is set to 0 if the file was opened for reading and
+** writing or 1 if the file was opened read-only. The function returns
+** SQLITE_OK.
+**
+** On failure, the function returns SQLITE_CANTOPEN and leaves
+** *pResulst and *pReadonly unchanged.
+*/
+int sqliteOsOpenReadWrite(char *zFilename, OsFile *pResult, int *pReadonly){
+#if OS_UNIX
+ int fd = open(zFilename, O_RDWR|O_CREAT, 0644);
+ if( fd<0 ){
+ fd = open(zFilename, O_RDONLY);
+ if( fd<0 ){
+ return SQLITE_CANTOPEN;
+ }
+ *pReadonly = 1;
+ }else{
+ *pReadonly = 0;
+ }
+ *pResult = fd;
+ return SQLITE_OK;
+#endif
+#if OS_WIN
+ HANDLE h = CreateFile(zFilename,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL
+ );
+ if( h==INVALID_HANDLE_VALUE ){
+ HANDLE h = CreateFile(zFilename,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL
+ );
+ if( h==INVALID_HANDLE_VALUE ){
+ return SQLITE_CANTOPEN;
+ }
+ *pReadonly = 1;
+ }else{
+ *pReadonly = 0;
+ }
+ *pResult = h;
+ return SQLITE_OK;
+#endif
+
+
+/*
+** Attempt to open a new file for exclusive access by this process.
+** The file will be opened for both reading and writing. To avoid
+** a potential security problem, we do not allow the file to have
+** previously existed. Nor do we allow the file to be a symbolic
+** link.
+**
+** On success, write the file handle into *pResult and return SQLITE_OK.
+**
+** On failure, return SQLITE_CANTOPEN.
+*/
+int sqliteOsOpenExclusive(char *zFilename, OsFile *pResult){
+#if OS_UNIX
+ struct stat buf;
+ time_t now;
+ int fd;
+ if( access(zFilename, 0)==0 ){
+ return SQLITE_CANTOPEN;
+ }
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+ fd = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600);
+ if( fd<0 ){
+ return SQLITE_CANTOPEN;
+ }
+ *pResult = fd;
+ return SQLITE_OK;
+#endif
+#if OS_WIN
+ HANDLE h = CreateFile(zFilename,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL
+ );
+ if( h==INVALID_HANDLE_VALUE ){
+ return SQLITE_CANTOPEN;
+ }
+ *pResult = h;
+ return SQLITE_OK;
+#endif
+}
+
+/*
+** Create a temporary file name in zBuf. zBuf must be big enough to
+** hold at least SQLITE_TEMPNAME_SIZE characters.
+*/
+int sqliteOsTempFileName(char *zBuf){
+#if OS_UNIX
+ static const char *azDirs[] = {
+ ".",
+ "/var/tmp",
+ "/usr/tmp",
+ "/tmp",
+ };
+ static char zChars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ int i, j;
+ struct stat buf;
+ char *zDir = ".";
+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
+ if( stat(azDirs[i], &buf) ) continue;
+ if( !S_ISDIR(buf.st_mode) ) continue;
+ if( access(azDirs[i], 07) ) continue;
+ zDir = azDirs[i];
+ break;
+ }
+ do{
+ sprintf(zBuf, "%s/sqlite_", zDir);
+ j = strlen(zBuf);
+ for(i=0; i<15; i++){
+ int n = sqliteRandomByte() % sizeof(zChars);
+ zBuf[j++] = zChars[n];
+ }
+ zBuf[j] = 0;
+ }while( access(zBuf,0)==0 );
+#endif
+#if OS_WIN
+ int i, j;
+ HANDLE h;
+ char zTempPath[SQLITE_TEMPNAME_SIZE];
+ GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
+ for(;;){
+ sprintf(zBuf, "%s/sqlite_", zTempPath);
+ j = strlen(zBuf);
+ for(i=0; i<15; i++){
+ int n = sqliteRandomByte() % sizeof(zChars);
+ zBuf[j++] = zChars[n];
+ }
+ zBuf[j] = 0;
+ h = CreateFile(zBuf,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL
+ );
+ if( h!=INVALID_FILE_HANDLE ){
+ CloseHandle(h);
+ continue;
+ }
+ break;
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Close a file
+*/
+int sqliteOsClose(OsFile id){
+#if OS_UNIX
+ close(id);
+ return SQLITE_OK;
+#endif
+#if OS_WIN
+ CloseHandle(id);
+ return SQLITE_OK;
+#endif
+}
+
+/*
+** Read data from a file into a buffer
+*/
+
+/*
+** Write data from a buffer into a file
+*/
+/*
+** Move the read/write pointer in a file.
+*/
+/*
+** Make sure all writes to a particular file are committed to disk.
+*/
+/*
+** Truncate an open file to a specified size
+*/
+/*
+** Determine the current size of a file in bytes
+*/
+/*
+** Get a read or write lock on a file.
+*/
+/*
+** Release the read or write lock from a file.
+*/
+/*
+** Get information to seed the random number generator.
+*/
+/*
+** Sleep for a little while.
+*/
+
+
+
+#endif /* OS_WIN */
--- /dev/null
+/*
+** 2001 September 16
+**
+** 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 header file (together with is companion C source-code file
+** "os.c") attempt to abstract the underlying operating system so that
+** the SQLite library will work on both POSIX and windows systems.
+*/
+#ifndef _SQLITE_OS_H_
+#define _SQLITE_OS_H_
+
+/*
+** A handle for an open file is stored in an OsFile object.
+*/
+#if OS_UNIX
+ typedef int OsFile;
+# define SQLITE_TEMPNAME_SIZE 200
+#endif
+
+#if OS_WIN
+ typedef HANDLE OsFile;
+# define SQLITE_TEMPNAME_SIZE (MAX_PATH+1)
+#endif
+
+int sqliteOsOpenReadWrite(char*, OsFile*, int*);
+int sqliteOsOpenExclusive(char*, OsFile*);
+int sqliteOsTempFileName(char*);
+int sqliteOsClose(OsFile);
+int sqliteOsRead(OsFile, int amt, void*);
+int sqliteOsWrite(OsFile, int amt, void*);
+int sqliteOsSeek(OsFile, int offset);
+int sqliteOsSync(OsFile);
+int sqliteOsTruncate(OsFile, int size);
+int sqliteOsFileSize(OsFile, int *pSize);
+int sqliteOsLock(OsFile, int wrlock);
+int sqliteOsUnlock(OsFile);
+int sqliteOsRandomSeed(int amt, char*);
+int sqliteSleep(int ms);
+
+
+
+#endif /* _SQLITE_OS_H_ */
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.51 2001/09/16 00:13:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.52 2001/09/17 20:25:58 drh Exp $
*/
#include "sqlite.h"
#include "vdbe.h"
int explain; /* True if the EXPLAIN flag is found on the query */
int initFlag; /* True if reparsing CREATE TABLEs */
int newTnum; /* Table number to use when reparsing CREATE TABLEs */
+ int newKnum; /* Primary key number when reparsing CREATE TABLEs */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated cursors */
int nMem; /* Number of memory cells used so far */
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE INDEX statement.
#
-# $Id: index.test,v 1.12 2001/09/16 00:13:28 drh Exp $
+# $Id: index.test,v 1.13 2001/09/17 20:25:58 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
} {16}
do_test index-7.3 {
set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}]
- expr {[lsearch $code test1__primary_key]>0}
+ expr {[lsearch $code {test1 (primary key)}]>0}
} {1}
do_test index-7.4 {
execsql {DROP table test1}