/ Check-in [7a1701e8]
Login

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

Overview
Comment:Or the SQLITE_UTF16_ALIGNED with the encoding field in sqlite3_create_collation and UTF16 strings will always be aligned on an even byte boundary when passed into the comparison function. (CVS 3103)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7a1701e8c562087d364dff28cd7cad7ca4cdb5ae
User & Date: drh 2006-02-16 18:16:37
Context
2006-02-17
12:25
Ensure temp db is open before executing a pragma like "temp.cachesize = xxx". Fix for #1682. (CVS 3104) check-in: 1e4644b2 user: danielk1977 tags: trunk
2006-02-16
18:16
Or the SQLITE_UTF16_ALIGNED with the encoding field in sqlite3_create_collation and UTF16 strings will always be aligned on an even byte boundary when passed into the comparison function. (CVS 3103) check-in: 7a1701e8 user: drh tags: trunk
00:32
Fix more typos in the file format document. (CVS 3102) check-in: d7495be8 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754

755
756
757
758
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
....
1226
1227
1228
1229
1230
1231
1232
1233
**
*************************************************************************
** 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.334 2006/02/09 13:43:29 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3* db, 
  const char *zName, 
  int enc, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  CollSeq *pColl;

  
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

  /* If SQLITE_UTF16 is specified as the encoding type, transform this
  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
  */

  if( enc==SQLITE_UTF16 ){
    enc = SQLITE_UTF16NATIVE;
  }

  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_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE"
    );
    return SQLITE_ERROR;
  }

  /* Check if this call is removing or replacing an existing collation 
  ** sequence. If so, and there are active VMs, return busy. If there
  ** are no active VMs, invalidate any pre-compiled statements.
  */
  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
  if( pColl && pColl->xCmp ){
    if( db->activeVdbeCnt ){
      sqlite3Error(db, SQLITE_BUSY, 
        "Unable to delete/modify collation sequence due to active statements");
      return SQLITE_BUSY;
    }
    sqlite3ExpirePreparedStatements(db);
  }

  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
  if( pColl ){
    pColl->xCmp = xCompare;
    pColl->pUser = pCtx;
    pColl->enc = enc;
  }
  sqlite3Error(db, SQLITE_OK, 0);
  return SQLITE_OK;
}


/*
................................................................................
    rc = SQLITE_ERROR;
  }
  sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
  sqliteFree(zErrMsg);
  return sqlite3ApiExit(db, rc);
}
#endif








|







 







>









>
|
|


<
>
|
<
<
<







|









|



|







 







<
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760

761
762



763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
....
1225
1226
1227
1228
1229
1230
1231

**
*************************************************************************
** 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.335 2006/02/16 18:16:37 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3* db, 
  const char *zName, 
  int enc, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*)
){
  CollSeq *pColl;
  int enc2;
  
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

  /* If SQLITE_UTF16 is specified as the encoding type, transform this
  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
  */
  enc2 = enc & ~SQLITE_UTF16_ALIGNED;
  if( enc2==SQLITE_UTF16 ){
    enc2 = SQLITE_UTF16NATIVE;
  }


  if( (enc2&~3)!=0 ){
    sqlite3Error(db, SQLITE_ERROR, "unknown encoding");



    return SQLITE_ERROR;
  }

  /* Check if this call is removing or replacing an existing collation 
  ** sequence. If so, and there are active VMs, return busy. If there
  ** are no active VMs, invalidate any pre-compiled statements.
  */
  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0);
  if( pColl && pColl->xCmp ){
    if( db->activeVdbeCnt ){
      sqlite3Error(db, SQLITE_BUSY, 
        "Unable to delete/modify collation sequence due to active statements");
      return SQLITE_BUSY;
    }
    sqlite3ExpirePreparedStatements(db);
  }

  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1);
  if( pColl ){
    pColl->xCmp = xCompare;
    pColl->pUser = pCtx;
    pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED);
  }
  sqlite3Error(db, SQLITE_OK, 0);
  return SQLITE_OK;
}


/*
................................................................................
    rc = SQLITE_ERROR;
  }
  sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
  sqliteFree(zErrMsg);
  return sqlite3ApiExit(db, rc);
}
#endif

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
**    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.162 2006/02/10 03:06:10 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);

/*
** These are the allowed values for the eTextRep argument to
** sqlite3_create_collation and sqlite3_create_function.
*/
#define SQLITE_UTF8    1
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16   4    /* Use native byte order */
#define SQLITE_ANY     5    /* sqlite3_create_function only */


/*
** These two functions are used to add new collation sequences to the
** sqlite3 handle specified as the first argument. 
**
** The name of the new collation sequence is specified as a UTF-8 string
** for sqlite3_create_collation() and a UTF-16 string for







|







 







|
|
|
|
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
**    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.163 2006/02/16 18:16:37 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);

/*
** These are the allowed values for the eTextRep argument to
** sqlite3_create_collation and sqlite3_create_function.
*/
#define SQLITE_UTF8           1
#define SQLITE_UTF16LE        2
#define SQLITE_UTF16BE        3
#define SQLITE_UTF16          4    /* Use native byte order */
#define SQLITE_ANY            5    /* sqlite3_create_function only */
#define SQLITE_UTF16_ALIGNED  8    /* sqlite3_create_collation only */

/*
** These two functions are used to add new collation sequences to the
** sqlite3 handle specified as the first argument. 
**
** The name of the new collation sequence is specified as a UTF-8 string
** for sqlite3_create_collation() and a UTF-16 string for

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
**    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.483 2006/02/15 21:19:01 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
** Defer sourcing vdbe.h and btree.h until after the "u8" and 
** "BusyHandler typedefs.
*/
#include "vdbe.h"
#include "btree.h"
#include "pager.h"

/*
** This macro casts a pointer to an integer.  Useful for doing
** pointer arithmetic.
*/
#define Addr(X)  ((uptr)X)

#ifdef SQLITE_MEMDEBUG
/*
** The following global variables are used for testing and debugging
** only.  They only work if SQLITE_MEMDEBUG is defined.
*/
extern int sqlite3_nMalloc;      /* Number of sqliteMalloc() calls */
extern int sqlite3_nFree;        /* Number of sqliteFree() calls */







|







 







<
<
<
<
<
<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
247
248
249
250
251
252
253






254
255
256
257
258
259
260
**    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.484 2006/02/16 18:16:37 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
** Defer sourcing vdbe.h and btree.h until after the "u8" and 
** "BusyHandler typedefs.
*/
#include "vdbe.h"
#include "btree.h"
#include "pager.h"







#ifdef SQLITE_MEMDEBUG
/*
** The following global variables are used for testing and debugging
** only.  They only work if SQLITE_MEMDEBUG is defined.
*/
extern int sqlite3_nMalloc;      /* Number of sqliteMalloc() calls */
extern int sqlite3_nFree;        /* Number of sqliteFree() calls */

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1525
1526
1527
1528
1529
1530
1531

















































1532
1533
1534
1535
1536
1537
1538
1539
....
3578
3579
3580
3581
3582
3583
3584

3585
3586
3587
3588
3589
3590
3591
....
3663
3664
3665
3666
3667
3668
3669


3670
3671
3672
3673
3674
3675
3676
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.206 2006/02/10 03:06:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;

bad_args:
  Tcl_WrongNumArgs(interp, 1, objv, "DB");
  return TCL_ERROR;
}

















































#endif /* SQLITE_OMIT_UTF16 */

/*
** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
**
** This function is used to test that SQLite selects the correct user
** function callback when multiple versions (for different text encodings)
** are available.
................................................................................
#endif

#ifndef SQLITE_OMIT_UTF16
     { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
     { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
     { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
     { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },

#ifdef SQLITE_ENABLE_COLUMN_METADATA
{"sqlite3_column_database_name16",
  test_stmt_utf16, sqlite3_column_database_name16},
{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16},
{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16},
#endif
#endif
................................................................................
      (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite3_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3_os_trace, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite3_tsd_count",
      (char*)&sqlite3_tsd_count, TCL_LINK_INT);


#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
  Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks",
      (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT);
#endif
#ifndef SQLITE_OMIT_UTF16
  Tcl_LinkVar(interp, "sqlite_last_needed_collation",
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);







|







 







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







 







>







 







>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
....
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
....
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.207 2006/02/16 18:16:37 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;

bad_args:
  Tcl_WrongNumArgs(interp, 1, objv, "DB");
  return TCL_ERROR;
}

/*
** tclcmd:   add_alignment_test_collations  DB
**
** Add two new collating sequences to the database DB
**
**     utf16_aligned
**     utf16_unaligned
**
** Both collating sequences use the same sort order as BINARY.
** The only difference is that the utf16_aligned collating
** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
** Both collating functions increment the unaligned utf16 counter
** whenever they see a string that begins on an odd byte boundary.
*/
static int unaligned_string_counter = 0;
static int alignmentCollFunc(
  void *NotUsed,
  int nKey1, const void *pKey1,
  int nKey2, const void *pKey2
){
  int rc, n;
  n = nKey1<nKey2 ? nKey1 : nKey2;
  if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++;
  if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++;
  rc = memcmp(pKey1, pKey2, n);
  if( rc==0 ){
    rc = nKey1 - nKey2;
  }
  return rc;
}
static int add_alignment_test_collations(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  if( objc>=2 ){
    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
    sqlite3_create_collation(db, "utf16_unaligned",
        SQLITE_UTF16, 
        0, alignmentCollFunc);
    sqlite3_create_collation(db, "utf16_aligned",
        SQLITE_UTF16 | SQLITE_UTF16_ALIGNED, 
        0, alignmentCollFunc);
  }
  return SQLITE_OK;
}
#endif /* !defined(SQLITE_OMIT_UTF16) */

/*
** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
**
** This function is used to test that SQLite selects the correct user
** function callback when multiple versions (for different text encodings)
** are available.
................................................................................
#endif

#ifndef SQLITE_OMIT_UTF16
     { "sqlite3_column_bytes16",    test_stmt_int,   sqlite3_column_bytes16   },
     { "sqlite3_column_text16",     test_stmt_utf16, sqlite3_column_text16    },
     { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
     { "sqlite3_column_name16",     test_stmt_utf16, sqlite3_column_name16    },
     { "add_alignment_test_collations", add_alignment_test_collations, 0      },
#ifdef SQLITE_ENABLE_COLUMN_METADATA
{"sqlite3_column_database_name16",
  test_stmt_utf16, sqlite3_column_database_name16},
{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16},
{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16},
#endif
#endif
................................................................................
      (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite3_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3_os_trace, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite3_tsd_count",
      (char*)&sqlite3_tsd_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "unaligned_string_counter",
      (char*)&unaligned_string_counter, TCL_LINK_INT);
#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
  Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks",
      (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT);
#endif
#ifndef SQLITE_OMIT_UTF16
  Tcl_LinkVar(interp, "sqlite_last_needed_collation",
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);

Changes to src/vdbemem.c.

37
38
39
40
41
42
43

44
45
46
47
48
49
50
...
592
593
594
595
596
597
598


599
600
601
602
603
604

605

606
607
608

609



610
611
612
613
614
615
616
617
618
...
748
749
750
751
752
753
754




755
756
757
758
759
760
761
762
763
764
765
766






767
768

769
770
771





772
773
774
775
776
777
778
  int rc;
  if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
    return SQLITE_OK;
  }
#ifdef SQLITE_OMIT_UTF16
  return SQLITE_ERROR;
#else


  /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
  ** then the encoding of the value may not have changed.
  */
  rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
  assert(rc==SQLITE_OK    || rc==SQLITE_NOMEM);
  assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
................................................................................
    ** the user deletes the collation sequence after the vdbe program is
    ** compiled (this was not always the 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{
        u8 origEnc = pMem1->enc;
        rc = pColl->xCmp(
          pColl->pUser,
          sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc),

          sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc),

          sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc),
          sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc)
        );

        sqlite3ValueBytes((sqlite3_value*)pMem1, origEnc);



        sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
        sqlite3ValueBytes((sqlite3_value*)pMem2, origEnc);
        sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
        return rc;
      }
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().  */
  }
................................................................................
#endif

/* This function is only available internally, it is not part of the
** external API. It works in a similar way to sqlite3_value_text(),
** except the data returned is in the encoding specified by the second
** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
** SQLITE_UTF8.




*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
  if( !pVal ) return 0;
  assert( enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE || enc==SQLITE_UTF8);

  if( pVal->flags&MEM_Null ){
    return 0;
  }
  assert( (MEM_Blob>>3) == MEM_Str );
  pVal->flags |= (pVal->flags & MEM_Blob)>>3;
  if( pVal->flags&MEM_Str ){
    sqlite3VdbeChangeEncoding(pVal, enc);






  }else if( !(pVal->flags&MEM_Blob) ){
    sqlite3VdbeMemStringify(pVal, enc);

  }
  assert(pVal->enc==enc || sqlite3MallocFailed() );
  return (const void *)(pVal->enc==enc ? (pVal->z) : 0);





}

/*
** Create a new sqlite3_value object.
*/
sqlite3_value* sqlite3ValueNew(void){
  Mem *p = sqliteMalloc(sizeof(*p));







>







 







>
>



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

<







 







>
>
>
>



|







|
>
>
>
>
>
>


>

|
<
>
>
>
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618

619
620
621
622
623
624
625
...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800
  int rc;
  if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
    return SQLITE_OK;
  }
#ifdef SQLITE_OMIT_UTF16
  return SQLITE_ERROR;
#else


  /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
  ** then the encoding of the value may not have changed.
  */
  rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
  assert(rc==SQLITE_OK    || rc==SQLITE_NOMEM);
  assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
................................................................................
    ** the user deletes the collation sequence after the vdbe program is
    ** compiled (this was not always the case).
    */
    assert( !pColl || pColl->xCmp );

    if( pColl ){
      if( pMem1->enc==pColl->enc ){
        /* The strings are already in the correct encoding.  Call the
        ** comparison function directly */
        return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
      }else{
        u8 origEnc = pMem1->enc;
        const void *v1, *v2;
        int n1, n2;
        /* Convert the strings into the encoding that the comparison
        ** function expects */
        v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
        n1 = v1==0 ? 0 : pMem1->n;
        assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
        v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);

        n2 = v2==0 ? 0 : pMem2->n;
        assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
        /* Do the comparison */
        rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
        /* Convert the strings back into the database encoding */
        sqlite3ValueText((sqlite3_value*)pMem1, origEnc);

        sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
        return rc;
      }
    }
    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().  */
  }
................................................................................
#endif

/* This function is only available internally, it is not part of the
** external API. It works in a similar way to sqlite3_value_text(),
** except the data returned is in the encoding specified by the second
** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
** SQLITE_UTF8.
**
** (2006-02-16:)  The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
** If that is the case, then the result must be aligned on an even byte
** boundary.
*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
  if( !pVal ) return 0;
  assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );

  if( pVal->flags&MEM_Null ){
    return 0;
  }
  assert( (MEM_Blob>>3) == MEM_Str );
  pVal->flags |= (pVal->flags & MEM_Blob)>>3;
  if( pVal->flags&MEM_Str ){
    sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
    if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){
      assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
      if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
        return 0;
      }
    }
  }else if( !(pVal->flags&MEM_Blob) ){
    sqlite3VdbeMemStringify(pVal, enc);
    assert( 0==(1&(int)pVal->z) );
  }
  assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || sqlite3MallocFailed() );

  if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
    return pVal->z;
  }else{
    return 0;
  }
}

/*
** Create a new sqlite3_value object.
*/
sqlite3_value* sqlite3ValueNew(void){
  Mem *p = sqliteMalloc(sizeof(*p));

Added test/utf16align.test.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 2006 February 16
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    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.
#
#***********************************************************************
# 
# This file contains code to verify that the SQLITE_UTF16_ALIGNED
# flag passed into the sqlite3_create_collation() function insures
# that all strings passed to that function are aligned on an even
# byte boundary.
#
# $Id: utf16align.test,v 1.1 2006/02/16 18:16:38 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Skip this entire test if we do not support UTF16
#
ifcapable !utf16 {
  finish_test
  return
}

# Create a database with a UTF16 encoding.  Put in lots of string
# data of varying lengths.
#
do_test utf16align-1.0 {
  set unaligned_string_counter 0
  add_alignment_test_collations [sqlite3_connection_pointer db]
  execsql {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(
      id INTEGER PRIMARY KEY,
      spacer TEXT,
      a TEXT COLLATE utf16_aligned,
      b TEXT COLLATE utf16_unaligned
    );
    INSERT INTO t1(a) VALUES("abc");
    INSERT INTO t1(a) VALUES("defghi");
    INSERT INTO t1(a) VALUES("jklmnopqrstuv");
    INSERT INTO t1(a) VALUES("wxyz0123456789-");
    UPDATE t1 SET b=a||'-'||a;
    INSERT INTO t1(a,b) SELECT a||b, b||a FROM t1;
    INSERT INTO t1(a,b) SELECT a||b, b||a FROM t1;
    INSERT INTO t1(a,b) SELECT a||b, b||a FROM t1;
    INSERT INTO t1(a,b) VALUES('one','two');
    INSERT INTO t1(a,b) SELECT a, b FROM t1;
    UPDATE t1 SET spacer = CASE WHEN rowid&1 THEN 'x' ELSE 'xx' END;
    SELECT count(*) FROM t1;
  }
} 66
do_test utf16align-1.1 {
  set unaligned_string_counter
} 0

# Creating an index that uses the unaligned collation.  We should see
# some unaligned strings passed to the collating function.
#
do_test utf16align-1.2 {
  execsql {
    CREATE INDEX t1i1 ON t1(spacer, b);
  }
  # puts $unaligned_string_counter
  expr {$unaligned_string_counter>0}
} 1

# Create another index that uses the aligned collation.  This time
# there should be no unaligned accesses
#
do_test utf16align-1.3 {
  set unaligned_string_counter 0
  execsql {
    CREATE INDEX t1i2 ON t1(spacer, a);
  }
  expr {$unaligned_string_counter>0}
} 0
integrity_check utf16align-1.4

finish_test