aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c63
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);