diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 63 |
1 files changed, 54 insertions, 9 deletions
diff --git a/src/main.c b/src/main.c index 38aa70bb1..bd72bdd97 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.371 2007/05/06 16:04:12 danielk1977 Exp $ +** $Id: main.c,v 1.372 2007/05/07 09:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -182,6 +182,12 @@ int sqlite3_close(sqlite3 *db){ for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ CollSeq *pColl = (CollSeq *)sqliteHashData(i); + /* Invoke any destructors registered for collation sequence user data. */ + for(j=0; j<3; j++){ + if( pColl[j].xDel ){ + pColl[j].xDel(pColl[j].pUser); + } + } sqliteFree(pColl); } sqlite3HashClear(&db->aCollSeq); @@ -825,7 +831,8 @@ static int createCollation( const char *zName, int enc, void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*) + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) ){ CollSeq *pColl; int enc2; @@ -860,12 +867,33 @@ static int createCollation( return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), + ** then any copies made by synthCollSeq() need to be invalidated. + ** Also, collation destructor - CollSeq.xDel() - function may need + ** to be called. + */ + if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, strlen(zName)); + int j; + for(j=0; j<3; j++){ + CollSeq *p = &aColl[j]; + if( p->enc==pColl->enc ){ + if( p->xDel ){ + p->xDel(p->pUser); + } + p->xCmp = 0; + } + } + } } pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); if( pColl ){ pColl->xCmp = xCompare; pColl->pUser = pCtx; + pColl->xDel = xDel; pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); } sqlite3Error(db, SQLITE_OK, 0); @@ -915,9 +943,9 @@ static int openDatabase( ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. */ - if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc) || - createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc) || - createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc) || + if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) || (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 ){ assert( sqlite3MallocFailed() ); @@ -926,7 +954,7 @@ static int openDatabase( } /* Also add a UTF-8 case-insensitive collation sequence. */ - createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); /* Set flags on the built-in collating sequences */ db->pDfltColl->type = SQLITE_COLL_BINARY; @@ -986,7 +1014,7 @@ static int openDatabase( #endif #ifdef SQLITE_ENABLE_ICU - { + if( !sqlite3MallocFailed() ){ extern int sqlite3IcuInit(sqlite3*); sqlite3IcuInit(db); } @@ -1106,7 +1134,24 @@ int sqlite3_create_collation( ){ int rc; assert( !sqlite3MallocFailed() ); - rc = createCollation(db, zName, enc, pCtx, xCompare); + rc = createCollation(db, zName, enc, pCtx, xCompare, 0); + return sqlite3ApiExit(db, rc); +} + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation_x( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); return sqlite3ApiExit(db, rc); } @@ -1126,7 +1171,7 @@ int sqlite3_create_collation16( assert( !sqlite3MallocFailed() ); zName8 = sqlite3utf16to8(zName, -1); if( zName8 ){ - rc = createCollation(db, zName8, enc, pCtx, xCompare); + rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); sqliteFree(zName8); } return sqlite3ApiExit(db, rc); |