diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/alter.c | 25 | ||||
-rw-r--r-- | src/build.c | 88 | ||||
-rw-r--r-- | src/parse.y | 21 | ||||
-rw-r--r-- | src/prepare.c | 46 | ||||
-rw-r--r-- | src/sqliteInt.h | 10 | ||||
-rw-r--r-- | src/vdbeaux.c | 12 |
6 files changed, 121 insertions, 81 deletions
diff --git a/src/alter.c b/src/alter.c index 1e4f8a274..6758315d1 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 <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); } diff --git a/src/build.c b/src/build.c index 2a9a144c5..32d4bfd05 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 <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); diff --git a/src/parse.y b/src/parse.y index 64f3a7beb..f000a6ffd 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 ca00049e6..f530dd874 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 && 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 */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5cd15242b..0285677f8 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 f435effa6..6949f8c35 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; |