Skip to content

Commit da982b9

Browse files
committed
Update SQLite sources to version 3.52.0
- Adjust sources of extensions - Adjust script for patching the shell source
1 parent 322ed89 commit da982b9

File tree

13 files changed

+39897
-32969
lines changed

13 files changed

+39897
-32969
lines changed

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ The code was mainly developed under Windows, but was tested under Linux as well.
1010

1111
## Version information
1212

13-
* 2.3.0 - Release planned for *March 2026*
14-
- Based on SQLite version 3.51.2, maybe update to version 3.52.0
13+
* 2.3.0 - *March 2026*
14+
- Based on SQLite version 3.52.0
1515
- Updated Visual Studio solution files to support VS2026
1616
- Unified architecture names in build files (use _x64_ instead of _Win64_) (to avoid VS2026 conflicts)
1717
- Support compiling for ARM64EC (affects AEGIS code only) (issue #222)

scripts/patchshell.sh

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ die() {
1717
sed -e '/^ sputf(stdout, "SQLite version/{n;N;d}' "$INPUT" \
1818
| sed '/#ifdef SQLITE_CUSTOM_INCLUDE/!{p;d;};n;n;n;a #if SQLITE3MC_USE_MINIZ != 0 && !defined(SQLITE_ENABLE_COMPRESS)\n#include "miniz.c"\n#ifdef SQLITE_HAVE_ZLIB\n#undef SQLITE_HAVE_ZLIB\n#endif\n#define SQLITE_HAVE_ZLIB 1\n#endif\n' \
1919
| sed '/#include <zlib.h>/c #include "zlibwrap.h"' \
20-
| sed '/^ sqlite3_fprintf(stdout,$/c \ extern const char* sqlite3mc_version();\n sqlite3_fprintf(stdout,' \
20+
| sed '/^ cli_printf(stdout,$/c \ extern const char* sqlite3mc_version();\n cli_printf(stdout,' \
2121
| sed '/^ "SQLite version/c \ "SQLite version \%s \%.19s" \/\*extra-version-info\*\/\n " (\%s)\\n" \/\*SQLite3-Multiple-Ciphers-version-info\*\/' \
2222
| sed '/^ sqlite3_libversion(), sqlite3_sourceid());/c \ sqlite3_libversion(), sqlite3_sourceid(), sqlite3mc_version());' \
23-
| sed '/^ sqlite3_libversion(), sqlite3_sourceid());/a \ extern const char* sqlite3mc_version();\n sqlite3_fprintf(p->out, "\%s\\n", sqlite3mc_version());' \
24-
| sed '/Begin ..\/ext\/misc\/shathree.c/i #ifndef SQLITE_OMIT_SHELL_SHATHREE' \
25-
| sed '/End ..\/ext\/misc\/shathree.c/a #endif' \
26-
| sed '/Begin ..\/ext\/misc\/series.c/i #ifndef SQLITE_OMIT_SHELL_SERIES' \
27-
| sed '/End ..\/ext\/misc\/series.c/a #endif' \
28-
| sed '/Begin ..\/ext\/misc\/regexp.c/i #ifndef SQLITE_OMIT_SHELL_REGEXP' \
29-
| sed '/End ..\/ext\/misc\/regexp.c/a #endif' \
23+
| sed '/^ sqlite3_libversion(), sqlite3_sourceid());/a \ extern const char* sqlite3mc_version();\n cli_printf(p->out, "\%s\\n", sqlite3mc_version());' \
24+
| sed '/Begin ext\/misc\/shathree.c/i #ifndef SQLITE_OMIT_SHELL_SHATHREE' \
25+
| sed '/End ext\/misc\/shathree.c/a #endif' \
26+
| sed '/Begin ext\/misc\/series.c/i #ifndef SQLITE_OMIT_SHELL_SERIES' \
27+
| sed '/End ext\/misc\/series.c/a #endif' \
28+
| sed '/Begin ext\/misc\/regexp.c/i #ifndef SQLITE_OMIT_SHELL_REGEXP' \
29+
| sed '/End ext\/misc\/regexp.c/a #endif' \
3030
| sed '/sqlite3_shathree_init(p->db, 0, 0);/i #ifndef SQLITE_OMIT_SHELL_SHATHREE' \
3131
| sed '/sqlite3_shathree_init(p->db, 0, 0);/a #endif' \
3232
| sed '/sqlite3_series_init(p->db, 0, 0);/i #ifndef SQLITE_OMIT_SHELL_SERIES' \

src/csv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
** schema= parameter, like this:
2525
**
2626
** CREATE VIRTUAL TABLE temp.csv2 USING csv(
27-
** filename = "../http.log",
28-
** schema = "CREATE TABLE x(date,ipaddr,url,referrer,userAgent)"
27+
** filename = '../http.log',
28+
** schema = 'CREATE TABLE x(date,ipaddr,url,referrer,userAgent)'
2929
** );
3030
**
3131
** Instead of specifying a file, the text of the CSV can be loaded using

src/fileio.c

Lines changed: 173 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,16 @@ SQLITE_EXTENSION_INIT1
9494
# include <utime.h>
9595
# include <sys/time.h>
9696
# define STRUCT_STAT struct stat
97+
# include <limits.h>
98+
# include <stdlib.h>
9799
#else
98100
# include "windirent.h"
99101
# include <direct.h>
100102
# define STRUCT_STAT struct _stat
101103
# define chmod(path,mode) fileio_chmod(path,mode)
102104
# define mkdir(path,mode) fileio_mkdir(path)
105+
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
106+
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
103107
#endif
104108
#include <time.h>
105109
#include <errno.h>
@@ -131,12 +135,9 @@ SQLITE_EXTENSION_INIT1
131135
*/
132136
#if defined(_WIN32) || defined(WIN32)
133137
static int fileio_chmod(const char *zPath, int pmode){
134-
sqlite3_int64 sz = strlen(zPath);
135-
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
136138
int rc;
139+
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
137140
if( b1==0 ) return -1;
138-
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
139-
b1[sz] = 0;
140141
rc = _wchmod(b1, pmode);
141142
sqlite3_free(b1);
142143
return rc;
@@ -148,12 +149,9 @@ static int fileio_chmod(const char *zPath, int pmode){
148149
*/
149150
#if defined(_WIN32) || defined(WIN32)
150151
static int fileio_mkdir(const char *zPath){
151-
sqlite3_int64 sz = strlen(zPath);
152-
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
153152
int rc;
153+
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
154154
if( b1==0 ) return -1;
155-
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
156-
b1[sz] = 0;
157155
rc = _wmkdir(b1);
158156
sqlite3_free(b1);
159157
return rc;
@@ -266,50 +264,7 @@ static sqlite3_uint64 fileTimeToUnixTime(
266264

267265
return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
268266
}
269-
270-
271-
#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
272-
# /* To allow a standalone DLL, use this next replacement function: */
273-
# undef sqlite3_win32_utf8_to_unicode
274-
# define sqlite3_win32_utf8_to_unicode utf8_to_utf16
275-
#
276-
LPWSTR utf8_to_utf16(const char *z){
277-
int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
278-
LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
279-
if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
280-
return rv;
281-
sqlite3_free(rv);
282-
return 0;
283-
}
284-
#endif
285-
286-
/*
287-
** This function attempts to normalize the time values found in the stat()
288-
** buffer to UTC. This is necessary on Win32, where the runtime library
289-
** appears to return these values as local times.
290-
*/
291-
static void statTimesToUtc(
292-
const char *zPath,
293-
STRUCT_STAT *pStatBuf
294-
){
295-
HANDLE hFindFile;
296-
WIN32_FIND_DATAW fd;
297-
LPWSTR zUnicodeName;
298-
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
299-
zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
300-
if( zUnicodeName ){
301-
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
302-
hFindFile = FindFirstFileW(zUnicodeName, &fd);
303-
if( hFindFile!=NULL ){
304-
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
305-
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
306-
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
307-
FindClose(hFindFile);
308-
}
309-
sqlite3_free(zUnicodeName);
310-
}
311-
}
312-
#endif
267+
#endif /* _WIN32 */
313268

314269
/*
315270
** This function is used in place of stat(). On Windows, special handling
@@ -321,14 +276,22 @@ static int fileStat(
321276
STRUCT_STAT *pStatBuf
322277
){
323278
#if defined(_WIN32)
324-
sqlite3_int64 sz = strlen(zPath);
325-
wchar_t *b1 = sqlite3_malloc64( (sz+1)*sizeof(b1[0]) );
326279
int rc;
280+
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
327281
if( b1==0 ) return 1;
328-
sz = MultiByteToWideChar(CP_UTF8, 0, zPath, sz, b1, sz);
329-
b1[sz] = 0;
330282
rc = _wstat(b1, pStatBuf);
331-
if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
283+
if( rc==0 ){
284+
HANDLE hFindFile;
285+
WIN32_FIND_DATAW fd;
286+
memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
287+
hFindFile = FindFirstFileW(b1, &fd);
288+
if( hFindFile!=NULL ){
289+
pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
290+
pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
291+
pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
292+
FindClose(hFindFile);
293+
}
294+
}
332295
sqlite3_free(b1);
333296
return rc;
334297
#else
@@ -460,7 +423,6 @@ static int writeFile(
460423

461424
if( mtime>=0 ){
462425
#if defined(_WIN32)
463-
#if !SQLITE_OS_WINRT
464426
/* Windows */
465427
FILETIME lastAccess;
466428
FILETIME lastWrite;
@@ -491,7 +453,6 @@ static int writeFile(
491453
}else{
492454
return 1;
493455
}
494-
#endif
495456
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
496457
/* Recent unix */
497458
struct timespec times[2];
@@ -1095,6 +1056,154 @@ static int fsdirRegister(sqlite3 *db){
10951056
# define fsdirRegister(x) SQLITE_OK
10961057
#endif
10971058

1059+
/*
1060+
** This version of realpath() works on any system. The string
1061+
** returned is held in memory allocated using sqlite3_malloc64().
1062+
** The caller is responsible for calling sqlite3_free().
1063+
*/
1064+
static char *portable_realpath(const char *zPath){
1065+
#if !defined(_WIN32) /* BEGIN unix */
1066+
1067+
char *zOut = 0; /* Result */
1068+
char *z; /* Temporary buffer */
1069+
#if defined(PATH_MAX)
1070+
char zBuf[PATH_MAX+1]; /* Space for the temporary buffer */
1071+
#endif
1072+
1073+
if( zPath==0 ) return 0;
1074+
#if defined(PATH_MAX)
1075+
z = realpath(zPath, zBuf);
1076+
if( z ){
1077+
zOut = sqlite3_mprintf("%s", zBuf);
1078+
}
1079+
#endif /* defined(PATH_MAX) */
1080+
if( zOut==0 ){
1081+
/* Try POSIX.1-2008 malloc behavior */
1082+
z = realpath(zPath, NULL);
1083+
if( z ){
1084+
zOut = sqlite3_mprintf("%s", z);
1085+
free(z);
1086+
}
1087+
}
1088+
return zOut;
1089+
1090+
#else /* End UNIX, Begin WINDOWS */
1091+
1092+
wchar_t *zPath16; /* UTF16 translation of zPath */
1093+
char *zOut = 0; /* Result */
1094+
wchar_t *z = 0; /* Temporary buffer */
1095+
1096+
if( zPath==0 ) return 0;
1097+
1098+
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
1099+
if( zPath16==0 ) return 0;
1100+
z = _wfullpath(NULL, zPath16, 0);
1101+
sqlite3_free(zPath16);
1102+
if( z ){
1103+
zOut = sqlite3_win32_unicode_to_utf8(z);
1104+
free(z);
1105+
}
1106+
return zOut;
1107+
1108+
#endif /* End WINDOWS, Begin common code */
1109+
}
1110+
1111+
/*
1112+
** SQL function: realpath(X)
1113+
**
1114+
** Try to convert file or pathname X into its real, absolute pathname.
1115+
** Return NULL if unable.
1116+
**
1117+
** The file or directory X is not required to exist. The answer is formed
1118+
** by calling system realpath() on the prefix of X that does exist and
1119+
** appending the tail of X that does not (yet) exist.
1120+
*/
1121+
static void realpathFunc(
1122+
sqlite3_context *context,
1123+
int argc,
1124+
sqlite3_value **argv
1125+
){
1126+
const char *zPath; /* Original input path */
1127+
char *zCopy; /* An editable copy of zPath */
1128+
char *zOut; /* The result */
1129+
char cSep = 0; /* Separator turned into \000 */
1130+
size_t len; /* Prefix length before cSep */
1131+
#ifdef _WIN32
1132+
const int isWin = 1;
1133+
#else
1134+
const int isWin = 0;
1135+
#endif
1136+
1137+
(void)argc;
1138+
zPath = (const char*)sqlite3_value_text(argv[0]);
1139+
if( zPath==0 ) return;
1140+
if( zPath[0]==0 ) zPath = ".";
1141+
zCopy = sqlite3_mprintf("%s",zPath);
1142+
len = strlen(zCopy);
1143+
while( len>1 && (zCopy[len-1]=='/' || (isWin && zCopy[len-1]=='\\')) ){
1144+
len--;
1145+
}
1146+
zCopy[len] = 0;
1147+
while( 1 /*exit-by-break*/ ){
1148+
zOut = portable_realpath(zCopy);
1149+
zCopy[len] = cSep;
1150+
if( zOut ){
1151+
if( cSep ){
1152+
zOut = sqlite3_mprintf("%z%s",zOut,&zCopy[len]);
1153+
}
1154+
break;
1155+
}else{
1156+
size_t i = len-1;
1157+
while( i>0 ){
1158+
if( zCopy[i]=='/' || (isWin && zCopy[i]=='\\') ) break;
1159+
i--;
1160+
}
1161+
if( i<=0 ){
1162+
if( zCopy[0]=='/' ){
1163+
zOut = zCopy;
1164+
zCopy = 0;
1165+
}else if( (zOut = portable_realpath("."))!=0 ){
1166+
zOut = sqlite3_mprintf("%z/%s", zOut, zCopy);
1167+
}
1168+
break;
1169+
}
1170+
cSep = zCopy[i];
1171+
zCopy[i] = 0;
1172+
len = i;
1173+
}
1174+
}
1175+
sqlite3_free(zCopy);
1176+
if( zOut ){
1177+
/* Simplify any "/./" or "/../" that might have snuck into the
1178+
** pathname due to appending of zCopy. We only have to consider
1179+
** unix "/" separators, because the _wfilepath() system call on
1180+
** Windows will have already done this simplification for us. */
1181+
size_t i, j, n;
1182+
n = strlen(zOut);
1183+
for(i=j=0; i<n; i++){
1184+
if( zOut[i]=='/' ){
1185+
if( zOut[i+1]=='/' ) continue;
1186+
if( zOut[i+1]=='.' && i+2<n && zOut[i+2]=='/' ){
1187+
i += 1;
1188+
continue;
1189+
}
1190+
if( zOut[i+1]=='.' && i+3<n && zOut[i+2]=='.' && zOut[i+3]=='/' ){
1191+
while( j>0 && zOut[j-1]!='/' ){ j--; }
1192+
if( j>0 ){ j--; }
1193+
i += 2;
1194+
continue;
1195+
}
1196+
}
1197+
zOut[j++] = zOut[i];
1198+
}
1199+
zOut[j] = 0;
1200+
1201+
/* Return the result */
1202+
sqlite3_result_text(context, zOut, -1, sqlite3_free);
1203+
}
1204+
}
1205+
1206+
10981207
#ifndef SQLITE_API
10991208
#define SQLITE_API
11001209
#endif
@@ -1122,5 +1231,10 @@ int sqlite3_fileio_init(
11221231
if( rc==SQLITE_OK ){
11231232
rc = fsdirRegister(db);
11241233
}
1234+
if( rc==SQLITE_OK ){
1235+
rc = sqlite3_create_function(db, "realpath", 1,
1236+
SQLITE_UTF8, 0,
1237+
realpathFunc, 0, 0);
1238+
}
11251239
return rc;
11261240
}

0 commit comments

Comments
 (0)