From: drh Date: Fri, 16 Dec 2005 01:06:16 +0000 (+0000) Subject: Initial infrastructure for recognizing DESC indices and being able to read X-Git-Tag: version-3.6.10~3338 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdd6e85a34cc4f1fcb49639519f3673627ecacbf;p=thirdparty%2Fsqlite.git Initial infrastructure for recognizing DESC indices and being able to read and write older databases that specify DESC indices but do not really use them. Nothing is close to working yet. (CVS 2822) FossilOrigin-Name: cd110aa225b09591064405dd8952b3df37278c52 --- 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,19 +462,26 @@ 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); + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); - /* Only set the file format to $f if it is currently less than $f. */ + /* 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, f, 0); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); } - - /* Reload the schema of the modified table. */ - reloadTableSchema(pParse, pTab, pTab->zName); } 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