1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-15 11:41:13 +03:00

Use the unicode API to win32 where available.

Tickets #1407, #1396, #1331, #1243, #1206 (CVS 2656)

FossilOrigin-Name: 3ec58c673ae4cf0695ea0c287cc9bcbdcdb1a200
This commit is contained in:
drh
2005-09-05 19:08:29 +00:00
parent a21c8495f9
commit c092998715
4 changed files with 239 additions and 72 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sover-aggressive\soptimization\sof\sORDER\sBY\sas\sreported\son\sthe\smailing\slist.\s(CVS\s2655) C Use\sthe\sunicode\sAPI\sto\swin32\swhere\savailable.\r\nTickets\s#1407,\s#1396,\s#1331,\s#1243,\s#1206\s(CVS\s2656)
D 2005-09-01T17:47:51 D 2005-09-05T19:08:29
F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -54,7 +54,7 @@ F src/os_test.c 91e5f22dd89491e5e1554820e715805f43fa4ece
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
F src/os_unix.c b4c4592589113db088662ef7570967ec36022b5d F src/os_unix.c b4c4592589113db088662ef7570967ec36022b5d
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c fe7b99cfcfb61d9bf54493ddf5857885a657fb89 F src/os_win.c 8b80f418aefd2ceabe3580f680f5dcc244cf2344
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c cd9896287a8fd33cc267bd0c2b69c421a4808169 F src/pager.c cd9896287a8fd33cc267bd0c2b69c421a4808169
F src/pager.h 17b13225abd93c1e9f470060f40a21b9edb5a164 F src/pager.h 17b13225abd93c1e9f470060f40a21b9edb5a164
@@ -69,7 +69,7 @@ F src/sqlite.h.in d6561d51025d08de4f455607f3f9f9aa76e855d5
F src/sqliteInt.h 845ff6f8019f80baafb1bdbb8ef80fcd04d9d0f9 F src/sqliteInt.h 845ff6f8019f80baafb1bdbb8ef80fcd04d9d0f9
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c ac94682f9e601dd373912c46414a5a842db2089a F src/tclsqlite.c ac94682f9e601dd373912c46414a5a842db2089a
F src/test1.c ca4b959ce0a966ede87727cd8d3f5905743dfd4e F src/test1.c 006fafaa3456d20db37951b94c9d9becac64568e
F src/test2.c 792f203be69fea88668fa221321194f0a28dfdfa F src/test2.c 792f203be69fea88668fa221321194f0a28dfdfa
F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7 F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7
F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f
@@ -306,7 +306,7 @@ F www/tclsqlite.tcl 3df553505b6efcad08f91e9b975deb2e6c9bb955
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 81259a01f1e85ba50a1d017b1282bf841b16f0a5 P efbb4bc83cd86b6a26d58c5818c58c2e3edaab18
R 9230534585e06aeccca811dde76702e9 R d11951b0db345c53b16225d15ddfa80a
U drh U drh
Z 91850feb3a4a5d6eb41e5886f9a1b320 Z ce91eee65efcee02daeb83c44469f09e

View File

@@ -1 +1 @@
efbb4bc83cd86b6a26d58c5818c58c2e3edaab18 3ec58c673ae4cf0695ea0c287cc9bcbdcdb1a200

View File

@@ -41,11 +41,99 @@
*/ */
#ifndef SQLITE_OMIT_DISKIO #ifndef SQLITE_OMIT_DISKIO
/*
** The following variable is (normally) set once and never changes
** thereafter. It records whether the operating system is Win95
** or WinNT.
**
** 0: Operating system unknown.
** 1: Operating system is Win95.
** 2: Operating system is WinNT.
**
** In order to facilitate testing on a WinNT system, the test fixture
** can manually set this value to 1 to emulate Win98 behavior.
*/
int sqlite3_os_type = 0;
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
static int isNT(void){
if( sqlite3_os_type==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return sqlite3_os_type==2;
}
/*
** Convert a UTF-8 string to UTF-32. Space to hold the returned string
** is obtained from sqliteMalloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
int nByte;
WCHAR *zWideFilename;
if( !isNT() ){
return 0;
}
nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
zWideFilename = sqliteMalloc( nByte );
if( zWideFilename==0 ){
return 0;
}
nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte);
if( nByte==0 ){
sqliteFree(zWideFilename);
zWideFilename = 0;
}
return zWideFilename;
}
/*
** Convert UTF-32 to UTF-8. Space to hold the returned string is
** obtained from sqliteMalloc().
*/
static char *unicodeToUtf8(const WCHAR *zWideFilename){
int nByte;
char *zFilename;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
zFilename = sqliteMalloc( nByte );
if( zFilename==0 ){
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
0, 0);
if( nByte == 0 ){
sqliteFree(zFilename);
zFilename = 0;
}
return zFilename;
}
/* /*
** Delete the named file ** Delete the named file
*/ */
int sqlite3OsDelete(const char *zFilename){ int sqlite3OsDelete(const char *zFilename){
DeleteFileA(zFilename); WCHAR *zWide = utf8ToUnicode(zFilename);
if( zWide ){
DeleteFileW(zWide);
sqliteFree(zWide);
}else{
DeleteFileA(zFilename);
}
TRACE2("DELETE \"%s\"\n", zFilename); TRACE2("DELETE \"%s\"\n", zFilename);
return SQLITE_OK; return SQLITE_OK;
} }
@@ -54,7 +142,15 @@ int sqlite3OsDelete(const char *zFilename){
** Return TRUE if the named file exists. ** Return TRUE if the named file exists.
*/ */
int sqlite3OsFileExists(const char *zFilename){ int sqlite3OsFileExists(const char *zFilename){
return GetFileAttributesA(zFilename) != 0xffffffff; int exists = 0;
WCHAR *zWide = utf8ToUnicode(zFilename);
if( zWide ){
exists = GetFileAttributesW(zWide) != 0xffffffff;
sqliteFree(zWide);
}else{
exists = GetFileAttributesA(zFilename) != 0xffffffff;
}
return exists;
} }
/* /*
@@ -76,30 +172,60 @@ int sqlite3OsOpenReadWrite(
int *pReadonly int *pReadonly
){ ){
HANDLE h; HANDLE h;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen ); assert( !id->isOpen );
h = CreateFileA(zFilename, if( zWide ){
GENERIC_READ | GENERIC_WRITE, h = CreateFileW(zWide,
FILE_SHARE_READ | FILE_SHARE_WRITE, GENERIC_READ | GENERIC_WRITE,
NULL, FILE_SHARE_READ | FILE_SHARE_WRITE,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
h = CreateFileA(zFilename,
GENERIC_READ,
FILE_SHARE_READ,
NULL, NULL,
OPEN_ALWAYS, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL NULL
); );
if( h==INVALID_HANDLE_VALUE ){ if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN; h = CreateFileW(zWide,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
sqliteFree(zWide);
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
} }
*pReadonly = 1; sqliteFree(zWide);
}else{ }else{
*pReadonly = 0; h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
h = CreateFileA(zFilename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
} }
id->h = h; id->h = h;
id->locktype = NO_LOCK; id->locktype = NO_LOCK;
@@ -128,6 +254,7 @@ int sqlite3OsOpenReadWrite(
int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
HANDLE h; HANDLE h;
int fileflags; int fileflags;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen ); assert( !id->isOpen );
if( delFlag ){ if( delFlag ){
fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
@@ -135,14 +262,26 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
}else{ }else{
fileflags = FILE_FLAG_RANDOM_ACCESS; fileflags = FILE_FLAG_RANDOM_ACCESS;
} }
h = CreateFileA(zFilename, if( zWide ){
GENERIC_READ | GENERIC_WRITE, h = CreateFileW(zWide,
0, GENERIC_READ | GENERIC_WRITE,
NULL, 0,
CREATE_ALWAYS, NULL,
fileflags, CREATE_ALWAYS,
NULL fileflags,
); NULL
);
sqliteFree(zWide);
}else{
h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
fileflags,
NULL
);
}
if( h==INVALID_HANDLE_VALUE ){ if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN; return SQLITE_CANTOPEN;
} }
@@ -164,15 +303,28 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
*/ */
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
HANDLE h; HANDLE h;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen ); assert( !id->isOpen );
h = CreateFileA(zFilename, if( zWide ){
GENERIC_READ, h = CreateFileW(zWide,
0, GENERIC_READ,
NULL, 0,
OPEN_EXISTING, NULL,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, OPEN_EXISTING,
NULL FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
); NULL
);
sqliteFree(zWide);
}else{
h = CreateFileA(zFilename,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
}
if( h==INVALID_HANDLE_VALUE ){ if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN; return SQLITE_CANTOPEN;
} }
@@ -229,6 +381,16 @@ int sqlite3OsTempFileName(char *zBuf){
if( sqlite3_temp_directory ){ if( sqlite3_temp_directory ){
strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
}else if( isNT() ){
char *zMulti;
WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
zMulti = unicodeToUtf8(zWidePath);
if( zMulti ){
memcpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
sqliteFree(zMulti);
}
}else{ }else{
GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
} }
@@ -364,28 +526,6 @@ int sqlite3OsFileSize(OsFile *id, i64 *pSize){
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
static int isNT(void){
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
if( osType==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return osType==2;
}
/* /*
** Acquire a reader lock. ** Acquire a reader lock.
** Different API routines are called depending on whether or not this ** Different API routines are called depending on whether or not this
@@ -426,11 +566,18 @@ static int unlockReadLock(OsFile *id){
** Check that a given pathname is a directory and is writable ** Check that a given pathname is a directory and is writable
** **
*/ */
int sqlite3OsIsDirWritable(char *zBuf){ int sqlite3OsIsDirWritable(char *zDirname){
int fileAttr; int fileAttr;
if(! zBuf ) return 0; WCHAR *zWide;
if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0; if( zDirname==0 ) return 0;
fileAttr = GetFileAttributesA(zBuf); if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
zWide = utf8ToUnicode(zDirname);
if( zWide ){
fileAttr = GetFileAttributesW(zWide);
sqliteFree(zWide);
}else{
fileAttr = GetFileAttributesA(zDirname);
}
if( fileAttr == 0xffffffff ) return 0; if( fileAttr == 0xffffffff ) return 0;
if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
return 0; return 0;
@@ -641,6 +788,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
char *sqlite3OsFullPathname(const char *zRelative){ char *sqlite3OsFullPathname(const char *zRelative){
char *zNotUsed; char *zNotUsed;
char *zFull; char *zFull;
WCHAR *zWide;
int nByte; int nByte;
#ifdef __CYGWIN__ #ifdef __CYGWIN__
nByte = strlen(zRelative) + MAX_PATH + 1001; nByte = strlen(zRelative) + MAX_PATH + 1001;
@@ -648,10 +796,22 @@ char *sqlite3OsFullPathname(const char *zRelative){
if( zFull==0 ) return 0; if( zFull==0 ) return 0;
if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
#else #else
nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1; zWide = utf8ToUnicode(zRelative);
zFull = sqliteMalloc( nByte ); if( zWide ){
if( zFull==0 ) return 0; WCHAR *zTemp, *zNotUsedW;
GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed); nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
if( zTemp==0 ) return 0;
GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
sqliteFree(zWide);
zFull = unicodeToUtf8(zTemp);
sqliteFree(zTemp);
}else{
nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
if( zFull==0 ) return 0;
GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
}
#endif #endif
return zFull; return zFull;
} }

View File

@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test1.c,v 1.158 2005/09/01 12:16:29 drh Exp $ ** $Id: test1.c,v 1.159 2005/09/05 19:08:29 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@@ -3157,6 +3157,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_memMax; extern int sqlite3_memMax;
extern char sqlite3_query_plan[]; extern char sqlite3_query_plan[];
extern int sqlite3_like_count; extern int sqlite3_like_count;
#if OS_WIN
extern int sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
extern int sqlite3_vdbe_addop_trace; extern int sqlite3_vdbe_addop_trace;
#endif #endif
@@ -3185,6 +3188,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_os_trace, TCL_LINK_INT); (char*)&sqlite3_os_trace, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_where_trace", Tcl_LinkVar(interp, "sqlite_where_trace",
(char*)&sqlite3_where_trace, TCL_LINK_INT); (char*)&sqlite3_where_trace, TCL_LINK_INT);
#if OS_WIN
Tcl_LinkVar(interp, "sqlite_os_type",
(char*)&sqlite3_os_type, TCL_LINK_INT);
#endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
Tcl_LinkVar(interp, "sqlite_addop_trace", Tcl_LinkVar(interp, "sqlite_addop_trace",
(char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT); (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);