diff --git a/manifest b/manifest index 5b495ea60e..fa524f5373 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sutf8\sto\sutf16\sconversion\sroutine\sfor\sshort\sstrings.\s\sBug\nintroduced\sby\scheck-in\s(2817).\s(CVS\s2821) -D 2005-12-15T22:34:01 +C Initial\sinfrastructure\sfor\srecognizing\sDESC\sindices\sand\sbeing\sable\sto\sread\r\nand\swrite\solder\sdatabases\sthat\sspecify\sDESC\sindices\sbut\sdo\snot\sreally\suse\r\nthem.\s\sNothing\sis\sclose\sto\sworking\syet.\s(CVS\s2822) +D 2005-12-16T01:06:17 F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -30,13 +30,13 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a -F src/alter.c 26e590618fe6a316c74626dbea6529c7315172e9 +F src/alter.c 7bc737c689044fa00ff2f445139c61f5c9ee0ad8 F src/analyze.c ea42005eed52c382fcc7ef66969e7f1858597633 F src/attach.c ee70131f128d31a9c6dcb8824e8471c91b18601a F src/auth.c 31e2304bef67f44d635655f44234387ea7d21454 F src/btree.c de0fc1a0f6a4631001ffb6070d1b7588cdebcbc5 F src/btree.h 1ed561263ca0e335bc3e81d761c9d5ff8c22f61e -F src/build.c 306dde3134acd8f1c9f3821d81c3cb598af91280 +F src/build.c 178a5c36365b5ec89a4a29a74186583f503c10fa F src/callback.c 62066afd516f220575e81b1a1239ab92a2eae252 F src/complete.c df1681cef40dec33a286006981845f87b194e7a4 F src/date.c bb079317bff6a2b78aba5c0d2ddae5f6f03acfb7 @@ -61,15 +61,15 @@ F src/os_win.c 9feb97f49b93d451f8ef7c5dd388e05a44647dc6 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 49f63a54b57164a70df0b1539141003fd27856c6 F src/pager.h e7b41ce8e7b5f629d456708b7ad9a8c8ede37140 -F src/parse.y d0b1f9a4d508bf043cdbc7079aa26dff7d358651 +F src/parse.y 142a4b347c82217332e2d3dfa317ff2b7ac32f9c F src/pragma.c 8883b4d34796efa315bdd0ec1b03f580ef1575b9 -F src/prepare.c ca4d58a46e74412dba1fcfaeeaa89b01e64f1a8b +F src/prepare.c 1417a396efe55e2767f9f97f694d21b8cac2f4d6 F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812 F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d F src/select.c 2292b065bc6be61e01aad39a2e1b93e332fb7e57 F src/shell.c 4872acee1d2a826c73c914961e469e563204b7f9 F src/sqlite.h.in 31ab5ef5268c7f1ee909151a0fc45c659290ec15 -F src/sqliteInt.h 927c7fbc25d105c89aa90dc148c68c0b33051048 +F src/sqliteInt.h 853a868ee69e841b9eba078f359932cddd3cf264 F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 F src/tclsqlite.c c2303e1b1e6602b8cfef4dad00e4d76a47868c5e F src/test1.c d6924b182773b2ad3b22e435e4d3bfd5a846da9e @@ -88,7 +88,7 @@ F src/vdbe.c a9acffc91d3e06af24dc1dcf5bf7d5e77460b1c5 F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 F src/vdbeInt.h 7b8b8c5dcb203243e4a9a4414c9e488473f67741 F src/vdbeapi.c b270b680cbc5d20b5a1abfdb08339667985df94e -F src/vdbeaux.c f714ee9e91f1e47d4b6ae83798e0b263ffe224cc +F src/vdbeaux.c 722736cd433f06942bc5c7b7915e6561be0b400c F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c deba8d6e3727643924b210a8c531a496c2b8d386 F src/where.c 269569f380ddc018518f67765fe2f0d3c8760e28 @@ -125,7 +125,7 @@ F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f F test/btree8.test fadc112bcbd6a0c622d34c813fc8a648eacf8804 F test/busy.test 0271c854738e23ad76e10d4096a698e5af29d211 F test/capi2.test f897209386fb21cfdc9267595e0c667ebaca9164 -F test/capi3.test fc8e573467049add3bfaf81f53827e8ff153cf8f +F test/capi3.test af46034e00e225eaef780930204a4f885bd40fa0 F test/capi3b.test 5b6a66f9f295f79f443b5d3f33187fa5ef6cf336 F test/cast.test 2543165ced4249c89ce5f0352222df503a98b9e5 F test/check.test 8154b8ac0c56c34088168b8d87eee713fba2b31b @@ -327,7 +327,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 36229018817eebfbfca7a66d2285e4faf7b39845 -R db348b533dcaa66ab84d8527c31842a7 +P 4fba2db38e0693be52ca7251e4958bd836607f05 +R cf0e0e36b0268dddfac27efc891f1d3b U drh -Z 04cd55b34392e021d53876472bf23ee4 +Z e31baf15a60fd5885441bd2ca28e4cd9 diff --git a/manifest.uuid b/manifest.uuid index 28a0663db4..cc851b73f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4fba2db38e0693be52ca7251e4958bd836607f05 \ No newline at end of file +cd110aa225b09591064405dd8952b3df37278c52 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 1e4f8a274a..6758315d1b 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.11 2005/12/09 20:02:05 drh Exp $ +** $Id: alter.c,v 1.12 2005/12/16 01:06:17 drh Exp $ */ #include "sqliteInt.h" #include @@ -462,21 +462,28 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ - if( (v=sqlite3GetVdbe(pParse))!=0 ){ - int f = (pDflt?3:2); - - /* Only set the file format to $f if it is currently less than $f. */ - sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); - } + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); /* Reload the schema of the modified table. */ reloadTableSchema(pParse, pTab, pTab->zName); } +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); + } +} + /* ** This function is called by the parser after the table-name in diff --git a/src/build.c b/src/build.c index 2a9a144c54..32d4bfd054 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.357 2005/12/09 20:02:05 drh Exp $ +** $Id: build.c,v 1.358 2005/12/16 01:06:17 drh Exp $ */ #include "sqliteInt.h" #include @@ -764,7 +764,7 @@ void sqlite3StartTable( sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); - sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); /* file format defaults to 1 */ sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); @@ -1010,7 +1010,8 @@ void sqlite3AddPrimaryKey( Parse *pParse, /* Parsing context */ ExprList *pList, /* List of field names to be indexed */ int onError, /* What to do with a uniqueness conflict */ - int autoInc /* True if the AUTOINCREMENT keyword is present */ + int autoInc, /* True if the AUTOINCREMENT keyword is present */ + int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; char *zType = 0; @@ -1041,7 +1042,8 @@ void sqlite3AddPrimaryKey( if( iCol>=0 && iColnCol ){ zType = pTab->aCol[iCol].zType; } - if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ pTab->iPKey = iCol; pTab->keyConf = onError; pTab->autoInc = autoInc; @@ -1051,7 +1053,7 @@ void sqlite3AddPrimaryKey( "INTEGER PRIMARY KEY"); #endif }else{ - sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder); pList = 0; } @@ -2094,18 +2096,24 @@ void sqlite3CreateIndex( ExprList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ - Token *pEnd /* The ")" that closes the CREATE INDEX statement */ + Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ + int sortOrder /* Sort order of primary key when pList==NULL */ ){ - Table *pTab = 0; /* Table to be indexed */ - Index *pIndex = 0; /* The index to be created */ - char *zName = 0; + Table *pTab = 0; /* Table to be indexed */ + Index *pIndex = 0; /* The index to be created */ + char *zName = 0; /* Name of the index */ + int nName; /* Number of characters in zName */ int i, j; - Token nullId; /* Fake token for an empty ID list */ - DbFixer sFix; /* For assigning database names to pTable */ + Token nullId; /* Fake token for an empty ID list */ + DbFixer sFix; /* For assigning database names to pTable */ + int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ + int descSeen = 0; /* Changes to true if a DESC is seen */ sqlite3 *db = pParse->db; - - int iDb; /* Index of the database that is being written */ - Token *pName = 0; /* Unqualified name of the index to create */ + Db *pDb; /* The specific table containing the indexed database */ + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + struct ExprList_item *pListItem; /* For looping over pList */ + CollSeq *pCollSeq; /* Collating sequence for one index column */ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto exit_create_index; @@ -2148,6 +2156,7 @@ void sqlite3CreateIndex( pTab = pParse->pNewTable; iDb = pTab->iDb; } + pDb = &db->aDb[iDb]; if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ @@ -2183,7 +2192,7 @@ void sqlite3CreateIndex( } if( !db->init.busy ){ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; - if( sqlite3FindIndex(db, zName, db->aDb[iDb].zName)!=0 ){ + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); goto exit_create_index; } @@ -2207,7 +2216,7 @@ void sqlite3CreateIndex( */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = db->aDb[iDb].zName; + const char *zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -2228,17 +2237,20 @@ void sqlite3CreateIndex( nullId.n = strlen((char*)nullId.z); pList = sqlite3ExprListAppend(0, 0, &nullId); if( pList==0 ) goto exit_create_index; + pList->a[0].sortOrder = sortOrder; } /* ** Allocate the index structure. */ - pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) + - (sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr ); + nName = strlen(zName); + pIndex = sqliteMalloc( sizeof(Index) + nName + 2 + sizeof(int) + + (sizeof(int)*2 + sizeof(CollSeq*) + 1)*pList->nExpr ); if( sqlite3Tsd()->mallocFailed ) goto exit_create_index; pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr]; pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr]; pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1]; + pIndex->keyInfo.aSortOrder = &pIndex->zName[nName+1]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nExpr; @@ -2246,23 +2258,38 @@ void sqlite3CreateIndex( pIndex->autoIndex = pName==0; pIndex->iDb = iDb; + /* Check to see if we should honor DESC requests on index columns + */ + if( pDb->file_format>=4 || (pDb->descIndex && db->init.busy) ){ +#if 0 + sortOrderMask = -1; /* Honor DESC */ +#else + sortOrderMask = 0; +#endif + }else{ + sortOrderMask = 0; /* Ignore DESC */ + } + /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ - for(i=0; inExpr; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int sortOrder; + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, pList->a[i].zName); + pTab->zName, zColName); goto exit_create_index; } pIndex->aiColumn[i] = j; - if( pList->a[i].pExpr ){ - assert( pList->a[i].pExpr->pColl ); - pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + pIndex->keyInfo.aColl[i] = pListItem->pExpr->pColl; }else{ pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl; } @@ -2272,6 +2299,11 @@ void sqlite3CreateIndex( ){ goto exit_create_index; } + sortOrder = pListItem->sortOrder; + pDb->descIndex |= sortOrder; + sortOrder &= sortOrderMask; + pIndex->keyInfo.aSortOrder[i] = sortOrder; + descSeen |= sortOrder; } pIndex->keyInfo.nField = pList->nExpr; sqlite3DefaultRowEst(pIndex); @@ -2301,6 +2333,7 @@ void sqlite3CreateIndex( for(k=0; knColumn; k++){ if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break; + if( pIdx->keyInfo.aSortOrder[k]!=pIndex->keyInfo.aSortOrder[k] ) break; } if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ @@ -2364,6 +2397,11 @@ void sqlite3CreateIndex( v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; + /* Make sure the file_format is at least 4 if we have DESC indices. */ + if( descSeen ){ + sqlite3MinimumFileFormat(pParse, iDb, 4); + } + /* Create the rootpage for the index */ sqlite3BeginWriteOperation(pParse, 1, iDb); diff --git a/src/parse.y b/src/parse.y index 64f3a7beb1..f000a6ffdf 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.187 2005/12/09 20:02:05 drh Exp $ +** @(#) $Id: parse.y,v 1.188 2005/12/16 01:06:17 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" @@ -257,9 +257,9 @@ carg ::= DEFAULT id(X). { // ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} -ccons ::= PRIMARY KEY sortorder onconf(R) autoinc(I). - {sqlite3AddPrimaryKey(pParse,0,R,I);} -ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);} +ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). + {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0);} ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} @@ -307,9 +307,9 @@ conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). - {sqlite3AddPrimaryKey(pParse,X,R,I);} + {sqlite3AddPrimaryKey(pParse,X,R,I,0);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). - {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} + {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0);} tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);} tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { @@ -834,7 +834,8 @@ cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D) ON nm(Y) LP idxlist(Z) RP(E) onconf(R). { if( U!=OE_None ) U = R; if( U==OE_Default) U = OE_Abort; - sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0),Z,U, &S, &E); + sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0), Z, U, + &S, &E, SQLITE_SO_ASC); } %type uniqueflag {int} @@ -849,21 +850,23 @@ uniqueflag(A) ::= . {A = OE_None;} idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} -idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder. { +idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n); } A = sqlite3ExprListAppend(X, p, &Y); + if( A ) A->a[A->nExpr-1].sortOrder = Z; } -idxlist(A) ::= idxitem(Y) collate(C) sortorder. { +idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). { Expr *p = 0; if( C.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)C.z, C.n); } A = sqlite3ExprListAppend(0, p, &Y); + if( A ) A->a[A->nExpr-1].sortOrder = Z; } idxitem(A) ::= nm(X). {A = X;} diff --git a/src/prepare.c b/src/prepare.c index ca00049e66..f530dd874a 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.9 2005/12/15 03:04:11 drh Exp $ +** $Id: prepare.c,v 1.10 2005/12/16 01:06:17 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -115,6 +115,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ BtCursor *curMain; int size; Table *pTab; + Db *pDb; char const *azArg[5]; char zDbNum[30]; int meta[10]; @@ -184,11 +185,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ /* Create a cursor to hold the database open */ - if( db->aDb[iDb].pBt==0 ){ + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded); return SQLITE_OK; } - rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); return rc; @@ -214,7 +216,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ if( rc==SQLITE_OK ){ int i; for(i=0; rc==SQLITE_OK && iaDb[iDb].pBt, i+1, (u32 *)&meta[i]); + rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); @@ -224,7 +226,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ }else{ memset(meta, 0, sizeof(meta)); } - db->aDb[iDb].schema_cookie = meta[0]; + pDb->schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. @@ -249,39 +251,25 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ size = meta[2]; if( size==0 ){ size = MAX_PAGES; } - db->aDb[iDb].cache_size = size; - - if( iDb==0 ){ - db->file_format = meta[1]; - if( db->file_format==0 ){ - /* This happens if the database was initially empty */ - db->file_format = 1; - } - - if( db->file_format==2 || db->file_format==3 ){ - /* File format 2 is treated exactly as file format 1. New - ** databases are created with file format 1. - */ - db->file_format = 1; - } - } + pDb->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); /* ** file_format==1 Version 3.0.0. - ** file_format==2 Version 3.1.3. - ** file_format==3 Version 3.1.4. - ** - ** Version 3.0 can only use files with file_format==1. Version 3.1.3 - ** can read and write files with file_format==1 or file_format==2. - ** Version 3.1.4 can read and write file formats 1, 2 and 3. + ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN + ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults + ** file_format==4 Version 3.3.0. // DESC indices */ - if( meta[1]>3 ){ + pDb->file_format = meta[1]; + if( pDb->file_format==0 ){ + pDb->file_format = 1; + } + if( pDb->file_format>4 ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5cd15242b3..0285677f87 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.437 2005/12/15 15:22:09 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.438 2005/12/16 01:06:17 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -356,6 +356,8 @@ struct Db { u16 flags; /* Flags associated with this database */ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at synching data to disk */ + u8 file_format; /* Schema format version for this file */ + u8 descIndex; /* True if any index uses the DESC attribute */ int cache_size; /* Number of pages to use in the cache */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ void *pAux; /* Auxiliary data. Usually NULL */ @@ -419,7 +421,6 @@ struct sqlite3 { int errCode; /* Most recent error code (SQLITE_*) */ u8 enc; /* Text encoding for this database. */ u8 autoCommit; /* The auto-commit flag. */ - u8 file_format; /* What file format version is this database? */ u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ @@ -1467,7 +1468,7 @@ void sqlite3OpenMasterTable(Vdbe *v, int); void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); -void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int); +void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); @@ -1493,7 +1494,7 @@ void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, - Token*); + Token*, int); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); @@ -1676,6 +1677,7 @@ void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SqliteTsd *sqlite3Tsd(); void sqlite3AttachFunctions(sqlite3 *); +void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3MallocClearFailed(); #ifdef NDEBUG diff --git a/src/vdbeaux.c b/src/vdbeaux.c index f435effa6b..6949f8c35c 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -435,16 +435,18 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ KeyInfo *pKeyInfo; int nField, nByte; - /* KeyInfo structures that include an KeyInfo.aSortOrder are always - ** sent in using P3_KEYINFO_HANDOFF. The KeyInfo.aSortOrder array - ** is not duplicated when P3_KEYINFO is used. */ - /* assert( pKeyInfo->aSortOrder==0 ); */ nField = ((KeyInfo*)zP3)->nField; - nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]); + nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; pKeyInfo = sqliteMallocRaw( nByte ); pOp->p3 = (char*)pKeyInfo; if( pKeyInfo ){ + char *aSortOrder; memcpy(pKeyInfo, zP3, nByte); + aSortOrder = pKeyInfo->aSortOrder; + if( aSortOrder ){ + pKeyInfo->aSortOrder = (char*)&pKeyInfo->aColl[nField]; + memcpy(pKeyInfo->aSortOrder, aSortOrder, nField); + } pOp->p3type = P3_KEYINFO; }else{ pOp->p3type = P3_NOTUSED; diff --git a/test/capi3.test b/test/capi3.test index 8810cfd28b..8f2a8da43a 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi3.test,v 1.34 2005/08/11 02:10:19 drh Exp $ +# $Id: capi3.test,v 1.35 2005/12/16 01:06:18 drh Exp $ # set testdir [file dirname $argv0] @@ -490,7 +490,7 @@ if {![sqlite3 -has-codec]} { set ::bt [btree_open test.db 10 0] btree_begin_transaction $::bt set meta [btree_get_meta $::bt] - lset meta 2 4 + lset meta 2 5 eval [concat btree_update_meta $::bt [lrange $meta 0 end]] btree_commit $::bt btree_close $::bt