]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Initial infrastructure for recognizing DESC indices and being able to read
authordrh <drh@noemail.net>
Fri, 16 Dec 2005 01:06:16 +0000 (01:06 +0000)
committerdrh <drh@noemail.net>
Fri, 16 Dec 2005 01:06:16 +0000 (01:06 +0000)
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

manifest
manifest.uuid
src/alter.c
src/build.c
src/parse.y
src/prepare.c
src/sqliteInt.h
src/vdbeaux.c
test/capi3.test

index 5b495ea60ed80f159aa1b16c9186fcbb6d201847..fa524f5373b9d10a1f15d87a8451370726122bc0 100644 (file)
--- 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
index 28a0663db4f2a57f9e744d972e349114c7acc871..cc851b73f41ac4d72e33766ba246e94c965ba593 100644 (file)
@@ -1 +1 @@
-4fba2db38e0693be52ca7251e4958bd836607f05
\ No newline at end of file
+cd110aa225b09591064405dd8952b3df37278c52
\ No newline at end of file
index 1e4f8a274ae6cb643f774caad35bd5e3bcb33b08..6758315d1beeda10bc9c527311312a965248f4c1 100644 (file)
@@ -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 <ctype.h>
@@ -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);
 }
 
 
index 2a9a144c54f8aab35e1a29823f304eebba807839..32d4bfd05477238d22a249932798b56c041fb4bb 100644 (file)
@@ -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 <ctype.h>
@@ -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 && iCol<pTab->nCol ){
     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; i<pList->nExpr; i++){
-    for(j=0; j<pTab->nCol; j++){
-      if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
+  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
+    const char *zColName = pListItem->zName;
+    Column *pTabCol;
+    int sortOrder;
+    for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; 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; k<pIdx->nColumn; 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);
index 64f3a7beb16af16c8d2b17722513a707e985d65e..f000a6ffdfecab0a2f6389415e499b9e23934a35 100644 (file)
@@ -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;}
 
index ca00049e660451efd8905bbdde0294b5b46b809f..f530dd874a1b24b8c26511b7732718543a2d2f29 100644 (file)
@@ -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 && i<sizeof(meta)/sizeof(meta[0]); i++){
-      rc = sqlite3BtreeGetMeta(db->aDb[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
   */
index 5cd15242b3ec8cf9a8d1fbdda02eeca96d2dab96..0285677f8768b87d15ad96b7354018436385fa20 100644 (file)
@@ -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
index f435effa6b399e7b76adc889c374b65b630a3cc5..6949f8c35cc08f2c222f3f312fc61cf8a07cd080 100644 (file)
@@ -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;
index 8810cfd28b33d967f6dcd229a683f4352d44806b..8f2a8da43afaabd95ae33a57709c2a611be407e5 100644 (file)
@@ -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