/ Check-in [b8aaa3a2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change the collation sequence interface to allow collation sequences that use UTF-16 in non-native byte order to be registered. (CVS 1559)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b8aaa3a29e0ddef357ab1b3b0b9f87ed390f2f36
User & Date: danielk1977 2004-06-10 02:16:02
Context
2004-06-10
04:32
When in PAGER_RESERVED state, don't write to the main file when rolling back a statement transaction. (CVS 1560) check-in: adb2bd61 user: danielk1977 tags: trunk
02:16
Change the collation sequence interface to allow collation sequences that use UTF-16 in non-native byte order to be registered. (CVS 1559) check-in: b8aaa3a2 user: danielk1977 tags: trunk
01:30
Add the vdbe_listing and sql_trace pragmas used for debugging. (CVS 1558) check-in: 28c3cc08 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
851
852
853
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

877
878
879
880





881
882
883
884
885
886
887













































888

889
890

















































891
892
893
894
895
896
897

898
899
900
901
902
903
904
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.213 2004/06/10 00:29:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl;
  }
}

/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry.
**
** FIX ME: For now, return NULL if create is not true and the entry is not
** found. But this needs to change to call the collation factory.

**
** FIX ME: If we have a UTF-8 version of the collation function, and a
** UTF-16 version would be better, should the collation factory be called?
** If so should a flag be set to say that we already requested such a
** function and couldn't get one?
*/
CollSeq *sqlite3FindCollSeq(
  sqlite *db, 
  const char *zName, 
  int nName,
  int create
){
  CollSeq *pColl;
  if( nName<0 ) nName = strlen(zName);
  pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);

  if( 0==pColl && create ){
    pColl = sqliteMalloc( sizeof(*pColl) + nName + 1 );
    if( pColl ){
      pColl->zName = (char*)&pColl[1];





      memcpy(pColl->zName, zName, nName+1);
      sqlite3HashInsert(&db->aCollSeq, pColl->zName, nName, pColl);
    }
  }
  return pColl;
}














































CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){

  CollSeq *pColl = sqlite3FindCollSeq(pParse->db, zName, nName, 0);
  if( !pColl ){

















































    if( pParse->nErr==0 ){
      sqlite3SetNString(&pParse->zErrMsg, 
          "no such collation sequence: ", -1, 
          zName, nName, 0);
    }
    pParse->nErr++;
  }

  return pColl;
}



/*
** Scan the column type name zType (length nType) and return the







|







 







|

|
|
>

<
|
|
|

|
|
|






>

|

|
>
>
>
>
>
|
|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
<




>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
851
852
853
854
855
856
857
858
859
860
861
862
863

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993

994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.214 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl;
  }
}

/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry. Otherwise return NULL.
**
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
** array of three CollSeq structures. The first is the collation sequence
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
**

** Stored immediately after the three collation sequences is a copy of
** the collation sequence name. A pointer to this string is stored in
** each collation sequence structure.
*/
static CollSeq * findCollSeqEntry(
  sqlite *db,
  const char *zName,
  int nName,
  int create
){
  CollSeq *pColl;
  if( nName<0 ) nName = strlen(zName);
  pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);

  if( 0==pColl && create ){
    pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 );
    if( pColl ){
      pColl[0].zName = (char*)&pColl[3];
      pColl[0].enc = TEXT_Utf8;
      pColl[1].zName = (char*)&pColl[3];
      pColl[1].enc = TEXT_Utf16le;
      pColl[2].zName = (char*)&pColl[3];
      pColl[2].enc = TEXT_Utf16be;
      memcpy(pColl[0].zName, zName, nName+1);
      sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
    }
  }
  return pColl;
}

/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry.  Otherwise return NULL.
*/
CollSeq *sqlite3FindCollSeq(
  sqlite *db,
  u8 enc,
  const char *zName,
  int nName,
  int create
){
  CollSeq *pColl = findCollSeqEntry(db, zName, nName, create);
  if( pColl ) switch( enc ){
    case TEXT_Utf8:
      break;
    case TEXT_Utf16le:
      pColl = &pColl[2];
      break;
    case TEXT_Utf16be:
      pColl = &pColl[1];
      break;
    default: 
      assert(!"Cannot happen");
  }
  return pColl;
}

/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName, length nName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
  u8 enc = pParse->db->enc;
  CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);
  if( !pColl || !pColl->xCmp ){
    /* No collation sequence of this type for this encoding is registered.
    ** Call the collation factory to see if it can supply us with one.
    */

    /* FIX ME: Actually call collation factory, then call
    ** sqlite3FindCollSeq() again.  */
    pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);

    if( pColl && !pColl->xCmp ){
      /* The collation factory failed to deliver a function but there are
      ** other versions of this collation function (for other text
      ** encodings) available. Use one of these instead. Avoid a 
      ** UTF-8 <-> UTF-16 conversion if possible.
      */
      CollSeq *pColl2 = 0;
      switch( enc ){
        case TEXT_Utf16le:
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16be,zName,nName,0);
          assert( pColl2 );
          if( pColl2->xCmp ) break;
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf8,zName,nName,0);
          assert( pColl2 );
          break;

        case TEXT_Utf16be:
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le,zName,nName,0);
          assert( pColl2 );
          if( pColl2->xCmp ) break;
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf8,zName,nName,0);
          assert( pColl2 );
          break;

        case TEXT_Utf8:
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16be,zName,nName,0);
          assert( pColl2 );
          if( pColl2->xCmp ) break;
          pColl2 = sqlite3FindCollSeq(pParse->db,TEXT_Utf16le,zName,nName,0);
          assert( pColl2 );
          break;
      }

      if( pColl2->xCmp ){
        memcpy(pColl, pColl2, sizeof(CollSeq));
      }
    }
  }

  /* If nothing has been found, write the error message into pParse */
  if( !pColl || !pColl->xCmp ){
    if( pParse->nErr==0 ){
      sqlite3SetNString(&pParse->zErrMsg, "no such collation sequence: ", -1,

          zName, nName, 0);
    }
    pParse->nErr++;
  }

  return pColl;
}



/*
** Scan the column type name zType (length nType) and return the

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
253
254
255
256
257
258
259

260
261
262
263
264
265
266
...
484
485
486
487
488
489
490






491
492
493
494
495
496
497
....
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
....
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186




1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.212 2004/06/10 01:30:59 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[4] ){  /* text encoding */
    if( iDb==0 ){
      /* If opening the main database, set db->enc. */
      db->enc = (u8)meta[4];

    }else{
      /* If opening an attached database, the encoding much match db->enc */
      if( meta[4]!=db->enc ){
        sqlite3BtreeCloseCursor(curMain);
        sqlite3SetString(pzErrMsg, "attached databases must use the same"
            " text encoding as main database", (char*)0);
        return SQLITE_ERROR;
................................................................................
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }






  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  sqliteFree(db);
}

/*
** Rollback all database files.
................................................................................
    sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
  }
  
  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** 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.
  */
  sqlite3_create_collation(db, "BINARY", 0, 0, binaryCollatingFunc);
  sqlite3_create_collation(db, "BINARY", 1, 0, binaryCollatingFunc);

  db->pDfltColl = sqlite3FindCollSeq(db, "BINARY", 6, 0);
  if( !db->pDfltColl ){
    rc = db->errCode;
    assert( rc!=SQLITE_OK );
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }

  /* Also add a UTF-8 case-insensitive collation sequence. */
  sqlite3_create_collation(db, "NOCASE", 0, 0, nocaseCollatingFunc);

  /* Open the backend database driver */
  if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
    db->temp_store = 2;
    db->nMaster = 0;    /* Disable atomic multi-file commit for :memory: */
  }else{
    db->nMaster = -1;   /* Size of master journal filename initially unknown */
................................................................................
  sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0);
  return rc;
}

int sqlite3_create_collation(
  sqlite3* db, 
  const char *zName, 
  int pref16, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  CollSeq *pColl;
  int rc = SQLITE_OK;
  pColl = sqlite3FindCollSeq(db, zName, strlen(zName), 1);
  if( 0==pColl ){
   rc = SQLITE_NOMEM;
  }else if( pref16 ){
    pColl->xCmp16 = xCompare;
    pColl->pUser16 = pCtx;




  }else{
    pColl->xCmp = xCompare;
    pColl->pUser = pCtx;
  }
  sqlite3Error(db, rc, 0);
  return SQLITE_OK;
}

int sqlite3_create_collation16(
  sqlite3* db, 
  const char *zName, 
  int pref16, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  int rc;
  char *zName8 = sqlite3utf16to8(zName, -1, SQLITE_BIGENDIAN);
  rc = sqlite3_create_collation(db, zName8, pref16, pCtx, xCompare);
  sqliteFree(zName8);
  return rc;
}







|







 







>







 







>
>
>
>
>
>







 







|
|
>
|








|







 







|





|
|
|
|
|
|
>
>
>
>





|





|





|



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
....
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
....
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.213 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[4] ){  /* text encoding */
    if( iDb==0 ){
      /* If opening the main database, set db->enc. */
      db->enc = (u8)meta[4];
      db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
    }else{
      /* If opening an attached database, the encoding much match db->enc */
      if( meta[4]!=db->enc ){
        sqlite3BtreeCloseCursor(curMain);
        sqlite3SetString(pzErrMsg, "attached databases must use the same"
            " text encoding as main database", (char*)0);
        return SQLITE_ERROR;
................................................................................
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }

  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    /* sqliteFree(pColl); */
  }

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  sqliteFree(db);
}

/*
** Rollback all database files.
................................................................................
    sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
  }
  
  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** 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.
  */
  sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binaryCollatingFunc);
  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16LE, 0,binaryCollatingFunc);
  sqlite3_create_collation(db, "BINARY", SQLITE_UTF16BE, 0,binaryCollatingFunc);
  db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
  if( !db->pDfltColl ){
    rc = db->errCode;
    assert( rc!=SQLITE_OK );
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }

  /* Also add a UTF-8 case-insensitive collation sequence. */
  sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);

  /* Open the backend database driver */
  if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
    db->temp_store = 2;
    db->nMaster = 0;    /* Disable atomic multi-file commit for :memory: */
  }else{
    db->nMaster = -1;   /* Size of master journal filename initially unknown */
................................................................................
  sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0);
  return rc;
}

int sqlite3_create_collation(
  sqlite3* db, 
  const char *zName, 
  int enc, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  CollSeq *pColl;
  int rc = SQLITE_OK;
  if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){
    sqlite3Error(db, SQLITE_ERROR, 
        "Param 3 to sqlite3_create_collation() must be one of "
        "SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE"
    );
    return SQLITE_ERROR;
  }
  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
  if( 0==pColl ){
   rc = SQLITE_NOMEM;
  }else{
    pColl->xCmp = xCompare;
    pColl->pUser = pCtx;
  }
  sqlite3Error(db, rc, 0);
  return rc;
}

int sqlite3_create_collation16(
  sqlite3* db, 
  const char *zName, 
  int enc, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  int rc;
  char *zName8 = sqlite3utf16to8(zName, -1, SQLITE_BIGENDIAN);
  rc = sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
  sqliteFree(zName8);
  return rc;
}

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.119 2004/06/10 01:30:59 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

/*
** Macros for troubleshooting.  Normally turned off
*/
#if 1
static Pager *mainPager = 0;
#define SET_PAGER(X)  if( mainPager==0 ) mainPager = (X)
#define CLR_PAGER(X)  if( mainPager==(X) ) mainPager = 0
#define TRACE1(X)     if( pPager==mainPager ) sqlite3DebugPrintf(X)
#define TRACE2(X,Y)   if( pPager==mainPager ) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) if( pPager==mainPager ) sqlite3DebugPrintf(X,Y,Z)
#else







|










|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.120 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

/*
** Macros for troubleshooting.  Normally turned off
*/
#if 0
static Pager *mainPager = 0;
#define SET_PAGER(X)  if( mainPager==0 ) mainPager = (X)
#define CLR_PAGER(X)  if( mainPager==(X) ) mainPager = 0
#define TRACE1(X)     if( pPager==mainPager ) sqlite3DebugPrintf(X)
#define TRACE2(X,Y)   if( pPager==mainPager ) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) if( pPager==mainPager ) sqlite3DebugPrintf(X,Y,Z)
#else

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
958
959
960
961
962
963
964




965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.95 2004/06/09 09:55:18 danielk1977 Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_error16(sqlite3_context*, const void*, int);
void sqlite3_result_int(sqlite3_context*, int);
void sqlite3_result_int64(sqlite3_context*, long long int);
void sqlite3_result_null(sqlite3_context*);
void sqlite3_result_text(sqlite3_context*, const char*, int n, int eCopy);
void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy);
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);





int sqlite3_create_collation(
  sqlite3*, 
  const char *zName, 
  int pref16, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);
int sqlite3_create_collation16(
  sqlite3*, 
  const char *zName, 
  int pref16, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);


#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif







|







 







>
>
>
>




|






|









8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.96 2004/06/10 02:16:02 danielk1977 Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_error16(sqlite3_context*, const void*, int);
void sqlite3_result_int(sqlite3_context*, int);
void sqlite3_result_int64(sqlite3_context*, long long int);
void sqlite3_result_null(sqlite3_context*);
void sqlite3_result_text(sqlite3_context*, const char*, int n, int eCopy);
void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy);
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);

#define SQLITE_UTF8    1
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3

int sqlite3_create_collation(
  sqlite3*, 
  const char *zName, 
  int enc, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);
int sqlite3_create_collation16(
  sqlite3*, 
  const char *zName, 
  int enc, 
  void*,
  int(*xCompare)(void*,int,const void*,int,const void*)
);


#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
508
509
510
511
512
513
514

515
516
517
518
519
520
521
522
523
524
525
....
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.278 2004/06/10 01:30:59 drh Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
**
** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
** collating sequence is undefined.  Indices built on an undefined
** collating sequence may not be read or written.
*/
struct CollSeq {
  char *zName;         /* Name of the collating sequence, UTF-8 encoded */

  void *pUser;         /* First argument to xCmp() */
  void *pUser16;       /* First argument to xCmp16() */
  int (*xCmp)(void*,int, const void*, int, const void*);
  int (*xCmp16)(void*,int, const void*, int, const void*);
};

/*
** A sort order can be either ASC or DESC.
*/
#define SQLITE_SO_ASC       0  /* Sort in ascending order */
#define SQLITE_SO_DESC      1  /* Sort in ascending order */
................................................................................
int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8);
u8 sqlite3UtfReadBom(const void *zData, int nData);
void *sqlite3HexToBlob(const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadUniChar(const char *zStr, int *pOffset, u8 *pEnc, int fold);
int sqlite3ReadSchema(sqlite *db, char **);
CollSeq *sqlite3FindCollSeq(sqlite *,const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Expr *pExpr);







|







 







>

<

<







 







|


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
508
509
510
511
512
513
514
515
516

517

518
519
520
521
522
523
524
....
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.279 2004/06/10 02:16:02 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
**
** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
** collating sequence is undefined.  Indices built on an undefined
** collating sequence may not be read or written.
*/
struct CollSeq {
  char *zName;         /* Name of the collating sequence, UTF-8 encoded */
  u8 enc;              /* Text encoding handled by xCmp() */
  void *pUser;         /* First argument to xCmp() */

  int (*xCmp)(void*,int, const void*, int, const void*);

};

/*
** A sort order can be either ASC or DESC.
*/
#define SQLITE_SO_ASC       0  /* Sort in ascending order */
#define SQLITE_SO_DESC      1  /* Sort in ascending order */
................................................................................
int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8);
u8 sqlite3UtfReadBom(const void *zData, int nData);
void *sqlite3HexToBlob(const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadUniChar(const char *zStr, int *pOffset, u8 *pEnc, int fold);
int sqlite3ReadSchema(sqlite *db, char **);
CollSeq *sqlite3FindCollSeq(sqlite *,u8 enc, const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Expr *pExpr);

Changes to src/tclsqlite.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
913
914
915
916
917
918
919
920

921
922
923
924
925
926
927
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.81 2004/06/09 09:55:19 danielk1977 Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
    zScript = Tcl_GetStringFromObj(objv[3], &nScript);
    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
    if( pCollate==0 ) return TCL_ERROR;
    pCollate->interp = interp;
    pCollate->pNext = pDb->pCollate;
    pCollate->zScript = (char*)&pCollate[1];
    strcpy(pCollate->zScript, zScript);
    if( sqlite3_create_collation(pDb->db, zName, 0, pCollate, tclSqlCollate) ){

      return TCL_ERROR;
    }
    break;
  }

  } /* End of the SWITCH statement */
  return rc;







|







 







|
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.82 2004/06/10 02:16:02 danielk1977 Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
    zScript = Tcl_GetStringFromObj(objv[3], &nScript);
    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
    if( pCollate==0 ) return TCL_ERROR;
    pCollate->interp = interp;
    pCollate->pNext = pDb->pCollate;
    pCollate->zScript = (char*)&pCollate[1];
    strcpy(pCollate->zScript, zScript);
    if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, 
        pCollate, tclSqlCollate) ){
      return TCL_ERROR;
    }
    break;
  }

  } /* End of the SWITCH statement */
  return rc;

Changes to src/vdbemem.c.

434
435
436
437
438
439
440
441
442
443
444




445
446
447
448
449
450
451
452




453
454
455
456
457
458
459



460
461
462
463
464
465
466

    /* FIX ME: This may fail if the collation sequence is deleted after
    ** this vdbe program is compiled. We cannot just use BINARY in this
    ** case as this may lead to a segfault caused by traversing an index
    ** table incorrectly.  We need to return an error to the user in this
    ** case.
    */
    assert( !pColl || (pColl->xCmp || pColl->xCmp16) );

    if( pColl ){
      if( (pMem1->enc==TEXT_Utf8 && pColl->xCmp) || !pColl->xCmp16 ){




        return pColl->xCmp(
          pColl->pUser,
          sqlite3_value_bytes((sqlite3_value *)pMem1),
          sqlite3_value_text((sqlite3_value *)pMem1),
          sqlite3_value_bytes((sqlite3_value *)pMem2),
          sqlite3_value_text((sqlite3_value *)pMem2)
        );
      }else{




        return pColl->xCmp16(
          pColl->pUser,
          sqlite3_value_bytes16((sqlite3_value *)pMem1),
          sqlite3_value_text16((sqlite3_value *)pMem1),
          sqlite3_value_bytes16((sqlite3_value *)pMem2),
          sqlite3_value_text16((sqlite3_value *)pMem2)
        );



      }
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().
    */
  }
 







|


|
>
>
>
>
|
|
|
|
|
|
|
<
>
>
>
>
|
|
|
|
|
|
|
>
>
>







434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

    /* FIX ME: This may fail if the collation sequence is deleted after
    ** this vdbe program is compiled. We cannot just use BINARY in this
    ** case as this may lead to a segfault caused by traversing an index
    ** table incorrectly.  We need to return an error to the user in this
    ** case.
    */
    assert( !pColl || pColl->xCmp );

    if( pColl ){
      if( pMem1->enc==pColl->enc ){
        return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
      }else{
        switch( pColl->enc ){
          case SQLITE_UTF8:
            return pColl->xCmp(
              pColl->pUser,
              sqlite3_value_bytes((sqlite3_value *)pMem1),
              sqlite3_value_text((sqlite3_value *)pMem1),
              sqlite3_value_bytes((sqlite3_value *)pMem2),
              sqlite3_value_text((sqlite3_value *)pMem2)
            );

          case SQLITE_UTF16LE:
          case SQLITE_UTF16BE:
            /* FIX ME: Handle non-native UTF-16 properly instead of
            ** assuming it is always native. */
            return pColl->xCmp(
              pColl->pUser,
              sqlite3_value_bytes16((sqlite3_value *)pMem1),
              sqlite3_value_text16((sqlite3_value *)pMem1),
              sqlite3_value_bytes16((sqlite3_value *)pMem2),
              sqlite3_value_text16((sqlite3_value *)pMem2)
            );
          default:
            assert(!"Cannot happen");
        }
      }
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().
    */
  }