Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Update the built-in SQLite to the latest trunk version that is destined to become 3.45.0 someday. This is beta-testing for SQLite. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
70cae0a964299bb22c02e2da0d2be0ad |
| User & Date: | drh 2023-12-14 17:24:49.650 |
Context
|
2023-12-22
| ||
| 14:27 | Remove the write-perms check from the /ajax/preview-text route so that folks without checkin permissions can use /chat. Problem reported in [forum:ed4a762b3a557898|forum post ed4a762b3a557898]. Some code-adjacent end-of-line whitespace cleanups. check-in: 0c6e669a7b user: stephan tags: trunk | |
|
2023-12-16
| ||
| 01:10 | In /wikiedit and /fileedit, add a checkbox to disable shift-enter for toggling preview, as per discussion in [forum:dbd5b68366147ce8|forum post dbd5b68366147ce8]. check-in: 8c1c4fa985 user: stephan tags: shift-enter-preview | |
|
2023-12-14
| ||
| 17:24 | Update the built-in SQLite to the latest trunk version that is destined to become 3.45.0 someday. This is beta-testing for SQLite. check-in: 70cae0a964 user: drh tags: trunk | |
| 16:29 | Improve "whatis" output when in "filename" mode and parse supported whatis options when using "fossil all whatis". check-in: e1e9da26f6 user: mgagnon tags: trunk | |
Changes
Changes to extsrc/shell.c.
| ︙ | ︙ | |||
430 431 432 433 434 435 436 | ** accepted char or character sequence is limited by nAccept. ** ** Returns the number of accepted char values. */ #ifdef CONSIO_SPUTB SQLITE_INTERNAL_LINKAGE int fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept); | < > | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | ** accepted char or character sequence is limited by nAccept. ** ** Returns the number of accepted char values. */ #ifdef CONSIO_SPUTB SQLITE_INTERNAL_LINKAGE int fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept); /* Like fPutbUtf8 except stream is always the designated output. */ #endif SQLITE_INTERNAL_LINKAGE int oPutbUtf8(const char *cBuf, int nAccept); /* Like fPutbUtf8 except stream is always the designated error. */ #ifdef CONSIO_EPUTB SQLITE_INTERNAL_LINKAGE int ePutbUtf8(const char *cBuf, int nAccept); #endif |
| ︙ | ︙ | |||
1096 1097 1098 1099 1100 1101 1102 |
}
}
return z;
}
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
#ifndef SQLITE_CIO_NO_TRANSLATE
| < | | | | | | | 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 |
}
}
return z;
}
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
#ifndef SQLITE_CIO_NO_TRANSLATE
# ifdef CONSIO_SPUTB
SQLITE_INTERNAL_LINKAGE int
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
assert(pfO!=0);
# if CIO_WIN_WC_XLATE
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
if( pstReachesConsole(ppst) ){
int rv;
maybeSetupAsConsole(ppst, 1);
rv = conZstrEmit(ppst, cBuf, nAccept);
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
return rv;
}else {
# endif
return (int)fwrite(cBuf, 1, nAccept, pfO);
# if CIO_WIN_WC_XLATE
}
# endif
}
# endif
SQLITE_INTERNAL_LINKAGE int
oPutbUtf8(const char *cBuf, int nAccept){
FILE *pfOut;
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
# if CIO_WIN_WC_XLATE
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
| ︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 | #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ #undef SHELL_INVALID_FILE_PTR /************************* End ../ext/consio/console_io.c ********************/ #ifndef SQLITE_SHELL_FIDDLE /* From here onward, fgets() is redirected to the console_io library. */ # define fgets(b,n,f) fGetsUtf8(b,n,f) /* * Define macros for emitting output text in various ways: * sputz(s, z) => emit 0-terminated string z to given stream s * sputf(s, f, ...) => emit varargs per format f to given stream s * oputz(z) => emit 0-terminated string z to default stream | > | 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 | #endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ #undef SHELL_INVALID_FILE_PTR /************************* End ../ext/consio/console_io.c ********************/ #ifndef SQLITE_SHELL_FIDDLE /* From here onward, fgets() is redirected to the console_io library. */ # define fgets(b,n,f) fGetsUtf8(b,n,f) /* * Define macros for emitting output text in various ways: * sputz(s, z) => emit 0-terminated string z to given stream s * sputf(s, f, ...) => emit varargs per format f to given stream s * oputz(z) => emit 0-terminated string z to default stream |
| ︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 | # define sputz(s,z) fPutsUtf8(z,s) # define sputf fPrintfUtf8 # define oputz(z) oPutsUtf8(z) # define oputf oPrintfUtf8 # define eputz(z) ePutsUtf8(z) # define eputf ePrintfUtf8 # define oputb(buf,na) oPutbUtf8(buf,na) #else /* For Fiddle, all console handling and emit redirection is omitted. */ # define sputz(fp,z) fputs(z,fp) # define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__) # define oputz(z) fputs(z,stdout) # define oputf(fmt, ...) printf(fmt,__VA_ARGS__) # define eputz(z) fputs(z,stderr) | > | 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 | # define sputz(s,z) fPutsUtf8(z,s) # define sputf fPrintfUtf8 # define oputz(z) oPutsUtf8(z) # define oputf oPrintfUtf8 # define eputz(z) ePutsUtf8(z) # define eputf ePrintfUtf8 # define oputb(buf,na) oPutbUtf8(buf,na) #else /* For Fiddle, all console handling and emit redirection is omitted. */ # define sputz(fp,z) fputs(z,fp) # define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__) # define oputz(z) fputs(z,stdout) # define oputf(fmt, ...) printf(fmt,__VA_ARGS__) # define eputz(z) fputs(z,stderr) |
| ︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 |
** Print the timing results.
*/
static void endTimer(void){
if( enableTimer ){
sqlite3_int64 iEnd = timeOfDay();
struct rusage sEnd;
getrusage(RUSAGE_SELF, &sEnd);
| | | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 |
** Print the timing results.
*/
static void endTimer(void){
if( enableTimer ){
sqlite3_int64 iEnd = timeOfDay();
struct rusage sEnd;
getrusage(RUSAGE_SELF, &sEnd);
sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
(iEnd - iBegin)*0.001,
timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
}
}
#define BEGIN_TIMER beginTimer()
|
| ︙ | ︙ | |||
1414 1415 1416 1417 1418 1419 1420 |
** Print the timing results.
*/
static void endTimer(void){
if( enableTimer && getProcessTimesAddr){
FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
sqlite3_int64 ftWallEnd = timeOfDay();
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
| | | 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 |
** Print the timing results.
*/
static void endTimer(void){
if( enableTimer && getProcessTimesAddr){
FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
sqlite3_int64 ftWallEnd = timeOfDay();
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
sputf(stdout, "Run Time: real %.3f user %f sys %f\n",
(ftWallEnd - ftWallBegin)*0.001,
timeDiff(&ftUserBegin, &ftUserEnd),
timeDiff(&ftKernelBegin, &ftKernelEnd));
}
}
#define BEGIN_TIMER beginTimer()
|
| ︙ | ︙ | |||
1711 1712 1713 1714 1715 1716 1717 |
/*
** Return open FILE * if zFile exists, can be opened for read
** and is an ordinary file or a character stream source.
** Otherwise return 0.
*/
static FILE * openChrSource(const char *zFile){
#if defined(_WIN32) || defined(WIN32)
| | | | 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 |
/*
** Return open FILE * if zFile exists, can be opened for read
** and is an ordinary file or a character stream source.
** Otherwise return 0.
*/
static FILE * openChrSource(const char *zFile){
#if defined(_WIN32) || defined(WIN32)
struct __stat64 x = {0};
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
/* On Windows, open first, then check the stream nature. This order
** is necessary because _stat() and sibs, when checking a named pipe,
** effectively break the pipe as its supplier sees it. */
FILE *rv = fopen(zFile, "rb");
if( rv==0 ) return 0;
if( _fstat64(_fileno(rv), &x) != 0
|| !STAT_CHR_SRC(x.st_mode)){
fclose(rv);
rv = 0;
}
return rv;
#else
struct stat x = {0};
|
| ︙ | ︙ | |||
14823 14824 14825 14826 14827 14828 14829 14830 14831 14832 14833 14834 14835 14836 |
iOff += nPointer;
/* Load the "byte of payload including overflow" field */
if( bNextPage || iOff>pCsr->nPage ){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
}
/* If this is a leaf intkey cell, load the rowid */
if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
}
| > | 14824 14825 14826 14827 14828 14829 14830 14831 14832 14833 14834 14835 14836 14837 14838 |
iOff += nPointer;
/* Load the "byte of payload including overflow" field */
if( bNextPage || iOff>pCsr->nPage ){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
}
/* If this is a leaf intkey cell, load the rowid */
if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
}
|
| ︙ | ︙ | |||
27603 27604 27605 27606 27607 27608 27609 27610 27611 27612 27613 27614 27615 27616 |
/*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
/*{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
{"fk_no_action", SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN" },
{"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{"localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
#ifdef YYCOVERAGE
{"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
#endif
{"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
| > | 27605 27606 27607 27608 27609 27610 27611 27612 27613 27614 27615 27616 27617 27618 27619 |
/*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
/*{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
{"fk_no_action", SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN" },
{"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{"json_selfcheck", SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN" },
{"localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
#ifdef YYCOVERAGE
{"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
#endif
{"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
|
| ︙ | ︙ | |||
27821 27822 27823 27824 27825 27826 27827 27828 27829 27830 27831 27832 27833 27834 |
case SQLITE_TESTCTRL_SORTER_MMAP:
if( nArg==3 ){
int opt = (unsigned int)integerValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
isOk = 3;
}
break;
}
}
if( isOk==0 && iCtrl>=0 ){
oputf("Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
rc = 1;
}else if( isOk==1 ){
oputf("%d\n", rc2);
| > > > > > > > > > > | 27824 27825 27826 27827 27828 27829 27830 27831 27832 27833 27834 27835 27836 27837 27838 27839 27840 27841 27842 27843 27844 27845 27846 27847 |
case SQLITE_TESTCTRL_SORTER_MMAP:
if( nArg==3 ){
int opt = (unsigned int)integerValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
isOk = 3;
}
break;
case SQLITE_TESTCTRL_JSON_SELFCHECK:
if( nArg==2 ){
rc2 = -1;
isOk = 1;
}else{
rc2 = booleanValue(azArg[2]);
isOk = 3;
}
sqlite3_test_control(testctrl, &rc2);
break;
}
}
if( isOk==0 && iCtrl>=0 ){
oputf("Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
rc = 1;
}else if( isOk==1 ){
oputf("%d\n", rc2);
|
| ︙ | ︙ | |||
28707 28708 28709 28710 28711 28712 28713 |
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
SetConsoleTextAttribute(out,
FOREGROUND_RED|FOREGROUND_INTENSITY
);
#endif
| | | | 28720 28721 28722 28723 28724 28725 28726 28727 28728 28729 28730 28731 28732 28733 28734 28735 28736 28737 28738 28739 28740 28741 |
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
SetConsoleTextAttribute(out,
FOREGROUND_RED|FOREGROUND_INTENSITY
);
#endif
sputz(stdout, zText);
#if !SQLITE_OS_WINRT
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
#endif
}
#else
static void printBold(const char *zText){
sputf(stdout, "\033[1m%s\033[0m", zText);
}
#endif
/*
** Get the argument to an --option. Throw an error and die if no argument
** is available.
*/
|
| ︙ | ︙ | |||
28908 28909 28910 28911 28912 28913 28914 |
|| cli_strcmp(z,"-newline")==0
|| cli_strcmp(z,"-cmd")==0
){
(void)cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-interactive")==0 ){
| < < < < | 28921 28922 28923 28924 28925 28926 28927 28928 28929 28930 28931 28932 28933 28934 |
|| cli_strcmp(z,"-newline")==0
|| cli_strcmp(z,"-cmd")==0
){
(void)cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-interactive")==0 ){
}else if( cli_strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
** informational messages (like from process_sqliterc) before
** we do the actual processing of arguments later in a second pass.
*/
stdin_is_interactive = 0;
}else if( cli_strcmp(z,"-utf8")==0 ){
|
| ︙ | ︙ | |||
29181 29182 29183 29184 29185 29186 29187 |
** prior to sending the SQL into SQLite. Useful for injecting
** crazy bytes in the middle of SQL statements for testing and debugging.
*/
ShellSetFlag(&data, SHFLG_Backslash);
}else if( cli_strcmp(z,"-bail")==0 ){
/* No-op. The bail_on_error flag should already be set. */
}else if( cli_strcmp(z,"-version")==0 ){
| | | | > > > | 29190 29191 29192 29193 29194 29195 29196 29197 29198 29199 29200 29201 29202 29203 29204 29205 29206 29207 29208 29209 29210 29211 |
** prior to sending the SQL into SQLite. Useful for injecting
** crazy bytes in the middle of SQL statements for testing and debugging.
*/
ShellSetFlag(&data, SHFLG_Backslash);
}else if( cli_strcmp(z,"-bail")==0 ){
/* No-op. The bail_on_error flag should already be set. */
}else if( cli_strcmp(z,"-version")==0 ){
sputf(stdout, "%s %s (%d-bit)\n",
sqlite3_libversion(), sqlite3_sourceid(), 8*(int)sizeof(char*));
return 0;
}else if( cli_strcmp(z,"-interactive")==0 ){
/* Need to check for interactive override here to so that it can
** affect console setup (for Windows only) and testing thereof.
*/
stdin_is_interactive = 1;
}else if( cli_strcmp(z,"-batch")==0 ){
/* already handled */
}else if( cli_strcmp(z,"-utf8")==0 ){
/* already handled */
}else if( cli_strcmp(z,"-no-utf8")==0 ){
/* already handled */
}else if( cli_strcmp(z,"-heap")==0 ){
|
| ︙ | ︙ | |||
29314 29315 29316 29317 29318 29319 29320 |
char *zHistory;
int nHistory;
#if CIO_WIN_WC_XLATE
# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "")
#else
# define SHELL_CIO_CHAR_SET ""
#endif
| | | | | 29326 29327 29328 29329 29330 29331 29332 29333 29334 29335 29336 29337 29338 29339 29340 29341 29342 29343 29344 29345 29346 |
char *zHistory;
int nHistory;
#if CIO_WIN_WC_XLATE
# define SHELL_CIO_CHAR_SET (stdout_is_console? " (UTF-16 console I/O)" : "")
#else
# define SHELL_CIO_CHAR_SET ""
#endif
sputf(stdout, "SQLite version %s %.19s%s\n" /*extra-version-info*/
"Enter \".help\" for usage hints.\n",
sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);
if( warnInmemoryDb ){
sputz(stdout, "Connected to a ");
printBold("transient in-memory database");
sputz(stdout, ".\nUse \".open FILENAME\" to reopen on a"
" persistent database.\n");
}
zHistory = getenv("SQLITE_HISTORY");
if( zHistory ){
zHistory = strdup(zHistory);
}else if( (zHome = find_home_dir(0))!=0 ){
nHistory = strlen30(zHome) + 20;
|
| ︙ | ︙ |
Changes to extsrc/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | | 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 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.45.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other ** programs, you need this file and the "sqlite3.h" header file that defines ** the programming interface to the SQLite library. (If you do not have ** the "sqlite3.h" header file at hand, you will find a copy embedded within ** the text of this file. Search for "Begin file sqlite3.h" to find the start ** of the embedded sqlite3.h header file.) Additional code files may be needed ** if you want a wrapper to interface SQLite with your choice of programming ** language. The code for the "sqlite3" command-line shell is also in a ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in ** 27d4a89a5ff96b7b7fc5dc9650e1269f7c7e. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif /************** Begin file sqliteInt.h ***************************************/ |
| ︙ | ︙ | |||
455 456 457 458 459 460 461 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.45.0" #define SQLITE_VERSION_NUMBER 3045000 #define SQLITE_SOURCE_ID "2023-12-14 16:34:47 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
4263 4264 4265 4266 4267 4268 4269 | ** <li> sqlite3_extended_errcode() ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language | | > | | > | 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 | ** <li> sqlite3_extended_errcode() ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively, ** or NULL if no error message is available. ** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text ** that describes the [result code] E, as UTF-8, or NULL if E is not an ** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** ** ^If the most recent error references a specific token in the input ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by ** sqlite3_error_offset() assumes that the input SQL is UTF8. |
| ︙ | ︙ | |||
8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 | #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 | > | 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 | #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ #define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 |
| ︙ | ︙ | |||
13293 13294 13295 13296 13297 13298 13299 13300 13301 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
| > > > > > > > > > > > > > > > > > > > > > > > > > | | 13296 13297 13298 13299 13300 13301 13302 13303 13304 13305 13306 13307 13308 13309 13310 13311 13312 13313 13314 13315 13316 13317 13318 13319 13320 13321 13322 13323 13324 13325 13326 13327 13328 13329 13330 13331 13332 13333 13334 13335 13336 13337 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
**
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase iPhrase of the current
** query. Before returning, output parameter *ppToken is set to point
** to a buffer containing the requested token, and *pnToken to the
** size of this buffer in bytes.
**
** The output text is not a copy of the query text that specified the
** token. It is the output of the tokenizer module. For tokendata=1
** tables, this includes any embedded 0x00 and trailing data.
**
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase hit iIdx within the
** current row. Output variable (*ppToken) is set to point to a buffer
** containing the matching document token, and (*pnToken) to the size
** of that buffer in bytes. This API is not available if the specified
** token matches a prefix query term. In that case both output variables
** are always set to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 3 */
void *(*xUserData)(Fts5Context*);
int (*xColumnCount)(Fts5Context*);
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
| ︙ | ︙ | |||
13330 13331 13332 13333 13334 13335 13336 13337 13338 13339 13340 13341 13342 13343 | void *(*xGetAuxdata)(Fts5Context*, int bClear); int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); }; /* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* | > > > > > > > | 13358 13359 13360 13361 13362 13363 13364 13365 13366 13367 13368 13369 13370 13371 13372 13373 13374 13375 13376 13377 13378 |
void *(*xGetAuxdata)(Fts5Context*, int bClear);
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
/* Below this point are iVersion>=3 only */
int (*xQueryToken)(Fts5Context*,
int iPhrase, int iToken,
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
|
| ︙ | ︙ | |||
16424 16425 16426 16427 16428 16429 16430 16431 16432 16433 16434 16435 16436 16437 | #define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */ #define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */ #define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ #define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 #define P5_ConstraintUnique 2 #define P5_ConstraintCheck 3 #define P5_ConstraintFK 4 | > | 16459 16460 16461 16462 16463 16464 16465 16466 16467 16468 16469 16470 16471 16472 16473 | #define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */ #define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */ #define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ #define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ #define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 #define P5_ConstraintUnique 2 #define P5_ConstraintCheck 3 #define P5_ConstraintFK 4 |
| ︙ | ︙ | |||
16646 16647 16648 16649 16650 16651 16652 | #define OP_VCheck 174 #define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ #define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ #define OP_VRename 177 #define OP_Pagecount 178 #define OP_MaxPgcnt 179 #define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ | > > | | | | | | | | 16682 16683 16684 16685 16686 16687 16688 16689 16690 16691 16692 16693 16694 16695 16696 16697 16698 16699 16700 16701 16702 16703 16704 | #define OP_VCheck 174 #define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ #define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ #define OP_VRename 177 #define OP_Pagecount 178 #define OP_MaxPgcnt 179 #define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ #define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */ #define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */ #define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */ #define OP_Trace 184 #define OP_CursorHint 185 #define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */ #define OP_Noop 187 #define OP_Explain 188 #define OP_Abortable 189 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c ** are encoded into bitvectors as follows: */ #define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */ #define OPFLG_IN1 0x02 /* in1: P1 is an input */ |
| ︙ | ︙ | |||
16688 16689 16690 16691 16692 16693 16694 | /* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ /* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ | | | | 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 16737 16738 16739 16740 16741 | /* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ /* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ /* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ /* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\ /* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} /* The resolve3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum ** JUMP opcode the better, so the mkopcodeh.tcl script that ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ |
| ︙ | ︙ | |||
17950 17951 17952 17953 17954 17955 17956 |
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
| | | | 17988 17989 17990 17991 17992 17993 17994 17995 17996 17997 17998 17999 18000 18001 18002 18003 18004 18005 18006 |
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\
SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\
((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \
SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
|
| ︙ | ︙ | |||
18702 18703 18704 18705 18706 18707 18708 18709 18710 18711 18712 18713 18714 18715 |
Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
int iDistAddr; /* Address of OP_OpenEphemeral */
int iOBTab; /* Ephemeral table to implement ORDER BY */
u8 bOBPayload; /* iOBTab has payload columns separate from key */
u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
#ifdef SQLITE_DEBUG
Select *pSelect; /* SELECT statement that this AggInfo supports */
#endif
};
| > | 18740 18741 18742 18743 18744 18745 18746 18747 18748 18749 18750 18751 18752 18753 18754 |
Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
int iDistAddr; /* Address of OP_OpenEphemeral */
int iOBTab; /* Ephemeral table to implement ORDER BY */
u8 bOBPayload; /* iOBTab has payload columns separate from key */
u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */
u8 bUseSubtype; /* Transfer subtype info through sorter */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
#ifdef SQLITE_DEBUG
Select *pSelect; /* SELECT statement that this AggInfo supports */
#endif
};
|
| ︙ | ︙ | |||
19235 19236 19237 19238 19239 19240 19241 19242 19243 19244 19245 19246 19247 19248 |
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
/*
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
| > | 19274 19275 19276 19277 19278 19279 19280 19281 19282 19283 19284 19285 19286 19287 19288 |
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
u32 nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
/*
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
|
| ︙ | ︙ | |||
19951 19952 19953 19954 19955 19956 19957 19958 19959 19960 19961 19962 19963 19964 |
** when the reference count reaches zero.
**
** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
** sqlite3_free()
**
** 3. Make a (read-only) copy of a read-only RCStr string using
** sqlite3RCStrRef().
*/
struct RCStr {
u64 nRCRef; /* Number of references */
/* Total structure size should be a multiple of 8 bytes for alignment */
};
/*
| > > > | 19991 19992 19993 19994 19995 19996 19997 19998 19999 20000 20001 20002 20003 20004 20005 20006 20007 |
** when the reference count reaches zero.
**
** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
** sqlite3_free()
**
** 3. Make a (read-only) copy of a read-only RCStr string using
** sqlite3RCStrRef().
**
** "String" is in the name, but an RCStr object can also be used to hold
** binary data.
*/
struct RCStr {
u64 nRCRef; /* Number of references */
/* Total structure size should be a multiple of 8 bytes for alignment */
};
/*
|
| ︙ | ︙ | |||
20009 20010 20011 20012 20013 20014 20015 20016 20017 20018 20019 20020 20021 20022 | u8 bCoreMutex; /* True to enable core mutexing */ u8 bFullMutex; /* True to enable full mutexing */ u8 bOpenUri; /* True to interpret filenames as URIs */ u8 bUseCis; /* Use covering indices for full-scans */ u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ u8 bUseLongDouble; /* Make use of long double */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ int nStmtSpill; /* Stmt-journal spill-to-disk threshold */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ | > > > | 20052 20053 20054 20055 20056 20057 20058 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 | u8 bCoreMutex; /* True to enable core mutexing */ u8 bFullMutex; /* True to enable full mutexing */ u8 bOpenUri; /* True to interpret filenames as URIs */ u8 bUseCis; /* Use covering indices for full-scans */ u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ u8 bUseLongDouble; /* Make use of long double */ #ifdef SQLITE_DEBUG u8 bJsonSelfcheck; /* Double-check JSON parsing */ #endif int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ int nStmtSpill; /* Stmt-journal spill-to-disk threshold */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ |
| ︙ | ︙ | |||
20635 20636 20637 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 20656 20657 | SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*); SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); #ifndef SQLITE_OMIT_VIRTUALTABLE | > > | 20681 20682 20683 20684 20685 20686 20687 20688 20689 20690 20691 20692 20693 20694 20695 20696 20697 20698 20699 20700 20701 20702 20703 20704 20705 | SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*); SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); #ifndef SQLITE_OMIT_VIRTUALTABLE |
| ︙ | ︙ | |||
20734 20735 20736 20737 20738 20739 20740 20741 20742 20743 20744 20745 20746 20747 | #if SQLITE_MAX_ATTACHED>30 SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); #endif SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); #ifndef SQLITE_OMIT_AUTOINCREMENT SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) | > | 20782 20783 20784 20785 20786 20787 20788 20789 20790 20791 20792 20793 20794 20795 20796 | #if SQLITE_MAX_ATTACHED>30 SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); #endif SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*); SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); #ifndef SQLITE_OMIT_AUTOINCREMENT SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) |
| ︙ | ︙ | |||
20770 20771 20772 20773 20774 20775 20776 20777 20778 20779 20780 20781 20782 20783 |
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*);
| > | 20819 20820 20821 20822 20823 20824 20825 20826 20827 20828 20829 20830 20831 20832 20833 |
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*);
|
| ︙ | ︙ | |||
20996 20997 20998 20999 21000 21001 21002 21003 21004 21005 21006 21007 21008 21009 | SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); SQLITE_PRIVATE int sqlite3Atoi(const char*); #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); #endif SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); | > | 21046 21047 21048 21049 21050 21051 21052 21053 21054 21055 21056 21057 21058 21059 21060 | SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); SQLITE_PRIVATE int sqlite3Atoi(const char*); #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); #endif SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); |
| ︙ | ︙ | |||
21342 21343 21344 21345 21346 21347 21348 21349 21350 21351 21352 21353 21354 21355 | SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) # define sqlite3CteDelete(D,C) # define sqlite3CteWithAdd(P,W,C) ((void*)0) # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) ((void*)0) | > | 21393 21394 21395 21396 21397 21398 21399 21400 21401 21402 21403 21404 21405 21406 21407 | SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) # define sqlite3CteDelete(D,C) # define sqlite3CteWithAdd(P,W,C) ((void*)0) # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) ((void*)0) |
| ︙ | ︙ | |||
22719 22720 22721 22722 22723 22724 22725 22726 22727 22728 22729 22730 22731 22732 |
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
{0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
| > > > | 22771 22772 22773 22774 22775 22776 22777 22778 22779 22780 22781 22782 22783 22784 22785 22786 22787 |
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
0, /* bJsonSelfcheck */
#endif
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
{0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
|
| ︙ | ︙ | |||
25053 25054 25055 25056 25057 25058 25059 25060 25061 25062 25063 25064 25065 25066 |
for(i=1; i<argc; i++){
z = sqlite3_value_text(argv[i]);
n = sqlite3_value_bytes(argv[i]);
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
}
computeJD(p);
if( p->isError || !validJulianDay(p->iJD) ) return 1;
return 0;
}
/*
** The following routines implement the various date and time functions
** of SQLite.
| > > > > > > | 25108 25109 25110 25111 25112 25113 25114 25115 25116 25117 25118 25119 25120 25121 25122 25123 25124 25125 25126 25127 |
for(i=1; i<argc; i++){
z = sqlite3_value_text(argv[i]);
n = sqlite3_value_bytes(argv[i]);
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
}
computeJD(p);
if( p->isError || !validJulianDay(p->iJD) ) return 1;
if( argc==1 && p->validYMD && p->D>28 ){
/* Make sure a YYYY-MM-DD is normalized.
** Example: 2023-02-31 -> 2023-03-03 */
assert( p->validJD );
p->validYMD = 0;
}
return 0;
}
/*
** The following routines implement the various date and time functions
** of SQLite.
|
| ︙ | ︙ | |||
32081 32082 32083 32084 32085 32086 32087 | va_start(ap,zFormat); sqlite3_str_vappendf(p, zFormat, ap); va_end(ap); } /***************************************************************************** | | | 32142 32143 32144 32145 32146 32147 32148 32149 32150 32151 32152 32153 32154 32155 32156 | va_start(ap,zFormat); sqlite3_str_vappendf(p, zFormat, ap); va_end(ap); } /***************************************************************************** ** Reference counted string/blob storage *****************************************************************************/ /* ** Increase the reference count of the string by one. ** ** The input parameter is returned. */ |
| ︙ | ︙ | |||
32933 32934 32935 32936 32937 32938 32939 |
case TK_BETWEEN: {
const Expr *pX, *pY, *pZ;
pX = pExpr->pLeft;
assert( ExprUseXList(pExpr) );
assert( pExpr->x.pList->nExpr==2 );
pY = pExpr->x.pList->a[0].pExpr;
pZ = pExpr->x.pList->a[1].pExpr;
| | | 32994 32995 32996 32997 32998 32999 33000 33001 33002 33003 33004 33005 33006 33007 33008 |
case TK_BETWEEN: {
const Expr *pX, *pY, *pZ;
pX = pExpr->pLeft;
assert( ExprUseXList(pExpr) );
assert( pExpr->x.pList->nExpr==2 );
pY = pExpr->x.pList->a[0].pExpr;
pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
| ︙ | ︙ | |||
34068 34069 34070 34071 34072 34073 34074 |
if( c<0x80
|| (c&0xFFFFF800)==0xD800
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
}
return c;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | 34129 34130 34131 34132 34133 34134 34135 34136 34137 34138 34139 34140 34141 34142 34143 34144 34145 34146 34147 34148 34149 34150 34151 34152 34153 34154 34155 34156 34157 34158 34159 34160 34161 34162 34163 34164 34165 34166 34167 34168 34169 34170 34171 34172 34173 34174 |
if( c<0x80
|| (c&0xFFFFF800)==0xD800
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
}
return c;
}
/*
** Read a single UTF8 character out of buffer z[], but reading no
** more than n characters from the buffer. z[] is not zero-terminated.
**
** Return the number of bytes used to construct the character.
**
** Invalid UTF8 might generate a strange result. No effort is made
** to detect invalid UTF8.
**
** At most 4 bytes will be read out of z[]. The return value will always
** be between 1 and 4.
*/
SQLITE_PRIVATE int sqlite3Utf8ReadLimited(
const u8 *z,
int n,
u32 *piOut
){
u32 c;
int i = 1;
assert( n>0 );
c = z[0];
if( c>=0xc0 ){
c = sqlite3Utf8Trans1[c-0xc0];
if( n>4 ) n = 4;
while( i<n && (z[i] & 0xc0)==0x80 ){
c = (c<<6) + (0x3f & z[i]);
i++;
}
}
*piOut = c;
return i;
}
/*
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
*/
/* #define TRANSLATE_TRACE 1 */
|
| ︙ | ︙ | |||
36837 36838 36839 36840 36841 36842 36843 |
/* 174 */ "VCheck" OpHelp(""),
/* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
/* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 177 */ "VRename" OpHelp(""),
/* 178 */ "Pagecount" OpHelp(""),
/* 179 */ "MaxPgcnt" OpHelp(""),
/* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
| > > | | | | | | | | 36929 36930 36931 36932 36933 36934 36935 36936 36937 36938 36939 36940 36941 36942 36943 36944 36945 36946 36947 36948 36949 36950 36951 |
/* 174 */ "VCheck" OpHelp(""),
/* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
/* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 177 */ "VRename" OpHelp(""),
/* 178 */ "Pagecount" OpHelp(""),
/* 179 */ "MaxPgcnt" OpHelp(""),
/* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
/* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
/* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
/* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
/* 184 */ "Trace" OpHelp(""),
/* 185 */ "CursorHint" OpHelp(""),
/* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
/* 187 */ "Noop" OpHelp(""),
/* 188 */ "Explain" OpHelp(""),
/* 189 */ "Abortable" OpHelp(""),
};
return azName[i];
}
#endif
/************** End of opcodes.c *********************************************/
/************** Begin file os_kv.c *******************************************/
|
| ︙ | ︙ | |||
41889 41890 41891 41892 41893 41894 41895 41896 41897 41898 41899 41900 41901 41902 41903 |
case SQLITE_FCNTL_HAS_MOVED: {
*(int*)pArg = fileHasMoved(pFile);
return SQLITE_OK;
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
pFile->iBusyTimeout = *(int*)pArg;
*(int*)pArg = iOld;
return SQLITE_OK;
}
#endif
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
| > > > > > > | 41983 41984 41985 41986 41987 41988 41989 41990 41991 41992 41993 41994 41995 41996 41997 41998 41999 42000 42001 42002 42003 |
case SQLITE_FCNTL_HAS_MOVED: {
*(int*)pArg = fileHasMoved(pFile);
return SQLITE_OK;
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
pFile->iBusyTimeout = *(int*)pArg;
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
pFile->iBusyTimeout = !!(*(int*)pArg);
#else
# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
#endif
*(int*)pArg = iOld;
return SQLITE_OK;
}
#endif
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
|
| ︙ | ︙ | |||
42142 42143 42144 42145 42146 42147 42148 42149 42150 42151 42152 42153 42154 42155 42156 42157 42158 42159 42160 42161 42162 42163 |
**
** hShm
** zFilename
**
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
u8 isUnlocked; /* True if no DMS lock held */
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
| > > > > > > > > > > > > > > > > > > > > > > < < | 42242 42243 42244 42245 42246 42247 42248 42249 42250 42251 42252 42253 42254 42255 42256 42257 42258 42259 42260 42261 42262 42263 42264 42265 42266 42267 42268 42269 42270 42271 42272 42273 42274 42275 42276 42277 42278 42279 42280 42281 42282 42283 42284 42285 42286 42287 42288 42289 42290 42291 42292 |
**
** hShm
** zFilename
**
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
**
** aLock[SQLITE_SHM_NLOCK]:
** This array records the various locks held by clients on each of the
** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no
** locks are held by the process on this slot. If it is set to -1, then
** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[]
** value is set to a positive value, then it is the number of shared
** locks currently held on the slot.
**
** aMutex[SQLITE_SHM_NLOCK]:
** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex
** pShmMutex is used to protect the aLock[] array and the right to
** call fcntl() on unixShmNode.hShm to obtain or release locks.
**
** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array
** of mutexes - one for each locking slot. To read or write locking
** slot aLock[iSlot], the caller must hold the corresponding mutex
** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a
** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
u8 isUnlocked; /* True if no DMS lock held */
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK];
#endif
int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
u8 nextShmId; /* Next available unixShm.id value */
#endif
};
/*
** Structure used internally by this VFS to record the state of an
** open shared memory connection.
|
| ︙ | ︙ | |||
42241 42242 42243 42244 42245 42246 42247 |
int ofst, /* First byte of the locking range */
int n /* Number of bytes to lock */
){
unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
| < > > > > > > > > > > > | | > > > | | < < | < < | < < | < < | | | < < < | 42361 42362 42363 42364 42365 42366 42367 42368 42369 42370 42371 42372 42373 42374 42375 42376 42377 42378 42379 42380 42381 42382 42383 42384 42385 42386 42387 42388 42389 42390 42391 42392 42393 42394 42395 42396 42397 42398 42399 42400 42401 42402 42403 42404 42405 42406 42407 42408 42409 42410 42411 42412 42413 42414 42415 42416 42417 42418 42419 42420 42421 42422 42423 42424 42425 42426 42427 42428 42429 42430 42431 42432 42433 42434 42435 42436 |
int ofst, /* First byte of the locking range */
int n /* Number of bytes to lock */
){
unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
pShmNode = pFile->pInode->pShmNode;
/* Assert that the correct mutex or mutexes are held. */
if( pShmNode->nRef==0 ){
assert( ofst==UNIX_SHM_DMS && n==1 && unixMutexHeld() );
}else{
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int ii;
for(ii=ofst-UNIX_SHM_BASE; ii<ofst-UNIX_SHM_BASE+n; ii++){
assert( sqlite3_mutex_held(pShmNode->aMutex[ii]) );
}
#else
assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
assert( pShmNode->nRef>0 );
#endif
}
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
if( pShmNode->hShm>=0 ){
int res;
/* Initialize the locking parameters */
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
if( res==-1 ){
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1
rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
#else
rc = SQLITE_BUSY;
#endif
}
}
/* Do debug tracing */
#ifdef SQLITE_DEBUG
OSTRACE(("SHM-LOCK "));
if( rc==SQLITE_OK ){
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1));
}
}else{
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1));
}
}
#endif
return rc;
}
/*
|
| ︙ | ︙ | |||
42338 42339 42340 42341 42342 42343 42344 42345 42346 42347 42348 42349 42350 42351 |
unixShmNode *p = pFd->pInode->pShmNode;
assert( unixMutexHeld() );
if( p && ALWAYS(p->nRef==0) ){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->pShmMutex);
for(i=0; i<p->nRegion; i+=nShmPerMap){
if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
| > > > > > | 42460 42461 42462 42463 42464 42465 42466 42467 42468 42469 42470 42471 42472 42473 42474 42475 42476 42477 42478 |
unixShmNode *p = pFd->pInode->pShmNode;
assert( unixMutexHeld() );
if( p && ALWAYS(p->nRef==0) ){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->pShmMutex);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
for(i=0; i<SQLITE_SHM_NLOCK; i++){
sqlite3_mutex_free(p->aMutex[i]);
}
#endif
for(i=0; i<p->nRegion; i+=nShmPerMap){
if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
|
| ︙ | ︙ | |||
42397 42398 42399 42400 42401 42402 42403 42404 42405 42406 42407 42408 42409 42410 42411 |
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
/* The first connection to attach must truncate the -shm file. We
** truncate to 3 bytes (an arbitrary small number, less than the
** -shm header size) rather than 0 as a system debugging aid, to
** help detect if a -shm file truncation is legitimate or is the work
** or a rogue process. */
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
| > > > > > > > > > > > > > | 42524 42525 42526 42527 42528 42529 42530 42531 42532 42533 42534 42535 42536 42537 42538 42539 42540 42541 42542 42543 42544 42545 42546 42547 42548 42549 42550 42551 |
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/* Do not use a blocking lock here. If the lock cannot be obtained
** immediately, it means some other connection is truncating the
** *-shm file. And after it has done so, it will not release its
** lock, but only downgrade it to a shared lock. So no point in
** blocking here. The call below to obtain the shared DMS lock may
** use a blocking lock. */
int iSaveTimeout = pDbFd->iBusyTimeout;
pDbFd->iBusyTimeout = 0;
#endif
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
pDbFd->iBusyTimeout = iSaveTimeout;
#endif
/* The first connection to attach must truncate the -shm file. We
** truncate to 3 bytes (an arbitrary small number, less than the
** -shm header size) rather than 0 as a system debugging aid, to
** help detect if a -shm file truncation is legitimate or is the work
** or a rogue process. */
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
|
| ︙ | ︙ | |||
42518 42519 42520 42521 42522 42523 42524 42525 42526 42527 42528 42529 42530 42531 |
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
}
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
(sStat.st_mode&0777));
}
| > > > > > > > > > > > > | 42658 42659 42660 42661 42662 42663 42664 42665 42666 42667 42668 42669 42670 42671 42672 42673 42674 42675 42676 42677 42678 42679 42680 42681 42682 42683 |
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
{
int ii;
for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){
pShmNode->aMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->aMutex[ii]==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
}
}
#endif
}
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
(sStat.st_mode&0777));
}
|
| ︙ | ︙ | |||
42739 42740 42741 42742 42743 42744 42745 42746 42747 |
** held by each client. Return true if it does, or false otherwise. This
** is to be used in an assert(). e.g.
**
** assert( assertLockingArrayOk(pShmNode) );
*/
#ifdef SQLITE_DEBUG
static int assertLockingArrayOk(unixShmNode *pShmNode){
unixShm *pX;
int aLock[SQLITE_SHM_NLOCK];
| > > > < > | | | 42891 42892 42893 42894 42895 42896 42897 42898 42899 42900 42901 42902 42903 42904 42905 42906 42907 42908 42909 42910 42911 42912 42913 42914 42915 42916 42917 42918 42919 42920 42921 42922 42923 42924 42925 42926 42927 42928 42929 42930 42931 42932 42933 42934 42935 42936 42937 42938 42939 42940 42941 42942 42943 42944 42945 42946 42947 42948 42949 |
** held by each client. Return true if it does, or false otherwise. This
** is to be used in an assert(). e.g.
**
** assert( assertLockingArrayOk(pShmNode) );
*/
#ifdef SQLITE_DEBUG
static int assertLockingArrayOk(unixShmNode *pShmNode){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
return 1;
#else
unixShm *pX;
int aLock[SQLITE_SHM_NLOCK];
memset(aLock, 0, sizeof(aLock));
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
int i;
for(i=0; i<SQLITE_SHM_NLOCK; i++){
if( pX->exclMask & (1<<i) ){
assert( aLock[i]==0 );
aLock[i] = -1;
}else if( pX->sharedMask & (1<<i) ){
assert( aLock[i]>=0 );
aLock[i]++;
}
}
}
assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
#endif
}
#endif
/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHARED and EXCLUSIVE locks is a little
** different here than in posix. In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back. But one may
** not go from shared to exclusive or from exclusive to shared.
*/
static int unixShmLock(
sqlite3_file *fd, /* Database file holding the shared memory */
int ofst, /* First lock to acquire or release */
int n, /* Number of locks to acquire or release */
int flags /* What to do with the lock */
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p; /* The shared memory being locked */
unixShmNode *pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask = (1<<(ofst+n)) - (1<<ofst); /* Mask of locks to take or release */
int *aLock;
p = pDbFd->pShm;
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
pShmNode = p->pShmNode;
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
aLock = pShmNode->aLock;
|
| ︙ | ︙ | |||
42815 42816 42817 42818 42819 42820 42821 | ** In other words, if this is a blocking lock, none of the locks that ** occur later in the above list than the lock being obtained may be ** held. ** ** It is not permitted to block on the RECOVER lock. */ #ifdef SQLITE_ENABLE_SETLK_TIMEOUT | > > | | | | | | > > > > > > > > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > | < < > | > > > > > > > > > | | | > > | | | | | | < | < < < < < < | < | | | > | < < | > | | | | | | | | | > > > | > > > | | | < | < | | | | | | | | | | < | | | | | | | | > > > > > > > > | > > > | 42970 42971 42972 42973 42974 42975 42976 42977 42978 42979 42980 42981 42982 42983 42984 42985 42986 42987 42988 42989 42990 42991 42992 42993 42994 42995 42996 42997 42998 42999 43000 43001 43002 43003 43004 43005 43006 43007 43008 43009 43010 43011 43012 43013 43014 43015 43016 43017 43018 43019 43020 43021 43022 43023 43024 43025 43026 43027 43028 43029 43030 43031 43032 43033 43034 43035 43036 43037 43038 43039 43040 43041 43042 43043 43044 43045 43046 43047 43048 43049 43050 43051 43052 43053 43054 43055 43056 43057 43058 43059 43060 43061 43062 43063 43064 43065 43066 43067 43068 43069 43070 43071 43072 43073 43074 43075 43076 43077 43078 43079 43080 43081 43082 43083 43084 43085 43086 43087 43088 43089 43090 43091 43092 43093 43094 43095 43096 43097 43098 43099 43100 43101 43102 43103 43104 43105 43106 43107 43108 43109 43110 43111 43112 43113 43114 43115 43116 43117 43118 43119 43120 43121 43122 43123 43124 43125 43126 43127 |
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
**
** It is not permitted to block on the RECOVER lock.
*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
));
}
#endif
/* Check if there is any work to do. There are three cases:
**
** a) An unlock operation where there are locks to unlock,
** b) An shared lock where the requested lock is not already held
** c) An exclusive lock where the requested lock is not already held
**
** The SQLite core never requests an exclusive lock that it already holds.
** This is assert()ed below.
*/
assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
|| 0==(p->exclMask & mask)
);
if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
|| (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
|| (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
){
/* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if
** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any
** other thread is holding this mutex, then it is either holding or about
** to hold a lock exclusive to the one being requested, and we may
** therefore return SQLITE_BUSY to the caller.
**
** Doing this prevents some deadlock scenarios. For example, thread 1 may
** be a checkpointer blocked waiting on the WRITER lock. And thread 2
** may be a normal SQL client upgrading to a write transaction. In this
** case thread 2 does a non-blocking request for the WRITER lock. But -
** if it were to use sqlite3_mutex_enter() then it would effectively
** become a (doomed) blocking request, as thread 2 would block until thread
** 1 obtained WRITER and released the mutex. Since thread 2 already holds
** a lock on a read-locking slot at this point, this breaks the
** anti-deadlock rules (see above). */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int iMutex;
for(iMutex=ofst; iMutex<ofst+n; iMutex++){
if( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ){
rc = sqlite3_mutex_try(pShmNode->aMutex[iMutex]);
if( rc!=SQLITE_OK ) break;
}else{
sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
}
}
#else
sqlite3_mutex_enter(pShmNode->pShmMutex);
#endif
if( rc==SQLITE_OK ){
if( flags & SQLITE_SHM_UNLOCK ){
/* Case (a) - unlock. */
int bUnlock = 1;
assert( (p->exclMask & p->sharedMask)==0 );
assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
/* If this is a SHARED lock being unlocked, it is possible that other
** clients within this process are holding the same SHARED lock. In
** this case, set bUnlock to 0 so that the posix lock is not removed
** from the file-descriptor below. */
if( flags & SQLITE_SHM_SHARED ){
assert( n==1 );
assert( aLock[ofst]>=1 );
if( aLock[ofst]>1 ){
bUnlock = 0;
aLock[ofst]--;
p->sharedMask &= ~mask;
}
}
if( bUnlock ){
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
memset(&aLock[ofst], 0, sizeof(int)*n);
p->sharedMask &= ~mask;
p->exclMask &= ~mask;
}
}
}else if( flags & SQLITE_SHM_SHARED ){
/* Case (b) - a shared lock. */
if( aLock[ofst]<0 ){
/* An exclusive lock is held by some other connection. BUSY. */
rc = SQLITE_BUSY;
}else if( aLock[ofst]==0 ){
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
}
/* Get the local shared locks */
if( rc==SQLITE_OK ){
p->sharedMask |= mask;
aLock[ofst]++;
}
}else{
/* Case (c) - an exclusive lock. */
int ii;
assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) );
assert( (p->sharedMask & mask)==0 );
assert( (p->exclMask & mask)==0 );
/* Make sure no sibling connections hold locks that will block this
** lock. If any do, return SQLITE_BUSY right away. */
for(ii=ofst; ii<ofst+n; ii++){
if( aLock[ii] ){
rc = SQLITE_BUSY;
break;
}
}
/* Get the exclusive locks at the system level. Then if successful
** also update the in-memory values. */
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
p->exclMask |= mask;
for(ii=ofst; ii<ofst+n; ii++){
aLock[ii] = -1;
}
}
}
}
assert( assertLockingArrayOk(pShmNode) );
}
/* Drop the mutexes acquired above. */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
for(iMutex--; iMutex>=ofst; iMutex--){
sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
}
#else
sqlite3_mutex_leave(pShmNode->pShmMutex);
#endif
}
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
}
/*
** Implement a memory barrier or memory fence on shared memory.
|
| ︙ | ︙ | |||
66234 66235 66236 66237 66238 66239 66240 66241 66242 66243 66244 66245 66246 66247 66248 66249 66250 66251 |
p = 0;
}
*pp = p;
return rc;
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/*
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
** they are supported by the VFS, and (b) the database handle is configured
** with a busy-timeout. Return 1 if blocking locks are successfully enabled,
** or 0 otherwise.
*/
static int walEnableBlocking(Wal *pWal){
int res = 0;
if( pWal->db ){
int tmout = pWal->db->busyTimeout;
if( tmout ){
| > > > > > > > > > > > > > < < < < | | 66451 66452 66453 66454 66455 66456 66457 66458 66459 66460 66461 66462 66463 66464 66465 66466 66467 66468 66469 66470 66471 66472 66473 66474 66475 66476 66477 66478 66479 66480 66481 66482 66483 66484 66485 66486 66487 66488 66489 |
p = 0;
}
*pp = p;
return rc;
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/*
** Attempt to enable blocking locks that block for nMs ms. Return 1 if
** blocking locks are successfully enabled, or 0 otherwise.
*/
static int walEnableBlockingMs(Wal *pWal, int nMs){
int rc = sqlite3OsFileControl(
pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&nMs
);
return (rc==SQLITE_OK);
}
/*
** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
** they are supported by the VFS, and (b) the database handle is configured
** with a busy-timeout. Return 1 if blocking locks are successfully enabled,
** or 0 otherwise.
*/
static int walEnableBlocking(Wal *pWal){
int res = 0;
if( pWal->db ){
int tmout = pWal->db->busyTimeout;
if( tmout ){
res = walEnableBlockingMs(pWal, tmout);
}
}
return res;
}
/*
** Disable blocking locks.
|
| ︙ | ︙ | |||
66298 66299 66300 66301 66302 66303 66304 |
/*
** Set the database handle used to determine if blocking locks are required.
*/
SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
pWal->db = db;
}
| < < < < < < < < < < | | 66524 66525 66526 66527 66528 66529 66530 66531 66532 66533 66534 66535 66536 66537 66538 66539 66540 66541 |
/*
** Set the database handle used to determine if blocking locks are required.
*/
SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
pWal->db = db;
}
#else
# define walEnableBlocking(x) 0
# define walDisableBlocking(x)
# define walEnableBlockingMs(pWal, ms) 0
# define sqlite3WalDb(pWal, db)
#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
/*
** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
** n. If the attempt fails and parameter xBusy is not NULL, then it is a
|
| ︙ | ︙ | |||
66912 66913 66914 66915 66916 66917 66918 |
if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
}else{
int bWriteLock = pWal->writeLock;
| | > > | > | 67128 67129 67130 67131 67132 67133 67134 67135 67136 67137 67138 67139 67140 67141 67142 67143 67144 67145 67146 67147 67148 67149 67150 67151 67152 67153 |
if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
}else{
int bWriteLock = pWal->writeLock;
if( bWriteLock
|| SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
** needs to be reconstructed. So run recovery to do exactly that.
** Disable blocking locks first. */
walDisableBlocking(pWal);
rc = walIndexRecover(pWal);
*pChanged = 1;
}
}
if( bWriteLock==0 ){
pWal->writeLock = 0;
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
| ︙ | ︙ | |||
67187 67188 67189 67190 67191 67192 67193 67194 67195 67196 67197 67198 67199 67200 |
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
u32 mxReadMark; /* Largest aReadMark[] value */
int mxI; /* Index of largest aReadMark[] value */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
u32 mxFrame; /* Wal frame to lock to */
assert( pWal->readLock<0 ); /* Not currently locked */
/* useWal may only be set for read/write connections */
assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );
/* Take steps to avoid spinning forever if there is a protocol error.
| > > > | 67406 67407 67408 67409 67410 67411 67412 67413 67414 67415 67416 67417 67418 67419 67420 67421 67422 |
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
u32 mxReadMark; /* Largest aReadMark[] value */
int mxI; /* Index of largest aReadMark[] value */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
u32 mxFrame; /* Wal frame to lock to */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int nBlockTmout = 0;
#endif
assert( pWal->readLock<0 ); /* Not currently locked */
/* useWal may only be set for read/write connections */
assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );
/* Take steps to avoid spinning forever if there is a protocol error.
|
| ︙ | ︙ | |||
67217 67218 67219 67220 67221 67222 67223 67224 67225 67226 67227 67228 67229 67230 67231 67232 67233 67234 67235 67236 67237 67238 |
if( cnt>5 ){
int nDelay = 1; /* Pause time in microseconds */
if( cnt>100 ){
VVA_ONLY( pWal->lockError = 1; )
return SQLITE_PROTOCOL;
}
if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
sqlite3OsSleep(pWal->pVfs, nDelay);
}
if( !useWal ){
assert( rc==SQLITE_OK );
if( pWal->bShmUnreliable==0 ){
rc = walIndexReadHdr(pWal, pChanged);
}
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
** then convert BUSY errors to WAL_RETRY. If recovery is known to
** be running, convert BUSY to BUSY_RECOVERY. There is a race here
** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY
** would be technically correct. But the race is benign since with
** WAL_RETRY this routine will be called again and will probably be
| > > > > > > > > > > > > > > > > > | 67439 67440 67441 67442 67443 67444 67445 67446 67447 67448 67449 67450 67451 67452 67453 67454 67455 67456 67457 67458 67459 67460 67461 67462 67463 67464 67465 67466 67467 67468 67469 67470 67471 67472 67473 67474 67475 67476 67477 |
if( cnt>5 ){
int nDelay = 1; /* Pause time in microseconds */
if( cnt>100 ){
VVA_ONLY( pWal->lockError = 1; )
return SQLITE_PROTOCOL;
}
if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39;
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
/* In SQLITE_ENABLE_SETLK_TIMEOUT builds, configure the file-descriptor
** to block for locks for approximately nDelay us. This affects three
** locks: (a) the shared lock taken on the DMS slot in os_unix.c (if
** using os_unix.c), (b) the WRITER lock taken in walIndexReadHdr() if the
** first attempted read fails, and (c) the shared lock taken on the DMS
** slot in os_unix.c. All three of these locks are attempted from within
** the call to walIndexReadHdr() below. */
nBlockTmout = (nDelay+998) / 1000;
if( !useWal && walEnableBlockingMs(pWal, nBlockTmout) ){
nDelay = 1;
}
#endif
sqlite3OsSleep(pWal->pVfs, nDelay);
}
if( !useWal ){
assert( rc==SQLITE_OK );
if( pWal->bShmUnreliable==0 ){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
#endif
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
** then convert BUSY errors to WAL_RETRY. If recovery is known to
** be running, convert BUSY to BUSY_RECOVERY. There is a race here
** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY
** would be technically correct. But the race is benign since with
** WAL_RETRY this routine will be called again and will probably be
|
| ︙ | ︙ | |||
67339 67340 67341 67342 67343 67344 67345 67346 67347 |
}
}
if( mxI==0 ){
assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
}
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
if( rc ){
| > > > | | 67578 67579 67580 67581 67582 67583 67584 67585 67586 67587 67588 67589 67590 67591 67592 67593 67594 67595 67596 67597 |
}
}
if( mxI==0 ){
assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
}
(void)walEnableBlockingMs(pWal, nBlockTmout);
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
walDisableBlocking(pWal);
if( rc ){
assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
}
/* Now that the read-lock has been obtained, check that neither the
** value in the aReadMark[] array or the contents of the wal-index
** header have changed.
**
** It is necessary to check that the wal-index header did not change
** between the time it was read and when the shared-lock was obtained
|
| ︙ | ︙ | |||
68434 68435 68436 68437 68438 68439 68440 |
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
| | < | | 68676 68677 68678 68679 68680 68681 68682 68683 68684 68685 68686 68687 68688 68689 68690 68691 68692 |
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
/* Enable blocking locks, if possible. */
sqlite3WalDb(pWal, db);
if( xBusy2 ) (void)walEnableBlocking(pWal);
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
** "checkpoint" lock on the database file.
** EVIDENCE-OF: R-10421-19736 If any other process is running a
** checkpoint operation at the same time, the lock cannot be obtained and
** SQLITE_BUSY is returned.
** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
|
| ︙ | ︙ | |||
68478 68479 68480 68481 68482 68483 68484 68485 68486 |
}
}
/* Read the wal-index header. */
SEH_TRY {
if( rc==SQLITE_OK ){
walDisableBlocking(pWal);
rc = walIndexReadHdr(pWal, &isChanged);
| > > > > > | | 68719 68720 68721 68722 68723 68724 68725 68726 68727 68728 68729 68730 68731 68732 68733 68734 68735 68736 68737 68738 68739 68740 |
}
}
/* Read the wal-index header. */
SEH_TRY {
if( rc==SQLITE_OK ){
/* For a passive checkpoint, do not re-enable blocking locks after
** reading the wal-index header. A passive checkpoint should not block
** or invoke the busy handler. The only lock such a checkpoint may
** attempt to obtain is a lock on a read-slot, and it should give up
** immediately and do a partial checkpoint if it cannot obtain it. */
walDisableBlocking(pWal);
rc = walIndexReadHdr(pWal, &isChanged);
if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
}
}
/* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){
|
| ︙ | ︙ | |||
68817 68818 68819 68820 68821 68822 68823 | ** 18 1 File format write version ** 19 1 File format read version ** 20 1 Bytes of unused space at the end of each page ** 21 1 Max embedded payload fraction (must be 64) ** 22 1 Min embedded payload fraction (must be 32) ** 23 1 Min leaf payload fraction (must be 32) ** 24 4 File change counter | | | 69063 69064 69065 69066 69067 69068 69069 69070 69071 69072 69073 69074 69075 69076 69077 | ** 18 1 File format write version ** 19 1 File format read version ** 20 1 Bytes of unused space at the end of each page ** 21 1 Max embedded payload fraction (must be 64) ** 22 1 Min embedded payload fraction (must be 32) ** 23 1 Min leaf payload fraction (must be 32) ** 24 4 File change counter ** 28 4 The size of the database in pages ** 32 4 First freelist page ** 36 4 Number of freelist pages in the file ** 40 60 15 4-byte meta values passed to higher layers ** ** 40 4 Schema cookie ** 44 4 File format of schema layer ** 48 4 Size of page cache |
| ︙ | ︙ | |||
85368 85369 85370 85371 85372 85373 85374 85375 85376 85377 85378 85379 85380 85381 |
}
break;
}
case P4_VTAB : {
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
}
}
/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain
** nOp entries.
| > > > > | 85614 85615 85616 85617 85618 85619 85620 85621 85622 85623 85624 85625 85626 85627 85628 85629 85630 85631 |
}
break;
}
case P4_VTAB : {
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
case P4_TABLEREF: {
if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
break;
}
}
}
/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain
** nOp entries.
|
| ︙ | ︙ | |||
85495 85496 85497 85498 85499 85500 85501 |
static void SQLITE_NOINLINE vdbeChangeP4Full(
Vdbe *p,
Op *pOp,
const char *zP4,
int n
){
if( pOp->p4type ){
| | | 85745 85746 85747 85748 85749 85750 85751 85752 85753 85754 85755 85756 85757 85758 85759 |
static void SQLITE_NOINLINE vdbeChangeP4Full(
Vdbe *p,
Op *pOp,
const char *zP4,
int n
){
if( pOp->p4type ){
assert( pOp->p4type > P4_FREE_IF_LE );
pOp->p4type = 0;
pOp->p4.p = 0;
}
if( n<0 ){
sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n);
}else{
if( n==0 ) n = sqlite3Strlen30(zP4);
|
| ︙ | ︙ | |||
89618 89619 89620 89621 89622 89623 89624 |
** Set all the parameters in the compiled SQL statement to NULL.
*/
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
#if SQLITE_THREADSAFE
| | > > > > > > > > | 89868 89869 89870 89871 89872 89873 89874 89875 89876 89877 89878 89879 89880 89881 89882 89883 89884 89885 89886 89887 89888 89889 89890 |
** Set all the parameters in the compiled SQL statement to NULL.
*/
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex;
#endif
#ifdef SQLITE_ENABLE_API_ARMOR
if( pStmt==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
#if SQLITE_THREADSAFE
mutex = p->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
for(i=0; i<p->nVar; i++){
sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null;
}
assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
|
| ︙ | ︙ | |||
90408 90409 90410 90411 90412 90413 90414 |
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
SQLITE_API void *sqlite3_user_data(sqlite3_context *p){
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ) return 0;
| | < | 90666 90667 90668 90669 90670 90671 90672 90673 90674 90675 90676 90677 90678 90679 90680 90681 |
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
SQLITE_API void *sqlite3_user_data(sqlite3_context *p){
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ) return 0;
#endif
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
**
|
| ︙ | ︙ | |||
94229 94230 94231 94232 94233 94234 94235 |
**
** To force any register to be an integer, just add 0.
*/
case OP_AddImm: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
sqlite3VdbeMemIntegerify(pIn1);
| | | 94486 94487 94488 94489 94490 94491 94492 94493 94494 94495 94496 94497 94498 94499 94500 |
**
** To force any register to be an integer, just add 0.
*/
case OP_AddImm: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
sqlite3VdbeMemIntegerify(pIn1);
*(u64*)&pIn1->u.i += (u64)pOp->p2;
break;
}
/* Opcode: MustBeInt P1 P2 * * *
**
** Force the value in register P1 to be an integer. If the value
** in P1 is not an integer and cannot be converted into an integer
|
| ︙ | ︙ | |||
100375 100376 100377 100378 100379 100380 100381 | Table *pTab; sqlite3_vtab *pVtab; const sqlite3_module *pModule; char *zErr = 0; pOut = &aMem[pOp->p2]; sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */ | | > < < | 100632 100633 100634 100635 100636 100637 100638 100639 100640 100641 100642 100643 100644 100645 100646 100647 100648 100649 100650 100651 100652 100653 100654 100655 100656 100657 100658 100659 100660 100661 100662 |
Table *pTab;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
char *zErr = 0;
pOut = &aMem[pOp->p2];
sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */
assert( pOp->p4type==P4_TABLEREF );
pTab = pOp->p4.pTab;
assert( pTab!=0 );
assert( pTab->nTabRef>0 );
assert( IsVirtual(pTab) );
if( pTab->u.vtab.p==0 ) break;
pVtab = pTab->u.vtab.p->pVtab;
assert( pVtab!=0 );
pModule = pVtab->pModule;
assert( pModule!=0 );
assert( pModule->iVersion>=4 );
assert( pModule->xIntegrity!=0 );
sqlite3VtabLock(pTab->u.vtab.p);
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName,
pOp->p3, &zErr);
sqlite3VtabUnlock(pTab->u.vtab.p);
if( rc ){
sqlite3_free(zErr);
goto abort_due_to_error;
}
if( zErr ){
sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free);
}
|
| ︙ | ︙ | |||
100517 100518 100519 100520 100521 100522 100523 100524 100525 100526 100527 100528 100529 100530 100531 100532 100533 100534 100535 100536 100537 100538 100539 100540 100541 100542 100543 100544 100545 100546 100547 |
** unused by OP_VColumn.
*/
case OP_VColumn: { /* ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
}
assert( pCur->eCurType==CURTYPE_VTAB );
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
sContext.enc = encoding;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
}else{
MemSetTypeFlag(pDest, MEM_Null);
| > > > > | 100773 100774 100775 100776 100777 100778 100779 100780 100781 100782 100783 100784 100785 100786 100787 100788 100789 100790 100791 100792 100793 100794 100795 100796 100797 100798 100799 100800 100801 100802 100803 100804 100805 100806 100807 |
** unused by OP_VColumn.
*/
case OP_VColumn: { /* ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
FuncDef nullFunc;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
}
assert( pCur->eCurType==CURTYPE_VTAB );
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
sContext.enc = encoding;
nullFunc.pUserData = 0;
nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE;
sContext.pFunc = &nullFunc;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
}else{
MemSetTypeFlag(pDest, MEM_Null);
|
| ︙ | ︙ | |||
100865 100866 100867 100868 100869 100870 100871 100872 100873 100874 100875 100876 100877 100878 |
** Clear the subtype from register P1.
*/
case OP_ClrSubtype: { /* in1 */
pIn1 = &aMem[pOp->p1];
pIn1->flags &= ~MEM_Subtype;
break;
}
/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
** Compute a hash on the P4 registers starting with r[P3] and
** add that hash to the bloom filter contained in r[P1].
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 101125 101126 101127 101128 101129 101130 101131 101132 101133 101134 101135 101136 101137 101138 101139 101140 101141 101142 101143 101144 101145 101146 101147 101148 101149 101150 101151 101152 101153 101154 101155 101156 101157 101158 101159 101160 101161 101162 101163 101164 101165 101166 101167 101168 101169 101170 101171 101172 101173 101174 |
** Clear the subtype from register P1.
*/
case OP_ClrSubtype: { /* in1 */
pIn1 = &aMem[pOp->p1];
pIn1->flags &= ~MEM_Subtype;
break;
}
/* Opcode: GetSubtype P1 P2 * * *
** Synopsis: r[P2] = r[P1].subtype
**
** Extract the subtype value from register P1 and write that subtype
** into register P2. If P1 has no subtype, then P1 gets a NULL.
*/
case OP_GetSubtype: { /* in1 out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Subtype ){
sqlite3VdbeMemSetInt64(pOut, pIn1->eSubtype);
}else{
sqlite3VdbeMemSetNull(pOut);
}
break;
}
/* Opcode: SetSubtype P1 P2 * * *
** Synopsis: r[P2].subtype = r[P1]
**
** Set the subtype value of register P2 to the integer from register P1.
** If P1 is NULL, clear the subtype from p2.
*/
case OP_SetSubtype: { /* in1 out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){
pOut->flags &= ~MEM_Subtype;
}else{
assert( pIn1->flags & MEM_Int );
pOut->flags |= MEM_Subtype;
pOut->eSubtype = (u8)(pIn1->u.i & 0xff);
}
break;
}
/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
** Compute a hash on the P4 registers starting with r[P3] and
** add that hash to the bloom filter contained in r[P1].
*/
|
| ︙ | ︙ | |||
105914 105915 105916 105917 105918 105919 105920 105921 105922 105923 105924 105925 105926 105927 |
int n;
Table *pExTab;
n = pExpr->iColumn;
assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
testcase( pExTab->nCol==BMS-1 );
testcase( pExTab->nCol==BMS );
return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
}else{
| > | 106210 106211 106212 106213 106214 106215 106216 106217 106218 106219 106220 106221 106222 106223 106224 |
int n;
Table *pExTab;
n = pExpr->iColumn;
assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
assert( n < pExTab->nCol );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
testcase( pExTab->nCol==BMS-1 );
testcase( pExTab->nCol==BMS );
return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
}else{
|
| ︙ | ︙ | |||
106516 106517 106518 106519 106520 106521 106522 | ** if the mask contains extra set bits. However, it is important to ** avoid setting bits beyond the maximum column number of the table. ** (See ticket [b92e5e8ec2cdbaa1]). ** ** If a generated column is referenced, set bits for every column ** of the table. */ | | | 106813 106814 106815 106816 106817 106818 106819 106820 106821 106822 106823 106824 106825 106826 106827 |
** if the mask contains extra set bits. However, it is important to
** avoid setting bits beyond the maximum column number of the table.
** (See ticket [b92e5e8ec2cdbaa1]).
**
** If a generated column is referenced, set bits for every column
** of the table.
*/
if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){
pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
}
pExpr->op = eNewExprOp;
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
|
| ︙ | ︙ | |||
106981 106982 106983 106984 106985 106986 106987 |
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
}
#endif
pNC2 = pNC;
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
| | > | 107278 107279 107280 107281 107282 107283 107284 107285 107286 107287 107288 107289 107290 107291 107292 107293 107294 107295 107296 107297 |
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
}
#endif
pNC2 = pNC;
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
pExpr->op2 += (1 + pNC2->nNestedSelect);
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
pExpr->op2 += pNC2->nNestedSelect;
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
pNC2->ncFlags |= NC_HasAgg
| ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
& (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
|
| ︙ | ︙ | |||
107544 107545 107546 107547 107548 107549 107550 107551 107552 107553 107554 107555 107556 107557 |
assert( pSub->pPrior && pSub->pOrderBy==0 );
pSub->pOrderBy = p->pOrderBy;
p->pOrderBy = 0;
}
/* Recursively resolve names in all subqueries in the FROM clause
*/
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
| > | 107842 107843 107844 107845 107846 107847 107848 107849 107850 107851 107852 107853 107854 107855 107856 |
assert( pSub->pPrior && pSub->pOrderBy==0 );
pSub->pOrderBy = p->pOrderBy;
p->pOrderBy = 0;
}
/* Recursively resolve names in all subqueries in the FROM clause
*/
if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
|
| ︙ | ︙ | |||
107567 107568 107569 107570 107571 107572 107573 107574 107575 107576 107577 107578 107579 107580 |
** the refcount on all contexts between the current one and the
** context containing the column when it resolves a name. */
if( pOuterNC ){
assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
}
}
}
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
sNC.ncFlags = NC_AllowAgg|NC_AllowWin;
sNC.pSrcList = p->pSrc;
| > > > | 107866 107867 107868 107869 107870 107871 107872 107873 107874 107875 107876 107877 107878 107879 107880 107881 107882 |
** the refcount on all contexts between the current one and the
** context containing the column when it resolves a name. */
if( pOuterNC ){
assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
}
}
}
if( pOuterNC && ALWAYS(pOuterNC->nNestedSelect>0) ){
pOuterNC->nNestedSelect--;
}
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
sNC.ncFlags = NC_AllowAgg|NC_AllowWin;
sNC.pSrcList = p->pSrc;
|
| ︙ | ︙ | |||
109155 109156 109157 109158 109159 109160 109161 |
return;
}
assert( pExpr->op==TK_FUNCTION );
assert( pExpr->pLeft==0 );
assert( ExprUseXList(pExpr) );
if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){
/* Ignore ORDER BY on zero-argument aggregates */
| | < < | 109457 109458 109459 109460 109461 109462 109463 109464 109465 109466 109467 109468 109469 109470 109471 |
return;
}
assert( pExpr->op==TK_FUNCTION );
assert( pExpr->pLeft==0 );
assert( ExprUseXList(pExpr) );
if( pExpr->x.pList==0 || NEVER(pExpr->x.pList->nExpr==0) ){
/* Ignore ORDER BY on zero-argument aggregates */
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pOrderBy);
return;
}
if( IsWindowFunc(pExpr) ){
sqlite3ExprOrderByAggregateError(pParse, pExpr);
sqlite3ExprListDelete(db, pOrderBy);
return;
}
|
| ︙ | ︙ | |||
109338 109339 109340 109341 109342 109343 109344 109345 109346 109347 109348 109349 109350 109351 |
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbNNFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Clear both elements of an OnOrUsing object
*/
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
if( p==0 ){
/* Nothing to clear */
| > > > | 109638 109639 109640 109641 109642 109643 109644 109645 109646 109647 109648 109649 109650 109651 109652 109653 109654 |
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbNNFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3 *db, void *p){
if( ALWAYS(p) ) sqlite3ExprDeleteNN(db, (Expr*)p);
}
/*
** Clear both elements of an OnOrUsing object
*/
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
if( p==0 ){
/* Nothing to clear */
|
| ︙ | ︙ | |||
109363 109364 109365 109366 109367 109368 109369 |
**
** The pExpr might be deleted immediately on an OOM error.
**
** The deferred delete is (currently) implemented by adding the
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
| | < < | 109666 109667 109668 109669 109670 109671 109672 109673 109674 109675 109676 109677 109678 109679 109680 |
**
** The pExpr might be deleted immediately on an OOM error.
**
** The deferred delete is (currently) implemented by adding the
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
if( p ){
|
| ︙ | ︙ | |||
110170 110171 110172 110173 110174 110175 110176 110177 110178 110179 110180 110181 110182 110183 |
if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName);
pItem++;
}while( --i>0 );
sqlite3DbNNFreeNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
}
/*
** Return the bitwise-OR of all Expr.flags fields in the given
** ExprList.
*/
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
| > > > | 110471 110472 110473 110474 110475 110476 110477 110478 110479 110480 110481 110482 110483 110484 110485 110486 110487 |
if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName);
pItem++;
}while( --i>0 );
sqlite3DbNNFreeNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3 *db, void *pList){
if( ALWAYS(pList) ) exprListDeleteNN(db, (ExprList*)pList);
}
/*
** Return the bitwise-OR of all Expr.flags fields in the given
** ExprList.
*/
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
|
| ︙ | ︙ | |||
114701 114702 114703 114704 114705 114706 114707 114708 114709 114710 114711 114712 114713 |
} /* end loop over pSrcList */
}
return WRC_Continue;
}
case TK_AGG_FUNCTION: {
if( (pNC->ncFlags & NC_InAggFunc)==0
&& pWalker->walkerDepth==pExpr->op2
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
| > | | 115005 115006 115007 115008 115009 115010 115011 115012 115013 115014 115015 115016 115017 115018 115019 115020 115021 115022 115023 115024 115025 115026 |
} /* end loop over pSrcList */
}
return WRC_Continue;
}
case TK_AGG_FUNCTION: {
if( (pNC->ncFlags & NC_InAggFunc)==0
&& pWalker->walkerDepth==pExpr->op2
&& pExpr->pAggInfo==0
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
|
| ︙ | ︙ | |||
114750 114751 114752 114753 114754 114755 114756 114757 114758 114759 114760 114761 114762 114763 |
pExpr->x.pList->a[0].pExpr,0)==0
){
pItem->bOBPayload = 0;
pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct);
}else{
pItem->bOBPayload = 1;
}
}else{
pItem->iOBTab = -1;
}
if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){
pItem->iDistinct = pParse->nTab++;
}else{
pItem->iDistinct = -1;
| > > | 115055 115056 115057 115058 115059 115060 115061 115062 115063 115064 115065 115066 115067 115068 115069 115070 |
pExpr->x.pList->a[0].pExpr,0)==0
){
pItem->bOBPayload = 0;
pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct);
}else{
pItem->bOBPayload = 1;
}
pItem->bUseSubtype =
(pItem->pFunc->funcFlags & SQLITE_SUBTYPE)!=0;
}else{
pItem->iOBTab = -1;
}
if( ExprHasProperty(pExpr, EP_Distinct) && !pItem->bOBUnique ){
pItem->iDistinct = pParse->nTab++;
}else{
pItem->iDistinct = -1;
|
| ︙ | ︙ | |||
120854 120855 120856 120857 120858 120859 120860 |
/*
** Return the expression associated with a column. The expression might be
** the DEFAULT clause or the AS clause of a generated column.
** Return NULL if the column has no associated expression.
*/
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
| | | 121161 121162 121163 121164 121165 121166 121167 121168 121169 121170 121171 121172 121173 121174 121175 |
/*
** Return the expression associated with a column. The expression might be
** the DEFAULT clause or the AS clause of a generated column.
** Return NULL if the column has no associated expression.
*/
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
if( !IsOrdinaryTable(pTab) ) return 0;
if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
}
/*
** Set the collating sequence name for a column.
|
| ︙ | ︙ | |||
121006 121007 121008 121009 121010 121011 121012 121013 121014 121015 121016 121017 121018 121019 |
}
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
assert( db!=0 );
if( !pTable ) return;
if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
deleteTable(db, pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
*/
| > > > | 121313 121314 121315 121316 121317 121318 121319 121320 121321 121322 121323 121324 121325 121326 121327 121328 121329 |
}
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
assert( db!=0 );
if( !pTable ) return;
if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
deleteTable(db, pTable);
}
SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){
sqlite3DeleteTable(db, (Table*)pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
*/
|
| ︙ | ︙ | |||
121544 121545 121546 121547 121548 121549 121550 | } } #endif /* ** Clean up the data structures associated with the RETURNING clause. */ | | > | 121854 121855 121856 121857 121858 121859 121860 121861 121862 121863 121864 121865 121866 121867 121868 121869 |
}
}
#endif
/*
** Clean up the data structures associated with the RETURNING clause.
*/
static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){
Returning *pRet = (Returning*)pArg;
Hash *pHash;
pHash = &(db->aDb[1].pSchema->trigHash);
sqlite3HashInsert(pHash, pRet->zName, 0);
sqlite3ExprListDelete(db, pRet->pReturnEL);
sqlite3DbFree(db, pRet);
}
|
| ︙ | ︙ | |||
121586 121587 121588 121589 121590 121591 121592 |
if( pRet==0 ){
sqlite3ExprListDelete(db, pList);
return;
}
pParse->u1.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
| | < | 121897 121898 121899 121900 121901 121902 121903 121904 121905 121906 121907 121908 121909 121910 121911 |
if( pRet==0 ){
sqlite3ExprListDelete(db, pList);
return;
}
pParse->u1.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet);
testcase( pParse->earlyCleanup );
if( db->mallocFailed ) return;
sqlite3_snprintf(sizeof(pRet->zName), pRet->zName,
"sqlite_returning_%p", pParse);
pRet->retTrig.zName = pRet->zName;
pRet->retTrig.op = TK_RETURNING;
pRet->retTrig.tr_tm = TRIGGER_AFTER;
|
| ︙ | ︙ | |||
125825 125826 125827 125828 125829 125830 125831 125832 125833 125834 125835 125836 125837 125838 |
if( pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
cteClear(db, &pWith->a[i]);
}
sqlite3DbFree(db, pWith);
}
}
#endif /* !defined(SQLITE_OMIT_CTE) */
/************** End of build.c ***********************************************/
/************** Begin file callback.c ****************************************/
/*
** 2005 May 23
| > > > | 126135 126136 126137 126138 126139 126140 126141 126142 126143 126144 126145 126146 126147 126148 126149 126150 126151 |
if( pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
cteClear(db, &pWith->a[i]);
}
sqlite3DbFree(db, pWith);
}
}
SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){
sqlite3WithDelete(db, (With*)pWith);
}
#endif /* !defined(SQLITE_OMIT_CTE) */
/************** End of build.c ***********************************************/
/************** Begin file callback.c ****************************************/
/*
** 2005 May 23
|
| ︙ | ︙ | |||
139051 139052 139053 139054 139055 139056 139057 |
if( pTab->u.vtab.p==0 ) continue;
pVTab = pTab->u.vtab.p->pVtab;
if( NEVER(pVTab==0) ) continue;
if( NEVER(pVTab->pModule==0) ) continue;
if( pVTab->pModule->iVersion<4 ) continue;
if( pVTab->pModule->xIntegrity==0 ) continue;
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
| > | | 139364 139365 139366 139367 139368 139369 139370 139371 139372 139373 139374 139375 139376 139377 139378 139379 |
if( pTab->u.vtab.p==0 ) continue;
pVTab = pTab->u.vtab.p->pVtab;
if( NEVER(pVTab==0) ) continue;
if( NEVER(pVTab->pModule==0) ) continue;
if( pVTab->pModule->iVersion<4 ) continue;
if( pVTab->pModule->xIntegrity==0 ) continue;
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
pTab->nTabRef++;
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, a1);
#endif
continue;
}
if( isQuick || HasRowid(pTab) ){
|
| ︙ | ︙ | |||
141078 141079 141080 141081 141082 141083 141084 141085 141086 141087 141088 141089 141090 141091 |
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Rerun the compilation of a statement after a schema change.
**
| > | 141392 141393 141394 141395 141396 141397 141398 141399 141400 141401 141402 141403 141404 141405 141406 |
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
assert( rc==SQLITE_OK || (*ppStmt)==0 );
return rc;
}
/*
** Rerun the compilation of a statement after a schema change.
**
|
| ︙ | ︙ | |||
141474 141475 141476 141477 141478 141479 141480 141481 141482 141483 141484 141485 141486 141487 |
/*
** Delete the given Select structure and all of its substructures.
*/
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
static Select *findRightmost(Select *p){
while( p->pNext ) p = p->pNext;
| > > > | 141789 141790 141791 141792 141793 141794 141795 141796 141797 141798 141799 141800 141801 141802 141803 141804 141805 |
/*
** Delete the given Select structure and all of its substructures.
*/
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3 *db, void *p){
if( ALWAYS(p) ) clearSelect(db, (Select*)p, 1);
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
static Select *findRightmost(Select *p){
while( p->pNext ) p = p->pNext;
|
| ︙ | ︙ | |||
144495 144496 144497 144498 144499 144500 144501 |
sqlite3KeyInfoUnref(pKeyInfo);
}
multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
if( pDelete ){
| | < < | 144813 144814 144815 144816 144817 144818 144819 144820 144821 144822 144823 144824 144825 144826 144827 |
sqlite3KeyInfoUnref(pKeyInfo);
}
multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
if( pDelete ){
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete);
}
return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** Error message for when two or more terms of a compound select have different
|
| ︙ | ︙ | |||
145048 145049 145050 145051 145052 145053 145054 |
/* Jump to the this point in order to terminate the query.
*/
sqlite3VdbeResolveLabel(v, labelEnd);
/* Make arrangements to free the 2nd and subsequent arms of the compound
** after the parse has finished */
if( pSplit->pPrior ){
| | < | 145364 145365 145366 145367 145368 145369 145370 145371 145372 145373 145374 145375 145376 145377 145378 |
/* Jump to the this point in order to terminate the query.
*/
sqlite3VdbeResolveLabel(v, labelEnd);
/* Make arrangements to free the 2nd and subsequent arms of the compound
** after the parse has finished */
if( pSplit->pPrior ){
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior);
}
pSplit->pPrior = pPrior;
pPrior->pNext = pSplit;
sqlite3ExprListDelete(db, pPrior->pOrderBy);
pPrior->pOrderBy = 0;
/*** TBD: Insert subroutine calls to close cursors on incomplete
|
| ︙ | ︙ | |||
145870 145871 145872 145873 145874 145875 145876 |
**
** pSubitem->pTab is always non-NULL by test restrictions and tests above.
*/
if( ALWAYS(pSubitem->pTab!=0) ){
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
| | < < | 146185 146186 146187 146188 146189 146190 146191 146192 146193 146194 146195 146196 146197 146198 146199 |
**
** pSubitem->pTab is always non-NULL by test restrictions and tests above.
*/
if( ALWAYS(pSubitem->pTab!=0) ){
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
pSubitem->pTab = 0;
}
|
| ︙ | ︙ | |||
146919 146920 146921 146922 146923 146924 146925 |
**
** If bFree is true, do not continue to use the pWith pointer after
** calling this routine, Instead, use only the return value.
*/
SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
if( bFree ){
| | < | 147232 147233 147234 147235 147236 147237 147238 147239 147240 147241 147242 147243 147244 147245 147246 |
**
** If bFree is true, do not continue to use the pWith pointer after
** calling this routine, Instead, use only the return value.
*/
SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
if( bFree ){
pWith = (With*)sqlite3ParserAddCleanup(pParse, sqlite3WithDeleteGeneric,
pWith);
if( pWith==0 ) return 0;
}
if( pParse->nErr==0 ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
|
| ︙ | ︙ | |||
147953 147954 147955 147956 147957 147958 147959 147960 147961 147962 147963 147964 147965 147966 147967 147968 147969 147970 147971 147972 147973 147974 147975 |
if( pFunc->iOBTab>=0 ){
ExprList *pOBList;
KeyInfo *pKeyInfo;
int nExtra = 0;
assert( pFunc->pFExpr->pLeft!=0 );
assert( pFunc->pFExpr->pLeft->op==TK_ORDER );
assert( ExprUseXList(pFunc->pFExpr->pLeft) );
pOBList = pFunc->pFExpr->pLeft->x.pList;
if( !pFunc->bOBUnique ){
nExtra++; /* One extra column for the OP_Sequence */
}
if( pFunc->bOBPayload ){
/* extra columns for the function arguments */
assert( ExprUseXList(pFunc->pFExpr) );
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra);
if( !pFunc->bOBUnique && pParse->nErr==0 ){
pKeyInfo->nKeyField++;
}
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
pFunc->iOBTab, pOBList->nExpr+nExtra, 0,
(char*)pKeyInfo, P4_KEYINFO);
| > > > > | 148265 148266 148267 148268 148269 148270 148271 148272 148273 148274 148275 148276 148277 148278 148279 148280 148281 148282 148283 148284 148285 148286 148287 148288 148289 148290 148291 |
if( pFunc->iOBTab>=0 ){
ExprList *pOBList;
KeyInfo *pKeyInfo;
int nExtra = 0;
assert( pFunc->pFExpr->pLeft!=0 );
assert( pFunc->pFExpr->pLeft->op==TK_ORDER );
assert( ExprUseXList(pFunc->pFExpr->pLeft) );
assert( pFunc->pFunc!=0 );
pOBList = pFunc->pFExpr->pLeft->x.pList;
if( !pFunc->bOBUnique ){
nExtra++; /* One extra column for the OP_Sequence */
}
if( pFunc->bOBPayload ){
/* extra columns for the function arguments */
assert( ExprUseXList(pFunc->pFExpr) );
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
if( pFunc->bUseSubtype ){
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOBList, 0, nExtra);
if( !pFunc->bOBUnique && pParse->nErr==0 ){
pKeyInfo->nKeyField++;
}
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
pFunc->iOBTab, pOBList->nExpr+nExtra, 0,
(char*)pKeyInfo, P4_KEYINFO);
|
| ︙ | ︙ | |||
147988 147989 147990 147991 147992 147993 147994 |
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
| | | | > > > > > > > > > > | 148304 148305 148306 148307 148308 148309 148310 148311 148312 148313 148314 148315 148316 148317 148318 148319 148320 148321 148322 148323 148324 148325 148326 148327 148328 148329 148330 148331 148332 148333 148334 148335 148336 148337 148338 148339 148340 148341 148342 148343 148344 148345 148346 148347 148348 148349 148350 148351 148352 148353 |
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
/* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs
** were stored in emphermal table pF->iOBTab. Here, we extract those
** inputs (in ORDER BY order) and make all calls to OP_AggStep
** before doing the OP_AggFinal call. */
int iTop; /* Start of loop for extracting columns */
int nArg; /* Number of columns to extract */
int nKey; /* Key columns to be skipped */
int regAgg; /* Extract into this array */
int j; /* Loop counter */
assert( pF->pFunc!=0 );
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
if( pF->bOBPayload==0 ){
nKey = 0;
}else{
assert( pF->pFExpr->pLeft!=0 );
assert( ExprUseXList(pF->pFExpr->pLeft) );
assert( pF->pFExpr->pLeft->x.pList!=0 );
nKey = pF->pFExpr->pLeft->x.pList->nExpr;
if( ALWAYS(!pF->bOBUnique) ) nKey++;
}
iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v);
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j);
}
if( pF->bUseSubtype ){
int regSubtype = sqlite3GetTempReg(pParse);
int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0);
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype);
sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j);
}
sqlite3ReleaseTempReg(pParse, regSubtype);
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, iTop);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
|
| ︙ | ︙ | |||
148068 148069 148070 148071 148072 148073 148074 148075 148076 148077 148078 148079 148080 148081 |
int addrNext = 0;
int regAgg;
int regAggSz = 0;
int regDistinct = 0;
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
&& regAcc
){
| > | 148394 148395 148396 148397 148398 148399 148400 148401 148402 148403 148404 148405 148406 148407 148408 |
int addrNext = 0;
int regAgg;
int regAggSz = 0;
int regDistinct = 0;
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
assert( pF->pFunc!=0 );
pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
&& regAcc
){
|
| ︙ | ︙ | |||
148111 148112 148113 148114 148115 148116 148117 148118 148119 148120 148121 148122 148123 148124 148125 148126 148127 148128 148129 148130 148131 148132 148133 148134 148135 148136 148137 |
assert( pOBList->nExpr>0 );
regAggSz = pOBList->nExpr;
if( !pF->bOBUnique ){
regAggSz++; /* One register for OP_Sequence */
}
if( pF->bOBPayload ){
regAggSz += nArg;
}
regAggSz++; /* One extra register to hold result of MakeRecord */
regAgg = sqlite3GetTempRange(pParse, regAggSz);
regDistinct = regAgg;
sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP);
jj = pOBList->nExpr;
if( !pF->bOBUnique ){
sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj);
jj++;
}
if( pF->bOBPayload ){
regDistinct = regAgg+jj;
sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP);
}
}else if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
regDistinct = regAgg;
sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
}else{
| > > > > > > > > > > > | 148438 148439 148440 148441 148442 148443 148444 148445 148446 148447 148448 148449 148450 148451 148452 148453 148454 148455 148456 148457 148458 148459 148460 148461 148462 148463 148464 148465 148466 148467 148468 148469 148470 148471 148472 148473 148474 148475 |
assert( pOBList->nExpr>0 );
regAggSz = pOBList->nExpr;
if( !pF->bOBUnique ){
regAggSz++; /* One register for OP_Sequence */
}
if( pF->bOBPayload ){
regAggSz += nArg;
}
if( pF->bUseSubtype ){
regAggSz += nArg;
}
regAggSz++; /* One extra register to hold result of MakeRecord */
regAgg = sqlite3GetTempRange(pParse, regAggSz);
regDistinct = regAgg;
sqlite3ExprCodeExprList(pParse, pOBList, regAgg, 0, SQLITE_ECEL_DUP);
jj = pOBList->nExpr;
if( !pF->bOBUnique ){
sqlite3VdbeAddOp2(v, OP_Sequence, pF->iOBTab, regAgg+jj);
jj++;
}
if( pF->bOBPayload ){
regDistinct = regAgg+jj;
sqlite3ExprCodeExprList(pParse, pList, regDistinct, 0, SQLITE_ECEL_DUP);
jj += nArg;
}
if( pF->bUseSubtype ){
int kk;
int regBase = pF->bOBPayload ? regDistinct : regAgg;
for(kk=0; kk<nArg; kk++, jj++){
sqlite3VdbeAddOp2(v, OP_GetSubtype, regBase+kk, regAgg+jj);
}
}
}else if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
regDistinct = regAgg;
sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
}else{
|
| ︙ | ︙ | |||
148328 148329 148330 148331 148332 148333 148334 | } return 0; } /* ** Deallocate a single AggInfo object */ | | > | 148666 148667 148668 148669 148670 148671 148672 148673 148674 148675 148676 148677 148678 148679 148680 148681 |
}
return 0;
}
/*
** Deallocate a single AggInfo object
*/
static void agginfoFree(sqlite3 *db, void *pArg){
AggInfo *p = (AggInfo*)pArg;
sqlite3DbFree(db, p->aCol);
sqlite3DbFree(db, p->aFunc);
sqlite3DbFreeNN(db, p);
}
/*
** Attempt to transform a query of the form
|
| ︙ | ︙ | |||
148582 148583 148584 148585 148586 148587 148588 |
if( p->pOrderBy ){
#if TREETRACE_ENABLED
TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
if( sqlite3TreeTrace & 0x800 ){
sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
}
#endif
| | < | | 148921 148922 148923 148924 148925 148926 148927 148928 148929 148930 148931 148932 148933 148934 148935 148936 |
if( p->pOrderBy ){
#if TREETRACE_ENABLED
TREETRACE(0x800,pParse,p, ("dropping superfluous ORDER BY:\n"));
if( sqlite3TreeTrace & 0x800 ){
sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
}
#endif
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric,
p->pOrderBy);
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
|
| ︙ | ︙ | |||
148776 148777 148778 148779 148780 148781 148782 |
&& pSub->pLimit==0 /* Condition (1) */
&& (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
&& (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
&& OptimizationEnabled(db, SQLITE_OmitOrderBy)
){
TREETRACE(0x800,pParse,p,
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
| | < | | 149114 149115 149116 149117 149118 149119 149120 149121 149122 149123 149124 149125 149126 149127 149128 149129 |
&& pSub->pLimit==0 /* Condition (1) */
&& (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
&& (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
&& OptimizationEnabled(db, SQLITE_OmitOrderBy)
){
TREETRACE(0x800,pParse,p,
("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric,
pSub->pOrderBy);
pSub->pOrderBy = 0;
}
/* If the outer query contains a "complex" result set (that is,
** if the result set of the outer query uses functions or subqueries)
** and if the subquery contains an ORDER BY clause and if
** it will be implemented as a co-routine, then do not flatten. This
|
| ︙ | ︙ | |||
149307 149308 149309 149310 149311 149312 149313 |
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
** SELECT statement.
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
if( pAggInfo ){
| | < | 149644 149645 149646 149647 149648 149649 149650 149651 149652 149653 149654 149655 149656 149657 149658 |
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
** SELECT statement.
*/
pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
if( pAggInfo ){
sqlite3ParserAddCleanup(pParse, agginfoFree, pAggInfo);
testcase( pParse->earlyCleanup );
}
if( db->mallocFailed ){
goto select_end;
}
pAggInfo->selId = p->selId;
#ifdef SQLITE_DEBUG
|
| ︙ | ︙ | |||
160985 160986 160987 160988 160989 160990 160991 160992 160993 160994 160995 160996 160997 160998 160999 161000 161001 161002 161003 161004 |
Vdbe *v = pParse->pVdbe;
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
}else if( pOp->opcode==OP_Rowid ){
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
}
| > > > > > > > > > > | 161321 161322 161323 161324 161325 161326 161327 161328 161329 161330 161331 161332 161333 161334 161335 161336 161337 161338 161339 161340 161341 161342 161343 161344 161345 161346 161347 161348 161349 161350 |
Vdbe *v = pParse->pVdbe;
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart);
}
#endif
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
}else if( pOp->opcode==OP_Rowid ){
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart);
}
#endif
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
}
|
| ︙ | ︙ | |||
162317 162318 162319 162320 162321 162322 162323 |
if( rc==SQLITE_OK ){
if( iUpper>iLower ){
nNew = sqlite3LogEst(iUpper - iLower);
/* TUNING: If both iUpper and iLower are derived from the same
** sample, then assume they are 4x more selective. This brings
** the estimated selectivity more in line with what it would be
** if estimated without the use of STAT4 tables. */
| | > | 162663 162664 162665 162666 162667 162668 162669 162670 162671 162672 162673 162674 162675 162676 162677 162678 |
if( rc==SQLITE_OK ){
if( iUpper>iLower ){
nNew = sqlite3LogEst(iUpper - iLower);
/* TUNING: If both iUpper and iLower are derived from the same
** sample, then assume they are 4x more selective. This brings
** the estimated selectivity more in line with what it would be
** if estimated without the use of STAT4 tables. */
if( iLwrIdx==iUprIdx ){ nNew -= 20; }
assert( 20==sqlite3LogEst(4) );
}else{
nNew = 10; assert( 10==sqlite3LogEst(2) );
}
if( nNew<nOut ){
nOut = nNew;
}
WHERETRACE(0x20, ("STAT4 range scan: %u..%u est=%d\n",
|
| ︙ | ︙ | |||
182232 182233 182234 182235 182236 182237 182238 182239 182240 182241 182242 182243 182244 182245 |
*piValue = Tuning(-id);
}else{
rc = SQLITE_NOTFOUND;
}
break;
}
#endif
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
return rc;
}
/*
| > > > > > > > > > > > > > > > > > > > > > > | 182579 182580 182581 182582 182583 182584 182585 182586 182587 182588 182589 182590 182591 182592 182593 182594 182595 182596 182597 182598 182599 182600 182601 182602 182603 182604 182605 182606 182607 182608 182609 182610 182611 182612 182613 182614 |
*piValue = Tuning(-id);
}else{
rc = SQLITE_NOTFOUND;
}
break;
}
#endif
/* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff);
**
** Activate or deactivate validation of JSONB that is generated from
** text. Off by default, as the validation is slow. Validation is
** only available if compiled using SQLITE_DEBUG.
**
** If onOff is initially 1, then turn it on. If onOff is initially
** off, turn it off. If onOff is initially -1, then change onOff
** to be the current setting.
*/
case SQLITE_TESTCTRL_JSON_SELFCHECK: {
#if defined(SQLITE_DEBUG)
int *pOnOff = va_arg(ap, int*);
if( *pOnOff<0 ){
*pOnOff = sqlite3Config.bJsonSelfcheck;
}else{
sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff);
}
#endif
break;
}
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
return rc;
}
/*
|
| ︙ | ︙ | |||
202646 202647 202648 202649 202650 202651 202652 | ** ** 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. ** ****************************************************************************** ** | | | > > > > > > > > > > > > > > > > > > | > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > | | > > | 203015 203016 203017 203018 203019 203020 203021 203022 203023 203024 203025 203026 203027 203028 203029 203030 203031 203032 203033 203034 203035 203036 203037 203038 203039 203040 203041 203042 203043 203044 203045 203046 203047 203048 203049 203050 203051 203052 203053 203054 203055 203056 203057 203058 203059 203060 203061 203062 203063 203064 203065 203066 203067 203068 203069 203070 203071 203072 203073 203074 203075 203076 203077 203078 203079 203080 203081 203082 203083 203084 203085 203086 203087 203088 203089 203090 203091 203092 203093 203094 203095 203096 203097 203098 203099 203100 203101 203102 203103 203104 203105 203106 203107 203108 203109 203110 203111 203112 203113 203114 203115 203116 203117 203118 203119 203120 203121 203122 203123 203124 203125 203126 203127 203128 203129 203130 203131 203132 203133 203134 203135 203136 203137 203138 203139 203140 203141 203142 203143 203144 203145 203146 203147 203148 203149 203150 203151 203152 203153 203154 203155 203156 203157 203158 203159 203160 203161 203162 203163 203164 203165 203166 203167 203168 203169 203170 203171 203172 203173 203174 203175 203176 203177 203178 203179 203180 203181 203182 203183 203184 203185 203186 203187 203188 203189 203190 203191 203192 203193 203194 203195 203196 203197 |
**
** 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.
**
******************************************************************************
**
** SQLite JSON functions.
**
** This file began as an extension in ext/misc/json1.c in 2015. That
** extension proved so useful that it has now been moved into the core.
**
** The original design stored all JSON as pure text, canonical RFC-8259.
** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16).
** All generated JSON text still conforms strictly to RFC-8259, but text
** with JSON-5 extensions is accepted as input.
**
** Beginning with version 3.45.0 (pending), these routines also accept
** BLOB values that have JSON encoded using a binary representation we
** call JSONB. The name JSONB comes from PostgreSQL, however the on-disk
** format SQLite JSONB is completely different and incompatible with
** PostgreSQL JSONB.
**
** Decoding and interpreting JSONB is still O(N) where N is the size of
** the input, the same as text JSON. However, the constant of proportionality
** for JSONB is much smaller due to faster parsing. The size of each
** element in JSONB is encoded in its header, so there is no need to search
** for delimiters using persnickety syntax rules. JSONB seems to be about
** 3x faster than text JSON as a result. JSONB is also tends to be slightly
** smaller than text JSON, by 5% or 10%, but there are corner cases where
** JSONB can be slightly larger. So you are not far mistaken to say that
** a JSONB blob is the same size as the equivalent RFC-8259 text.
**
**
** THE JSONB ENCODING:
**
** Every JSON element is encoded in JSONB as a header and a payload.
** The header is between 1 and 9 bytes in size. The payload is zero
** or more bytes.
**
** The lower 4 bits of the first byte of the header determines the
** element type:
**
** 0: NULL
** 1: TRUE
** 2: FALSE
** 3: INT -- RFC-8259 integer literal
** 4: INT5 -- JSON5 integer literal
** 5: FLOAT -- RFC-8259 floating point literal
** 6: FLOAT5 -- JSON5 floating point literal
** 7: TEXT -- Text literal acceptable to both SQL and JSON
** 8: TEXTJ -- Text containing RFC-8259 escapes
** 9: TEXT5 -- Text containing JSON5 and/or RFC-8259 escapes
** 10: TEXTRAW -- Text containing unescaped syntax characters
** 11: ARRAY
** 12: OBJECT
**
** The other three possible values (13-15) are reserved for future
** enhancements.
**
** The upper 4 bits of the first byte determine the size of the header
** and sometimes also the size of the payload. If X is the first byte
** of the element and if X>>4 is between 0 and 11, then the payload
** will be that many bytes in size and the header is exactly one byte
** in size. Other four values for X>>4 (12-15) indicate that the header
** is more than one byte in size and that the payload size is determined
** by the remainder of the header, interpreted as a unsigned big-endian
** integer.
**
** Value of X>>4 Size integer Total header size
** ------------- -------------------- -----------------
** 12 1 byte (0-255) 2
** 13 2 byte (0-65535) 3
** 14 4 byte (0-4294967295) 5
** 15 8 byte (0-1.8e19) 9
**
** The payload size need not be expressed in its minimal form. For example,
** if the payload size is 10, the size can be expressed in any of 5 different
** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by on 0x0a byte,
** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by
** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and
** a single byte of 0x0a. The shorter forms are preferred, of course, but
** sometimes when generating JSONB, the payload size is not known in advance
** and it is convenient to reserve sufficient header space to cover the
** largest possible payload size and then come back later and patch up
** the size when it becomes known, resulting in a non-minimal encoding.
**
** The value (X>>4)==15 is not actually used in the current implementation
** (as SQLite is currently unable handle BLOBs larger than about 2GB)
** but is included in the design to allow for future enhancements.
**
** The payload follows the header. NULL, TRUE, and FALSE have no payload and
** their payload size must always be zero. The payload for INT, INT5,
** FLOAT, FLOAT5, TEXT, TEXTJ, TEXT5, and TEXTROW is text. Note that the
** "..." or '...' delimiters are omitted from the various text encodings.
** The payload for ARRAY and OBJECT is a list of additional elements that
** are the content for the array or object. The payload for an OBJECT
** must be an even number of elements. The first element of each pair is
** the label and must be of type TEXT, TEXTJ, TEXT5, or TEXTRAW.
**
** A valid JSONB blob consists of a single element, as described above.
** Usually this will be an ARRAY or OBJECT element which has many more
** elements as its content. But the overall blob is just a single element.
**
** Input validation for JSONB blobs simply checks that the element type
** code is between 0 and 12 and that the total size of the element
** (header plus payload) is the same as the size of the BLOB. If those
** checks are true, the BLOB is assumed to be JSONB and processing continues.
** Errors are only raised if some other miscoding is discovered during
** processing.
*/
#ifndef SQLITE_OMIT_JSON
/* #include "sqliteInt.h" */
/* JSONB element types
*/
#define JSONB_NULL 0 /* "null" */
#define JSONB_TRUE 1 /* "true" */
#define JSONB_FALSE 2 /* "false" */
#define JSONB_INT 3 /* integer acceptable to JSON and SQL */
#define JSONB_INT5 4 /* integer in 0x000 notation */
#define JSONB_FLOAT 5 /* float acceptable to JSON and SQL */
#define JSONB_FLOAT5 6 /* float with JSON5 extensions */
#define JSONB_TEXT 7 /* Text compatible with both JSON and SQL */
#define JSONB_TEXTJ 8 /* Text with JSON escapes */
#define JSONB_TEXT5 9 /* Text with JSON-5 escape */
#define JSONB_TEXTRAW 10 /* SQL text that needs escaping for JSON */
#define JSONB_ARRAY 11 /* An array */
#define JSONB_OBJECT 12 /* An object */
/* Human-readable names for the JSONB values. The index for each
** string must correspond to the JSONB_* integer above.
*/
static const char * const jsonbType[] = {
"null", "true", "false", "integer", "integer",
"real", "real", "text", "text", "text",
"text", "array", "object", "", "", "", ""
};
/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function, resulting in a 7% overall performance
** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static const char jsonIsSpace[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
/*
** The set of all space characters recognized by jsonIsspace().
** Useful as the second argument to strspn().
*/
static const char jsonSpaces[] = "\011\012\015\040";
/*
** Characters that are special to JSON. Control characters,
** '"' and '\\' and '\''. Actually, '\'' is not special to
** canonical JSON, but it is special in JSON-5, so we include
** it in the set of special characters.
*/
static const char jsonIsOk[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| ︙ | ︙ | |||
202710 202711 202712 202713 202714 202715 202716 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | < < < < < < < | | > > > > > > > > > > > > > > > > > > | > > > > > > > > | < < < < < < < < | < < < | | | < < < < < | > > < < < < < < | | < < | | < | | | < < < < < < < < < < < < < < < < < < < < < | < | | > < | | | < < < < < < < < < > > | | | | | < | < | < < < > | | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | | | | | | | | | | | | | | | | | | | | < < < < < < | < | | > > > | > > > | < > | > > | > | > > > > > > > > > > > | | | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 203205 203206 203207 203208 203209 203210 203211 203212 203213 203214 203215 203216 203217 203218 203219 203220 203221 203222 203223 203224 203225 203226 203227 203228 203229 203230 203231 203232 203233 203234 203235 203236 203237 203238 203239 203240 203241 203242 203243 203244 203245 203246 203247 203248 203249 203250 203251 203252 203253 203254 203255 203256 203257 203258 203259 203260 203261 203262 203263 203264 203265 203266 203267 203268 203269 203270 203271 203272 203273 203274 203275 203276 203277 203278 203279 203280 203281 203282 203283 203284 203285 203286 203287 203288 203289 203290 203291 203292 203293 203294 203295 203296 203297 203298 203299 203300 203301 203302 203303 203304 203305 203306 203307 203308 203309 203310 203311 203312 203313 203314 203315 203316 203317 203318 203319 203320 203321 203322 203323 203324 203325 203326 203327 203328 203329 203330 203331 203332 203333 203334 203335 203336 203337 203338 203339 203340 203341 203342 203343 203344 203345 203346 203347 203348 203349 203350 203351 203352 203353 203354 203355 203356 203357 203358 203359 203360 203361 203362 203363 203364 203365 203366 203367 203368 203369 203370 203371 203372 203373 203374 203375 203376 203377 203378 203379 203380 203381 203382 203383 203384 203385 203386 203387 203388 203389 203390 203391 203392 203393 203394 203395 203396 203397 203398 203399 203400 203401 203402 203403 203404 203405 203406 203407 203408 203409 203410 203411 203412 203413 203414 203415 203416 203417 203418 203419 203420 203421 203422 203423 203424 203425 203426 203427 203428 203429 203430 203431 203432 203433 203434 203435 203436 203437 203438 203439 203440 203441 203442 203443 203444 203445 203446 203447 203448 203449 203450 203451 203452 203453 203454 203455 203456 203457 203458 203459 203460 203461 203462 203463 203464 203465 203466 203467 203468 203469 203470 203471 203472 203473 203474 203475 203476 203477 203478 203479 203480 203481 203482 203483 203484 203485 203486 203487 203488 203489 203490 203491 203492 203493 203494 203495 203496 203497 203498 203499 203500 203501 203502 203503 203504 203505 203506 203507 203508 203509 203510 203511 203512 203513 203514 203515 203516 203517 203518 203519 203520 203521 203522 203523 203524 203525 203526 203527 203528 203529 203530 203531 203532 203533 203534 203535 203536 203537 203538 203539 203540 203541 203542 203543 203544 203545 203546 203547 203548 203549 203550 203551 203552 203553 203554 203555 203556 203557 203558 203559 203560 203561 203562 203563 203564 203565 203566 203567 203568 203569 203570 203571 203572 203573 203574 203575 203576 203577 203578 203579 203580 203581 203582 203583 203584 203585 203586 203587 203588 203589 203590 203591 203592 203593 203594 203595 203596 203597 203598 203599 203600 203601 203602 203603 203604 203605 203606 203607 203608 203609 203610 203611 203612 203613 203614 203615 203616 203617 203618 203619 203620 203621 203622 203623 203624 203625 203626 203627 203628 203629 203630 203631 203632 203633 203634 203635 203636 203637 203638 203639 203640 203641 203642 203643 203644 203645 203646 203647 203648 203649 203650 203651 203652 203653 203654 203655 203656 203657 203658 203659 203660 203661 203662 203663 203664 203665 203666 203667 203668 203669 203670 203671 203672 203673 203674 203675 203676 203677 203678 203679 203680 203681 203682 203683 203684 203685 203686 203687 203688 203689 203690 203691 |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
/* Objects */
typedef struct JsonCache JsonCache;
typedef struct JsonString JsonString;
typedef struct JsonParse JsonParse;
/*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/
#define JSON_CACHE_ID (-429938) /* Cache entry */
#define JSON_CACHE_SIZE 4 /* Max number of cache entries */
/* A cache mapping JSON text into JSONB blobs.
**
** Each cache entry is a JsonParse object with the following restrictions:
**
** * The bReadOnly flag must be set
**
** * The aBlob[] array must be owned by the JsonParse object. In other
** words, nBlobAlloc must be non-zero.
**
** * zJson must be an RCStr. In other words bJsonIsRCStr must be true.
*/
struct JsonCache {
sqlite3 *db; /* Database connection */
int nUsed; /* Number of active entries in the cache */
JsonParse *a[JSON_CACHE_SIZE]; /* One line for each cache entry */
};
/* An instance of this object represents a JSON string
** under construction. Really, this is a generic string accumulator
** that can be and is used to create strings other than JSON.
**
** If the generated string is longer than will fit into the zSpace[] buffer,
** then it will be an RCStr string. This aids with caching of large
** JSON strings.
*/
struct JsonString {
sqlite3_context *pCtx; /* Function context - put error messages here */
char *zBuf; /* Append JSON content here */
u64 nAlloc; /* Bytes of storage available in zBuf[] */
u64 nUsed; /* Bytes of zBuf[] currently used */
u8 bStatic; /* True if zBuf is static space */
u8 eErr; /* True if an error has been encountered */
char zSpace[100]; /* Initial static space */
};
/* Allowed values for JsonString.eErr */
#define JSTRING_OOM 0x01 /* Out of memory */
#define JSTRING_MALFORMED 0x02 /* Malformed JSONB */
#define JSTRING_ERR 0x04 /* Error already sent to sqlite3_result */
/* The "subtype" set for text JSON values passed through using
** sqlite3_result_subtype() and sqlite3_value_subtype().
*/
#define JSON_SUBTYPE 74 /* Ascii for "J" */
/*
** Bit values for the flags passed into various SQL function implementations
** via the sqlite3_user_data() value.
*/
#define JSON_JSON 0x01 /* Result is always JSON */
#define JSON_SQL 0x02 /* Result is always SQL */
#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
#define JSON_BLOB 0x08 /* Use the BLOB output format */
/* A parsed JSON value. Lifecycle:
**
** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
** original text is stored in zJson. This step is skipped if the
** input is JSONB instead of text JSON.
**
** 2. The aBlob[] array is searched using the JSON path notation, if needed.
**
** 3. Zero or more changes are made to aBlob[] (via json_remove() or
** json_replace() or json_patch() or similar).
**
** 4. New JSON text is generated from the aBlob[] for output. This step
** is skipped the function is one of the jsonb_* functions that returns
** JSONB instead of text JSON.
*/
struct JsonParse {
u8 *aBlob; /* JSONB representation of JSON value */
u32 nBlob; /* Bytes of aBlob[] actually used */
u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */
char *zJson; /* Json text used for parsing */
int nJson; /* Length of the zJson string in bytes */
u16 iDepth; /* Nesting depth */
u8 nErr; /* Number of errors seen */
u8 oom; /* Set to true if out of memory */
u8 bJsonIsRCStr; /* True if zJson is an RCStr */
u8 hasNonstd; /* True if input uses non-standard features like JSON5 */
u8 bReadOnly; /* Do not modify. */
u32 nJPRef; /* Number of references to this object */
u32 iErr; /* Error location in zJson[] */
/* Search and edit information. See jsonLookupStep() */
u8 eEdit; /* Edit operation to apply */
int delta; /* Size change due to the edit */
u32 nIns; /* Number of bytes to insert */
u32 iLabel; /* Location of label if search landed on an object value */
u8 *aIns; /* Content to be inserted */
};
/* Allowed values for JsonParse.eEdit */
#define JEDIT_DEL 1 /* Delete if exists */
#define JEDIT_REPL 2 /* Overwrite if exists */
#define JEDIT_INS 3 /* Insert if not exists */
#define JEDIT_SET 4 /* Insert or overwrite */
/*
** Maximum nesting depth of JSON for this implementation.
**
** This limit is needed to avoid a stack overflow in the recursive
** descent parser. A depth of 1000 is far deeper than any sane JSON
** should go. Historical note: This limit was 2000 prior to version 3.42.0
*/
#ifndef SQLITE_JSON_MAX_DEPTH
# define JSON_MAX_DEPTH 1000
#else
# define JSON_MAX_DEPTH SQLITE_JSON_MAX_DEPTH
#endif
/*
** Allowed values for the flgs argument to jsonParseFuncArg();
*/
#define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */
#define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */
/**************************************************************************
** Forward references
**************************************************************************/
static void jsonReturnStringAsBlob(JsonString*);
static int jsonFuncArgMightBeBinary(sqlite3_value *pJson);
static u32 jsonXlateBlobToText(const JsonParse*,u32,JsonString*);
static void jsonReturnParse(sqlite3_context*,JsonParse*);
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
static void jsonParseFree(JsonParse*);
static u32 jsonbPayloadSize(const JsonParse*, u32, u32*);
static u32 jsonUnescapeOneChar(const char*, u32, u32*);
/**************************************************************************
** Utility routines for dealing with JsonCache objects
**************************************************************************/
/*
** Free a JsonCache object.
*/
static void jsonCacheDelete(JsonCache *p){
int i;
for(i=0; i<p->nUsed; i++){
jsonParseFree(p->a[i]);
}
sqlite3DbFree(p->db, p);
}
static void jsonCacheDeleteGeneric(void *p){
jsonCacheDelete((JsonCache*)p);
}
/*
** Insert a new entry into the cache. If the cache is full, expel
** the least recently used entry. Return SQLITE_OK on success or a
** result code otherwise.
**
** Cache entries are stored in age order, oldest first.
*/
static int jsonCacheInsert(
sqlite3_context *ctx, /* The SQL statement context holding the cache */
JsonParse *pParse /* The parse object to be added to the cache */
){
JsonCache *p;
assert( pParse->zJson!=0 );
assert( pParse->bJsonIsRCStr );
p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID);
if( p==0 ){
sqlite3 *db = sqlite3_context_db_handle(ctx);
p = sqlite3DbMallocZero(db, sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
p->db = db;
sqlite3_set_auxdata(ctx, JSON_CACHE_ID, p, jsonCacheDeleteGeneric);
p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID);
if( p==0 ) return SQLITE_NOMEM;
}
if( p->nUsed >= JSON_CACHE_SIZE ){
jsonParseFree(p->a[0]);
memmove(p->a, &p->a[1], (JSON_CACHE_SIZE-1)*sizeof(p->a[0]));
p->nUsed = JSON_CACHE_SIZE-1;
}
assert( pParse->nBlobAlloc>0 );
pParse->eEdit = 0;
pParse->nJPRef++;
pParse->bReadOnly = 1;
p->a[p->nUsed] = pParse;
p->nUsed++;
return SQLITE_OK;
}
/*
** Search for a cached translation the json text supplied by pArg. Return
** the JsonParse object if found. Return NULL if not found.
**
** When a match if found, the matching entry is moved to become the
** most-recently used entry if it isn't so already.
**
** The JsonParse object returned still belongs to the Cache and might
** be deleted at any moment. If the caller whants the JsonParse to
** linger, it needs to increment the nPJRef reference counter.
*/
static JsonParse *jsonCacheSearch(
sqlite3_context *ctx, /* The SQL statement context holding the cache */
sqlite3_value *pArg /* Function argument containing SQL text */
){
JsonCache *p;
int i;
const char *zJson;
int nJson;
if( sqlite3_value_type(pArg)!=SQLITE_TEXT ){
return 0;
}
zJson = (const char*)sqlite3_value_text(pArg);
if( zJson==0 ) return 0;
nJson = sqlite3_value_bytes(pArg);
p = sqlite3_get_auxdata(ctx, JSON_CACHE_ID);
if( p==0 ){
return 0;
}
for(i=0; i<p->nUsed; i++){
if( p->a[i]->zJson==zJson ) break;
}
if( i>=p->nUsed ){
for(i=0; i<p->nUsed; i++){
if( p->a[i]->nJson!=nJson ) continue;
if( memcmp(p->a[i]->zJson, zJson, nJson)==0 ) break;
}
}
if( i<p->nUsed ){
if( i<p->nUsed-1 ){
/* Make the matching entry the most recently used entry */
JsonParse *tmp = p->a[i];
memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp));
p->a[p->nUsed-1] = tmp;
i = p->nUsed - 1;
}
return p->a[i];
}else{
return 0;
}
}
/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/
/* Turn uninitialized bulk memory into a valid JsonString object
** holding a zero-length string.
*/
static void jsonStringZero(JsonString *p){
p->zBuf = p->zSpace;
p->nAlloc = sizeof(p->zSpace);
p->nUsed = 0;
p->bStatic = 1;
}
/* Initialize the JsonString object
*/
static void jsonStringInit(JsonString *p, sqlite3_context *pCtx){
p->pCtx = pCtx;
p->eErr = 0;
jsonStringZero(p);
}
/* Free all allocated memory and reset the JsonString object back to its
** initial state.
*/
static void jsonStringReset(JsonString *p){
if( !p->bStatic ) sqlite3RCStrUnref(p->zBuf);
jsonStringZero(p);
}
/* Report an out-of-memory (OOM) condition
*/
static void jsonStringOom(JsonString *p){
p->eErr |= JSTRING_OOM;
if( p->pCtx ) sqlite3_result_error_nomem(p->pCtx);
jsonStringReset(p);
}
/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
** Return zero on success. Return non-zero on an OOM error
*/
static int jsonStringGrow(JsonString *p, u32 N){
u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
char *zNew;
if( p->bStatic ){
if( p->eErr ) return 1;
zNew = sqlite3RCStrNew(nTotal);
if( zNew==0 ){
jsonStringOom(p);
return SQLITE_NOMEM;
}
memcpy(zNew, p->zBuf, (size_t)p->nUsed);
p->zBuf = zNew;
p->bStatic = 0;
}else{
p->zBuf = sqlite3RCStrResize(p->zBuf, nTotal);
if( p->zBuf==0 ){
p->eErr |= JSTRING_OOM;
jsonStringZero(p);
return SQLITE_NOMEM;
}
}
p->nAlloc = nTotal;
return SQLITE_OK;
}
/* Append N bytes from zIn onto the end of the JsonString string.
*/
static SQLITE_NOINLINE void jsonStringExpandAndAppend(
JsonString *p,
const char *zIn,
u32 N
){
assert( N>0 );
if( jsonStringGrow(p,N) ) return;
memcpy(p->zBuf+p->nUsed, zIn, N);
p->nUsed += N;
}
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
if( N==0 ) return;
if( N+p->nUsed >= p->nAlloc ){
jsonStringExpandAndAppend(p,zIn,N);
}else{
memcpy(p->zBuf+p->nUsed, zIn, N);
p->nUsed += N;
}
}
static void jsonAppendRawNZ(JsonString *p, const char *zIn, u32 N){
assert( N>0 );
if( N+p->nUsed >= p->nAlloc ){
jsonStringExpandAndAppend(p,zIn,N);
}else{
memcpy(p->zBuf+p->nUsed, zIn, N);
p->nUsed += N;
}
}
/* Append formatted text (not to exceed N bytes) to the JsonString.
*/
static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
va_list ap;
if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return;
va_start(ap, zFormat);
sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
va_end(ap);
p->nUsed += (int)strlen(p->zBuf+p->nUsed);
}
/* Append a single character
*/
static SQLITE_NOINLINE void jsonAppendCharExpand(JsonString *p, char c){
if( jsonStringGrow(p,1) ) return;
p->zBuf[p->nUsed++] = c;
}
static void jsonAppendChar(JsonString *p, char c){
if( p->nUsed>=p->nAlloc ){
jsonAppendCharExpand(p,c);
}else{
p->zBuf[p->nUsed++] = c;
}
}
/* Make sure there is a zero terminator on p->zBuf[]
**
** Return true on success. Return false if an OOM prevents this
** from happening.
*/
static int jsonStringTerminate(JsonString *p){
jsonAppendChar(p, 0);
p->nUsed--;
return p->eErr==0;
}
/* Append a comma separator to the output buffer, if the previous
** character is not '[' or '{'.
*/
static void jsonAppendSeparator(JsonString *p){
char c;
if( p->nUsed==0 ) return;
c = p->zBuf[p->nUsed-1];
if( c=='[' || c=='{' ) return;
jsonAppendChar(p, ',');
}
/* Append the N-byte string in zIn to the end of the JsonString string
** under construction. Enclose the string in double-quotes ("...") and
** escape any double-quotes or backslash characters contained within the
** string.
**
** This routine is a high-runner. There is a measurable performance
** increase associated with unwinding the jsonIsOk[] loop.
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 k;
u8 c;
const u8 *z = (const u8*)zIn;
if( z==0 ) return;
if( (N+p->nUsed+2 >= p->nAlloc) && jsonStringGrow(p,N+2)!=0 ) return;
p->zBuf[p->nUsed++] = '"';
while( 1 /*exit-by-break*/ ){
k = 0;
while( k+1<N && jsonIsOk[z[k]] && jsonIsOk[z[k+1]] ){ k += 2; } /* <--, */
while( k<N && jsonIsOk[z[k]] ){ k++; } /* <-- loop unwound for speed */
if( k>=N ){
if( k>0 ){
memcpy(&p->zBuf[p->nUsed], z, k);
p->nUsed += k;
}
break;
}
if( k>0 ){
memcpy(&p->zBuf[p->nUsed], z, k);
p->nUsed += k;
z += k;
N -= k;
}
c = z[0];
if( c=='"' || c=='\\' ){
json_simple_escape:
if( (p->nUsed+N+3 > p->nAlloc) && jsonStringGrow(p,N+3)!=0 ) return;
p->zBuf[p->nUsed++] = '\\';
p->zBuf[p->nUsed++] = c;
}else if( c=='\'' ){
p->zBuf[p->nUsed++] = c;
}else{
static const char aSpecial[] = {
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
assert( sizeof(aSpecial)==32 );
assert( aSpecial['\b']=='b' );
assert( aSpecial['\f']=='f' );
assert( aSpecial['\n']=='n' );
assert( aSpecial['\r']=='r' );
assert( aSpecial['\t']=='t' );
assert( c>=0 && c<sizeof(aSpecial) );
if( aSpecial[c] ){
c = aSpecial[c];
goto json_simple_escape;
}
if( (p->nUsed+N+7 > p->nAlloc) && jsonStringGrow(p,N+7)!=0 ) return;
p->zBuf[p->nUsed++] = '\\';
p->zBuf[p->nUsed++] = 'u';
p->zBuf[p->nUsed++] = '0';
p->zBuf[p->nUsed++] = '0';
p->zBuf[p->nUsed++] = "0123456789abcdef"[c>>4];
p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf];
}
z++;
N--;
}
p->zBuf[p->nUsed++] = '"';
assert( p->nUsed<p->nAlloc );
}
/*
** Append an sqlite3_value (such as a function parameter) to the JSON
** string under construction in p.
*/
static void jsonAppendSqlValue(
JsonString *p, /* Append to this JSON string */
sqlite3_value *pValue /* Value to append */
){
switch( sqlite3_value_type(pValue) ){
case SQLITE_NULL: {
jsonAppendRawNZ(p, "null", 4);
break;
|
| ︙ | ︙ | |||
203221 203222 203223 203224 203225 203226 203227 |
jsonAppendRaw(p, z, n);
}else{
jsonAppendString(p, z, n);
}
break;
}
default: {
| > > > > > > | | | | | | > > > > | > > > > > > | > > > | | > > | > > > > > > > > > | | > | | > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | > | | > | | < < < < > | | | | | | | | < < < < < < < < < < < < < < < < | < < < < < < | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < | | > < | | | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 203707 203708 203709 203710 203711 203712 203713 203714 203715 203716 203717 203718 203719 203720 203721 203722 203723 203724 203725 203726 203727 203728 203729 203730 203731 203732 203733 203734 203735 203736 203737 203738 203739 203740 203741 203742 203743 203744 203745 203746 203747 203748 203749 203750 203751 203752 203753 203754 203755 203756 203757 203758 203759 203760 203761 203762 203763 203764 203765 203766 203767 203768 203769 203770 203771 203772 203773 203774 203775 203776 203777 203778 203779 203780 203781 203782 203783 203784 203785 203786 203787 203788 203789 203790 203791 203792 203793 203794 203795 203796 203797 203798 203799 203800 203801 203802 203803 203804 203805 203806 203807 203808 203809 203810 203811 203812 203813 203814 203815 203816 203817 203818 203819 203820 203821 203822 203823 203824 203825 203826 203827 203828 203829 203830 203831 203832 203833 203834 203835 203836 203837 203838 203839 203840 203841 203842 203843 203844 203845 203846 203847 203848 203849 203850 203851 203852 203853 203854 203855 203856 203857 |
jsonAppendRaw(p, z, n);
}else{
jsonAppendString(p, z, n);
}
break;
}
default: {
if( jsonFuncArgMightBeBinary(pValue) ){
JsonParse px;
memset(&px, 0, sizeof(px));
px.aBlob = (u8*)sqlite3_value_blob(pValue);
px.nBlob = sqlite3_value_bytes(pValue);
jsonXlateBlobToText(&px, 0, p);
}else if( p->eErr==0 ){
sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
p->eErr = JSTRING_ERR;
jsonStringReset(p);
}
break;
}
}
}
/* Make the text in p (which is probably a generated JSON text string)
** the result of the SQL function.
**
** The JsonString is reset.
**
** If pParse and ctx are both non-NULL, then the SQL string in p is
** loaded into the zJson field of the pParse object as a RCStr and the
** pParse is added to the cache.
*/
static void jsonReturnString(
JsonString *p, /* String to return */
JsonParse *pParse, /* JSONB source or NULL */
sqlite3_context *ctx /* Where to cache */
){
assert( (pParse!=0)==(ctx!=0) );
assert( ctx==0 || ctx==p->pCtx );
if( p->eErr==0 ){
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(p->pCtx));
if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(p);
}else if( p->bStatic ){
sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
SQLITE_TRANSIENT, SQLITE_UTF8);
}else if( jsonStringTerminate(p) ){
if( pParse && pParse->bJsonIsRCStr==0 && pParse->nBlobAlloc>0 ){
int rc;
pParse->zJson = sqlite3RCStrRef(p->zBuf);
pParse->nJson = p->nUsed;
pParse->bJsonIsRCStr = 1;
rc = jsonCacheInsert(ctx, pParse);
if( rc==SQLITE_NOMEM ){
sqlite3_result_error_nomem(ctx);
jsonStringReset(p);
return;
}
}
sqlite3_result_text64(p->pCtx, sqlite3RCStrRef(p->zBuf), p->nUsed,
sqlite3RCStrUnref,
SQLITE_UTF8);
}else{
sqlite3_result_error_nomem(p->pCtx);
}
}else if( p->eErr & JSTRING_OOM ){
sqlite3_result_error_nomem(p->pCtx);
}else if( p->eErr & JSTRING_MALFORMED ){
sqlite3_result_error(p->pCtx, "malformed JSON", -1);
}
jsonStringReset(p);
}
/**************************************************************************
** Utility routines for dealing with JsonParse objects
**************************************************************************/
/*
** Reclaim all memory allocated by a JsonParse object. But do not
** delete the JsonParse object itself.
*/
static void jsonParseReset(JsonParse *pParse){
assert( pParse->nJPRef<=1 );
if( pParse->bJsonIsRCStr ){
sqlite3RCStrUnref(pParse->zJson);
pParse->zJson = 0;
pParse->nJson = 0;
pParse->bJsonIsRCStr = 0;
}
if( pParse->nBlobAlloc ){
sqlite3_free(pParse->aBlob);
pParse->aBlob = 0;
pParse->nBlob = 0;
pParse->nBlobAlloc = 0;
}
}
/*
** Decrement the reference count on the JsonParse object. When the
** count reaches zero, free the object.
*/
static void jsonParseFree(JsonParse *pParse){
if( pParse ){
if( pParse->nJPRef>1 ){
pParse->nJPRef--;
}else{
jsonParseReset(pParse);
sqlite3_free(pParse);
}
}
}
/**************************************************************************
** Utility routines for the JSON text parser
**************************************************************************/
/*
** Translate a single byte of Hex into an integer.
** This routine only gives a correct answer if h really is a valid hexadecimal
** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not
** assert() if the digit is not hex.
*/
static u8 jsonHexToInt(int h){
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
return (u8)(h & 0xf);
}
/*
** Convert a 4-byte hex string into an integer
*/
static u32 jsonHexToInt4(const char *z){
u32 v;
v = (jsonHexToInt(z[0])<<12)
+ (jsonHexToInt(z[1])<<8)
+ (jsonHexToInt(z[2])<<4)
+ jsonHexToInt(z[3]);
return v;
}
/*
** Return true if z[] begins with 2 (or more) hexadecimal digits
*/
static int jsonIs2Hex(const char *z){
return sqlite3Isxdigit(z[0]) && sqlite3Isxdigit(z[1]);
}
|
| ︙ | ︙ | |||
203955 203956 203957 203958 203959 203960 203961 |
char c2;
char n;
char eType;
char nRepl;
char *zMatch;
char *zRepl;
} aNanInfName[] = {
| | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > | | | | | | | | | > | < > | | > | > | | > | | | < | > | | | | | | | > | > | < | | | | | | | | | | > | > > > > > > > > > | | | > > > | | | | | | < | < | | | | | | > | | | | | > > > > | | 203997 203998 203999 204000 204001 204002 204003 204004 204005 204006 204007 204008 204009 204010 204011 204012 204013 204014 204015 204016 204017 204018 204019 204020 204021 204022 204023 204024 204025 204026 204027 204028 204029 204030 204031 204032 204033 204034 204035 204036 204037 204038 204039 204040 204041 204042 204043 204044 204045 204046 204047 204048 204049 204050 204051 204052 204053 204054 204055 204056 204057 204058 204059 204060 204061 204062 204063 204064 204065 204066 204067 204068 204069 204070 204071 204072 204073 204074 204075 204076 204077 204078 204079 204080 204081 204082 204083 204084 204085 204086 204087 204088 204089 204090 204091 204092 204093 204094 204095 204096 204097 204098 204099 204100 204101 204102 204103 204104 204105 204106 204107 204108 204109 204110 204111 204112 204113 204114 204115 204116 204117 204118 204119 204120 204121 204122 204123 204124 204125 204126 204127 204128 204129 204130 204131 204132 204133 204134 204135 204136 204137 204138 204139 204140 204141 204142 204143 204144 204145 204146 204147 204148 204149 204150 204151 204152 204153 204154 204155 204156 204157 204158 204159 204160 204161 204162 204163 204164 204165 204166 204167 204168 204169 204170 204171 204172 204173 204174 204175 204176 204177 204178 204179 204180 204181 204182 204183 204184 204185 204186 204187 204188 204189 204190 204191 204192 204193 204194 204195 204196 204197 204198 204199 204200 204201 204202 204203 204204 204205 204206 204207 204208 204209 204210 204211 204212 204213 204214 204215 204216 204217 204218 204219 204220 204221 204222 204223 204224 204225 204226 204227 204228 204229 204230 204231 204232 204233 204234 204235 204236 204237 204238 204239 204240 204241 204242 204243 204244 204245 204246 204247 204248 204249 204250 204251 204252 204253 204254 204255 204256 204257 204258 204259 204260 204261 204262 204263 204264 204265 204266 204267 204268 204269 204270 204271 204272 204273 204274 204275 204276 204277 204278 204279 204280 204281 204282 204283 204284 204285 204286 204287 204288 204289 204290 204291 204292 204293 204294 204295 204296 204297 204298 204299 204300 204301 204302 204303 204304 204305 204306 204307 204308 204309 204310 204311 204312 204313 204314 204315 204316 204317 204318 204319 204320 204321 204322 204323 204324 204325 204326 204327 204328 204329 204330 204331 204332 204333 204334 204335 204336 204337 204338 204339 204340 204341 204342 204343 204344 204345 204346 204347 204348 204349 204350 204351 204352 204353 204354 204355 204356 204357 204358 204359 204360 204361 204362 204363 204364 204365 204366 204367 204368 204369 204370 204371 204372 204373 204374 204375 204376 204377 204378 204379 204380 204381 204382 204383 204384 204385 204386 204387 204388 204389 204390 204391 204392 204393 204394 204395 204396 204397 204398 204399 204400 204401 204402 204403 204404 204405 204406 204407 204408 204409 204410 204411 204412 204413 204414 204415 204416 204417 204418 204419 204420 204421 204422 204423 204424 204425 204426 204427 204428 204429 204430 204431 204432 204433 204434 204435 204436 204437 204438 204439 204440 204441 204442 204443 204444 204445 204446 204447 204448 204449 204450 204451 204452 204453 204454 204455 204456 204457 204458 204459 204460 204461 204462 204463 204464 204465 204466 204467 204468 204469 204470 204471 204472 204473 204474 204475 204476 204477 204478 204479 204480 204481 204482 204483 204484 204485 204486 204487 204488 204489 204490 204491 204492 204493 204494 204495 204496 204497 204498 204499 204500 204501 204502 204503 204504 204505 204506 204507 204508 204509 204510 204511 204512 204513 204514 204515 204516 204517 204518 204519 204520 204521 204522 204523 204524 204525 204526 204527 204528 204529 204530 204531 204532 204533 204534 204535 204536 204537 204538 204539 204540 204541 204542 204543 204544 204545 204546 204547 204548 204549 204550 204551 204552 204553 204554 204555 204556 204557 204558 204559 204560 204561 204562 204563 204564 204565 204566 204567 204568 204569 204570 204571 204572 204573 204574 204575 204576 204577 204578 204579 204580 204581 204582 204583 204584 204585 204586 204587 204588 204589 204590 204591 204592 204593 204594 204595 204596 204597 204598 204599 204600 204601 204602 204603 204604 204605 204606 204607 204608 204609 204610 204611 204612 204613 204614 204615 204616 204617 204618 204619 204620 204621 204622 204623 204624 204625 204626 204627 204628 204629 204630 204631 204632 204633 204634 204635 204636 204637 204638 204639 204640 204641 204642 204643 204644 204645 204646 204647 204648 204649 204650 204651 204652 204653 204654 204655 204656 204657 204658 204659 204660 204661 204662 204663 204664 204665 204666 204667 204668 204669 204670 204671 204672 204673 204674 204675 204676 204677 204678 204679 204680 204681 204682 204683 204684 204685 204686 204687 204688 204689 204690 204691 204692 204693 204694 204695 204696 204697 204698 204699 204700 204701 204702 204703 204704 204705 204706 204707 204708 204709 204710 204711 204712 204713 204714 204715 204716 204717 204718 204719 204720 204721 204722 204723 204724 204725 204726 204727 204728 204729 204730 204731 204732 204733 204734 204735 204736 204737 204738 204739 204740 204741 204742 204743 204744 204745 204746 204747 204748 204749 204750 204751 204752 204753 204754 204755 204756 204757 204758 204759 204760 204761 204762 204763 204764 204765 204766 204767 204768 204769 204770 204771 204772 204773 204774 204775 204776 204777 204778 204779 204780 204781 204782 204783 204784 204785 204786 204787 204788 204789 204790 204791 204792 204793 204794 204795 204796 204797 204798 204799 204800 204801 204802 204803 204804 204805 204806 204807 204808 204809 204810 204811 204812 204813 204814 204815 204816 204817 204818 204819 204820 204821 204822 204823 204824 204825 204826 204827 204828 204829 204830 204831 204832 204833 204834 204835 204836 204837 204838 204839 204840 204841 204842 204843 |
char c2;
char n;
char eType;
char nRepl;
char *zMatch;
char *zRepl;
} aNanInfName[] = {
{ 'i', 'I', 3, JSONB_FLOAT, 7, "inf", "9.0e999" },
{ 'i', 'I', 8, JSONB_FLOAT, 7, "infinity", "9.0e999" },
{ 'n', 'N', 3, JSONB_NULL, 4, "NaN", "null" },
{ 'q', 'Q', 4, JSONB_NULL, 4, "QNaN", "null" },
{ 's', 'S', 4, JSONB_NULL, 4, "SNaN", "null" },
};
/*
** Report the wrong number of arguments for json_insert(), json_replace()
** or json_set().
*/
static void jsonWrongNumArgs(
sqlite3_context *pCtx,
const char *zFuncName
){
char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
zFuncName);
sqlite3_result_error(pCtx, zMsg, -1);
sqlite3_free(zMsg);
}
/****************************************************************************
** Utility routines for dealing with the binary BLOB representation of JSON
****************************************************************************/
/*
** Expand pParse->aBlob so that it holds at least N bytes.
**
** Return the number of errors.
*/
static int jsonBlobExpand(JsonParse *pParse, u32 N){
u8 *aNew;
u32 t;
assert( N>pParse->nBlobAlloc );
if( pParse->nBlobAlloc==0 ){
t = 100;
}else{
t = pParse->nBlobAlloc*2;
}
if( t<N ) t = N+100;
aNew = sqlite3_realloc64( pParse->aBlob, t );
if( aNew==0 ){ pParse->oom = 1; return 1; }
pParse->aBlob = aNew;
pParse->nBlobAlloc = t;
return 0;
}
/*
** If pParse->aBlob is not previously editable (because it is taken
** from sqlite3_value_blob(), as indicated by the fact that
** pParse->nBlobAlloc==0 and pParse->nBlob>0) then make it editable
** by making a copy into space obtained from malloc.
**
** Return true on success. Return false on OOM.
*/
static int jsonBlobMakeEditable(JsonParse *pParse, u32 nExtra){
u8 *aOld;
u32 nSize;
assert( !pParse->bReadOnly );
if( pParse->oom ) return 0;
if( pParse->nBlobAlloc>0 ) return 1;
aOld = pParse->aBlob;
nSize = pParse->nBlob + nExtra;
pParse->aBlob = 0;
if( jsonBlobExpand(pParse, nSize) ){
return 0;
}
assert( pParse->nBlobAlloc >= pParse->nBlob + nExtra );
memcpy(pParse->aBlob, aOld, pParse->nBlob);
return 1;
}
/* Expand pParse->aBlob and append one bytes.
*/
static SQLITE_NOINLINE void jsonBlobExpandAndAppendOneByte(
JsonParse *pParse,
u8 c
){
jsonBlobExpand(pParse, pParse->nBlob+1);
if( pParse->oom==0 ){
assert( pParse->nBlob+1<=pParse->nBlobAlloc );
pParse->aBlob[pParse->nBlob++] = c;
}
}
/* Append a single character.
*/
static void jsonBlobAppendOneByte(JsonParse *pParse, u8 c){
if( pParse->nBlob >= pParse->nBlobAlloc ){
jsonBlobExpandAndAppendOneByte(pParse, c);
}else{
pParse->aBlob[pParse->nBlob++] = c;
}
}
/* Slow version of jsonBlobAppendNode() that first resizes the
** pParse->aBlob structure.
*/
static void jsonBlobAppendNode(JsonParse*,u8,u32,const void*);
static SQLITE_NOINLINE void jsonBlobExpandAndAppendNode(
JsonParse *pParse,
u8 eType,
u32 szPayload,
const void *aPayload
){
if( jsonBlobExpand(pParse, pParse->nBlob+szPayload+9) ) return;
jsonBlobAppendNode(pParse, eType, szPayload, aPayload);
}
/* Append an node type byte together with the payload size and
** possibly also the payload.
**
** If aPayload is not NULL, then it is a pointer to the payload which
** is also appended. If aPayload is NULL, the pParse->aBlob[] array
** is resized (if necessary) so that it is big enough to hold the
** payload, but the payload is not appended and pParse->nBlob is left
** pointing to where the first byte of payload will eventually be.
*/
static void jsonBlobAppendNode(
JsonParse *pParse, /* The JsonParse object under construction */
u8 eType, /* Node type. One of JSONB_* */
u32 szPayload, /* Number of bytes of payload */
const void *aPayload /* The payload. Might be NULL */
){
u8 *a;
if( pParse->nBlob+szPayload+9 > pParse->nBlobAlloc ){
jsonBlobExpandAndAppendNode(pParse,eType,szPayload,aPayload);
return;
}
assert( pParse->aBlob!=0 );
a = &pParse->aBlob[pParse->nBlob];
if( szPayload<=11 ){
a[0] = eType | (szPayload<<4);
pParse->nBlob += 1;
}else if( szPayload<=0xff ){
a[0] = eType | 0xc0;
a[1] = szPayload & 0xff;
pParse->nBlob += 2;
}else if( szPayload<=0xffff ){
a[0] = eType | 0xd0;
a[1] = (szPayload >> 8) & 0xff;
a[2] = szPayload & 0xff;
pParse->nBlob += 3;
}else{
a[0] = eType | 0xe0;
a[1] = (szPayload >> 24) & 0xff;
a[2] = (szPayload >> 16) & 0xff;
a[3] = (szPayload >> 8) & 0xff;
a[4] = szPayload & 0xff;
pParse->nBlob += 5;
}
if( aPayload ){
pParse->nBlob += szPayload;
memcpy(&pParse->aBlob[pParse->nBlob-szPayload], aPayload, szPayload);
}
}
/* Change the payload size for the node at index i to be szPayload.
*/
static int jsonBlobChangePayloadSize(
JsonParse *pParse,
u32 i,
u32 szPayload
){
u8 *a;
u8 szType;
u8 nExtra;
u8 nNeeded;
int delta;
if( pParse->oom ) return 0;
a = &pParse->aBlob[i];
szType = a[0]>>4;
if( szType<=11 ){
nExtra = 0;
}else if( szType==12 ){
nExtra = 1;
}else if( szType==13 ){
nExtra = 2;
}else{
nExtra = 4;
}
if( szPayload<=11 ){
nNeeded = 0;
}else if( szPayload<=0xff ){
nNeeded = 1;
}else if( szPayload<=0xffff ){
nNeeded = 2;
}else{
nNeeded = 4;
}
delta = nNeeded - nExtra;
if( delta ){
u32 newSize = pParse->nBlob + delta;
if( delta>0 ){
if( newSize>pParse->nBlobAlloc && jsonBlobExpand(pParse, newSize) ){
return 0; /* OOM error. Error state recorded in pParse->oom. */
}
a = &pParse->aBlob[i];
memmove(&a[1+delta], &a[1], pParse->nBlob - (i+1));
}else{
memmove(&a[1], &a[1-delta], pParse->nBlob - (i+1-delta));
}
pParse->nBlob = newSize;
}
if( nNeeded==0 ){
a[0] = (a[0] & 0x0f) | (szPayload<<4);
}else if( nNeeded==1 ){
a[0] = (a[0] & 0x0f) | 0xc0;
a[1] = szPayload & 0xff;
}else if( nNeeded==2 ){
a[0] = (a[0] & 0x0f) | 0xd0;
a[1] = (szPayload >> 8) & 0xff;
a[2] = szPayload & 0xff;
}else{
a[0] = (a[0] & 0x0f) | 0xe0;
a[1] = (szPayload >> 24) & 0xff;
a[2] = (szPayload >> 16) & 0xff;
a[3] = (szPayload >> 8) & 0xff;
a[4] = szPayload & 0xff;
}
return delta;
}
/*
** If z[0] is 'u' and is followed by exactly 4 hexadecimal character,
** then set *pOp to JSONB_TEXTJ and return true. If not, do not make
** any changes to *pOp and return false.
*/
static int jsonIs4HexB(const char *z, int *pOp){
if( z[0]!='u' ) return 0;
if( !sqlite3Isxdigit(z[1]) ) return 0;
if( !sqlite3Isxdigit(z[2]) ) return 0;
if( !sqlite3Isxdigit(z[3]) ) return 0;
if( !sqlite3Isxdigit(z[4]) ) return 0;
*pOp = JSONB_TEXTJ;
return 1;
}
/*
** Check a single element of the JSONB in pParse for validity.
**
** The element to be checked starts at offset i and must end at on the
** last byte before iEnd.
**
** Return 0 if everything is correct. Return the 1-based byte offset of the
** error if a problem is detected. (In other words, if the error is at offset
** 0, return 1).
*/
static u32 jsonbValidityCheck(
const JsonParse *pParse, /* Input JSONB. Only aBlob and nBlob are used */
u32 i, /* Start of element as pParse->aBlob[i] */
u32 iEnd, /* One more than the last byte of the element */
u32 iDepth /* Current nesting depth */
){
u32 n, sz, j, k;
const u8 *z;
u8 x;
if( iDepth>JSON_MAX_DEPTH ) return i+1;
sz = 0;
n = jsonbPayloadSize(pParse, i, &sz);
if( NEVER(n==0) ) return i+1; /* Checked by caller */
if( NEVER(i+n+sz!=iEnd) ) return i+1; /* Checked by caller */
z = pParse->aBlob;
x = z[i] & 0x0f;
switch( x ){
case JSONB_NULL:
case JSONB_TRUE:
case JSONB_FALSE: {
return n+sz==1 ? 0 : i+1;
}
case JSONB_INT: {
if( sz<1 ) return i+1;
j = i+n;
if( z[j]=='-' ){
j++;
if( sz<2 ) return i+1;
}
k = i+n+sz;
while( j<k ){
if( sqlite3Isdigit(z[j]) ){
j++;
}else{
return j+1;
}
}
return 0;
}
case JSONB_INT5: {
if( sz<3 ) return i+1;
j = i+n;
if( z[j]=='-' ){
if( sz<4 ) return i+1;
j++;
}
if( z[j]!='0' ) return i+1;
if( z[j+1]!='x' && z[j+1]!='X' ) return j+2;
j += 2;
k = i+n+sz;
while( j<k ){
if( sqlite3Isxdigit(z[j]) ){
j++;
}else{
return j+1;
}
}
return 0;
}
case JSONB_FLOAT:
case JSONB_FLOAT5: {
u8 seen = 0; /* 0: initial. 1: '.' seen 2: 'e' seen */
if( sz<2 ) return i+1;
j = i+n;
k = j+sz;
if( z[j]=='-' ){
j++;
if( sz<3 ) return i+1;
}
if( z[j]=='.' ){
if( x==JSONB_FLOAT ) return j+1;
if( !sqlite3Isdigit(z[j+1]) ) return j+1;
j += 2;
seen = 1;
}else if( z[j]=='0' && x==JSONB_FLOAT ){
if( j+3>k ) return j+1;
if( z[j+1]!='.' && z[j+1]!='e' && z[j+1]!='E' ) return j+1;
j++;
}
for(; j<k; j++){
if( sqlite3Isdigit(z[j]) ) continue;
if( z[j]=='.' ){
if( seen>0 ) return j+1;
if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){
return j+1;
}
seen = 1;
continue;
}
if( z[j]=='e' || z[j]=='E' ){
if( seen==2 ) return j+1;
if( j==k-1 ) return j+1;
if( z[j+1]=='+' || z[j+1]=='-' ){
j++;
if( j==k-1 ) return j+1;
}
seen = 2;
continue;
}
return j+1;
}
if( seen==0 ) return i+1;
return 0;
}
case JSONB_TEXT: {
j = i+n;
k = j+sz;
while( j<k ){
if( !jsonIsOk[z[j]] && z[j]!='\'' ) return j+1;
j++;
}
return 0;
}
case JSONB_TEXTJ:
case JSONB_TEXT5: {
j = i+n;
k = j+sz;
while( j<k ){
if( !jsonIsOk[z[j]] && z[j]!='\'' ){
if( z[j]=='"' ){
if( x==JSONB_TEXTJ ) return j+1;
}else if( z[j]!='\\' || j+1>=k ){
return j+1;
}else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){
j++;
}else if( z[j+1]=='u' ){
if( j+5>=k ) return j+1;
if( !jsonIs4Hex((const char*)&z[j+2]) ) return j+1;
j++;
}else if( x!=JSONB_TEXT5 ){
return j+1;
}else{
u32 c = 0;
u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c);
if( c==0xfffd ) return j+1;
j += szC - 1;
}
}
j++;
}
return 0;
}
case JSONB_TEXTRAW: {
return 0;
}
case JSONB_ARRAY: {
u32 sub;
j = i+n;
k = j+sz;
while( j<k ){
sz = 0;
n = jsonbPayloadSize(pParse, j, &sz);
if( n==0 ) return j+1;
if( j+n+sz>k ) return j+1;
sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1);
if( sub ) return sub;
j += n + sz;
}
assert( j==k );
return 0;
}
case JSONB_OBJECT: {
u32 cnt = 0;
u32 sub;
j = i+n;
k = j+sz;
while( j<k ){
sz = 0;
n = jsonbPayloadSize(pParse, j, &sz);
if( n==0 ) return j+1;
if( j+n+sz>k ) return j+1;
if( (cnt & 1)==0 ){
x = z[j] & 0x0f;
if( x<JSONB_TEXT || x>JSONB_TEXTRAW ) return j+1;
}
sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1);
if( sub ) return sub;
cnt++;
j += n + sz;
}
assert( j==k );
if( (cnt & 1)!=0 ) return j+1;
return 0;
}
default: {
return i+1;
}
}
}
/*
** Translate a single element of JSON text at pParse->zJson[i] into
** its equivalent binary JSONB representation. Append the translation into
** pParse->aBlob[] beginning at pParse->nBlob. The size of
** pParse->aBlob[] is increased as necessary.
**
** Return the index of the first character past the end of the element parsed,
** or one of the following special result codes:
**
** 0 End of input
** -1 Syntax error or OOM
** -2 '}' seen \
** -3 ']' seen \___ For these returns, pParse->iErr is set to
** -4 ',' seen / the index in zJson[] of the seen character
** -5 ':' seen /
*/
static int jsonXlateTextToBlob(JsonParse *pParse, u32 i){
char c;
u32 j;
u32 iThis, iStart;
int x;
u8 t;
const char *z = pParse->zJson;
json_parse_restart:
switch( (u8)z[i] ){
case '{': {
/* Parse object */
iThis = pParse->nBlob;
jsonBlobAppendNode(pParse, JSONB_OBJECT, pParse->nJson-i, 0);
if( ++pParse->iDepth > JSON_MAX_DEPTH ){
pParse->iErr = i;
return -1;
}
iStart = pParse->nBlob;
for(j=i+1;;j++){
u32 iBlob = pParse->nBlob;
x = jsonXlateTextToBlob(pParse, j);
if( x<=0 ){
int op;
if( x==(-2) ){
j = pParse->iErr;
if( pParse->nBlob!=(u32)iStart ) pParse->hasNonstd = 1;
break;
}
j += json5Whitespace(&z[j]);
op = JSONB_TEXT;
if( sqlite3JsonId1(z[j])
|| (z[j]=='\\' && jsonIs4HexB(&z[j+1], &op))
){
int k = j+1;
while( (sqlite3JsonId2(z[k]) && json5Whitespace(&z[k])==0)
|| (z[k]=='\\' && jsonIs4HexB(&z[k+1], &op))
){
k++;
}
assert( iBlob==pParse->nBlob );
jsonBlobAppendNode(pParse, op, k-j, &z[j]);
pParse->hasNonstd = 1;
x = k;
}else{
if( x!=-1 ) pParse->iErr = j;
return -1;
}
}
if( pParse->oom ) return -1;
t = pParse->aBlob[iBlob] & 0x0f;
if( t<JSONB_TEXT || t>JSONB_TEXTRAW ){
pParse->iErr = j;
return -1;
}
j = x;
if( z[j]==':' ){
j++;
}else{
if( jsonIsspace(z[j]) ){
/* strspn() is not helpful here */
do{ j++; }while( jsonIsspace(z[j]) );
if( z[j]==':' ){
j++;
goto parse_object_value;
}
}
x = jsonXlateTextToBlob(pParse, j);
if( x!=(-5) ){
if( x!=(-1) ) pParse->iErr = j;
return -1;
}
j = pParse->iErr+1;
}
parse_object_value:
x = jsonXlateTextToBlob(pParse, j);
if( x<=0 ){
if( x!=(-1) ) pParse->iErr = j;
return -1;
}
j = x;
if( z[j]==',' ){
continue;
}else if( z[j]=='}' ){
break;
}else{
if( jsonIsspace(z[j]) ){
j += 1 + (u32)strspn(&z[j+1], jsonSpaces);
if( z[j]==',' ){
continue;
}else if( z[j]=='}' ){
break;
}
}
x = jsonXlateTextToBlob(pParse, j);
if( x==(-4) ){
j = pParse->iErr;
continue;
}
if( x==(-2) ){
j = pParse->iErr;
break;
}
}
pParse->iErr = j;
return -1;
}
jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart);
pParse->iDepth--;
return j+1;
}
case '[': {
/* Parse array */
iThis = pParse->nBlob;
jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0);
iStart = pParse->nBlob;
if( pParse->oom ) return -1;
if( ++pParse->iDepth > JSON_MAX_DEPTH ){
pParse->iErr = i;
return -1;
}
for(j=i+1;;j++){
x = jsonXlateTextToBlob(pParse, j);
if( x<=0 ){
if( x==(-3) ){
j = pParse->iErr;
if( pParse->nBlob!=iStart ) pParse->hasNonstd = 1;
break;
}
if( x!=(-1) ) pParse->iErr = j;
return -1;
}
j = x;
if( z[j]==',' ){
continue;
}else if( z[j]==']' ){
break;
}else{
if( jsonIsspace(z[j]) ){
j += 1 + (u32)strspn(&z[j+1], jsonSpaces);
if( z[j]==',' ){
continue;
}else if( z[j]==']' ){
break;
}
}
x = jsonXlateTextToBlob(pParse, j);
if( x==(-4) ){
j = pParse->iErr;
continue;
}
if( x==(-3) ){
j = pParse->iErr;
break;
}
}
pParse->iErr = j;
return -1;
}
jsonBlobChangePayloadSize(pParse, iThis, pParse->nBlob - iStart);
pParse->iDepth--;
return j+1;
}
case '\'': {
u8 opcode;
char cDelim;
pParse->hasNonstd = 1;
opcode = JSONB_TEXT;
goto parse_string;
case '"':
/* Parse string */
opcode = JSONB_TEXT;
parse_string:
cDelim = z[i];
j = i+1;
while( 1 /*exit-by-break*/ ){
if( jsonIsOk[(u8)z[j]] ){
if( !jsonIsOk[(u8)z[j+1]] ){
j += 1;
}else if( !jsonIsOk[(u8)z[j+2]] ){
j += 2;
}else{
j += 3;
continue;
}
}
c = z[j];
if( c==cDelim ){
break;
}else if( c=='\\' ){
c = z[++j];
if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
|| c=='n' || c=='r' || c=='t'
|| (c=='u' && jsonIs4Hex(&z[j+1])) ){
if( opcode==JSONB_TEXT ) opcode = JSONB_TEXTJ;
}else if( c=='\'' || c=='0' || c=='v' || c=='\n'
|| (0xe2==(u8)c && 0x80==(u8)z[j+1]
&& (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
|| (c=='x' && jsonIs2Hex(&z[j+1])) ){
opcode = JSONB_TEXT5;
pParse->hasNonstd = 1;
}else if( c=='\r' ){
if( z[j+1]=='\n' ) j++;
opcode = JSONB_TEXT5;
pParse->hasNonstd = 1;
}else{
pParse->iErr = j;
return -1;
}
}else if( c<=0x1f ){
/* Control characters are not allowed in strings */
pParse->iErr = j;
return -1;
}else if( c=='"' ){
opcode = JSONB_TEXT5;
}
j++;
}
jsonBlobAppendNode(pParse, opcode, j-1-i, &z[i+1]);
return j+1;
}
case 't': {
if( strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){
jsonBlobAppendOneByte(pParse, JSONB_TRUE);
return i+4;
}
pParse->iErr = i;
return -1;
}
case 'f': {
if( strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){
jsonBlobAppendOneByte(pParse, JSONB_FALSE);
return i+5;
}
pParse->iErr = i;
return -1;
}
case '+': {
u8 seenE;
pParse->hasNonstd = 1;
t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
goto parse_number;
case '.':
if( sqlite3Isdigit(z[i+1]) ){
pParse->hasNonstd = 1;
t = 0x03; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
seenE = 0;
goto parse_number_2;
}
pParse->iErr = i;
return -1;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* Parse number */
t = 0x00; /* Bit 0x01: JSON5. Bit 0x02: FLOAT */
parse_number:
seenE = 0;
assert( '-' < '0' );
assert( '+' < '0' );
assert( '.' < '0' );
c = z[i];
if( c<='0' ){
if( c=='0' ){
if( (z[i+1]=='x' || z[i+1]=='X') && sqlite3Isxdigit(z[i+2]) ){
assert( t==0x00 );
pParse->hasNonstd = 1;
t = 0x01;
for(j=i+3; sqlite3Isxdigit(z[j]); j++){}
goto parse_number_finish;
}else if( sqlite3Isdigit(z[i+1]) ){
pParse->iErr = i+1;
return -1;
}
}else{
if( !sqlite3Isdigit(z[i+1]) ){
/* JSON5 allows for "+Infinity" and "-Infinity" using exactly
** that case. SQLite also allows these in any case and it allows
** "+inf" and "-inf". */
if( (z[i+1]=='I' || z[i+1]=='i')
&& sqlite3StrNICmp(&z[i+1], "inf",3)==0
){
pParse->hasNonstd = 1;
if( z[i]=='-' ){
jsonBlobAppendNode(pParse, JSONB_FLOAT, 6, "-9e999");
}else{
jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999");
}
return i + (sqlite3StrNICmp(&z[i+4],"inity",5)==0 ? 9 : 4);
}
if( z[i+1]=='.' ){
pParse->hasNonstd = 1;
t |= 0x01;
goto parse_number_2;
}
pParse->iErr = i;
return -1;
}
if( z[i+1]=='0' ){
if( sqlite3Isdigit(z[i+2]) ){
pParse->iErr = i+1;
return -1;
}else if( (z[i+2]=='x' || z[i+2]=='X') && sqlite3Isxdigit(z[i+3]) ){
pParse->hasNonstd = 1;
t |= 0x01;
for(j=i+4; sqlite3Isxdigit(z[j]); j++){}
goto parse_number_finish;
}
}
}
}
parse_number_2:
for(j=i+1;; j++){
c = z[j];
if( sqlite3Isdigit(c) ) continue;
if( c=='.' ){
if( (t & 0x02)!=0 ){
pParse->iErr = j;
return -1;
}
t |= 0x02;
continue;
}
if( c=='e' || c=='E' ){
if( z[j-1]<'0' ){
if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){
pParse->hasNonstd = 1;
t |= 0x01;
}else{
pParse->iErr = j;
return -1;
}
}
if( seenE ){
pParse->iErr = j;
return -1;
}
t |= 0x02;
seenE = 1;
c = z[j+1];
if( c=='+' || c=='-' ){
j++;
c = z[j+1];
}
if( c<'0' || c>'9' ){
pParse->iErr = j;
return -1;
}
continue;
}
break;
}
if( z[j-1]<'0' ){
if( ALWAYS(z[j-1]=='.') && ALWAYS(j-2>=i) && sqlite3Isdigit(z[j-2]) ){
pParse->hasNonstd = 1;
t |= 0x01;
}else{
pParse->iErr = j;
return -1;
}
}
parse_number_finish:
assert( JSONB_INT+0x01==JSONB_INT5 );
assert( JSONB_FLOAT+0x01==JSONB_FLOAT5 );
assert( JSONB_INT+0x02==JSONB_FLOAT );
if( z[i]=='+' ) i++;
jsonBlobAppendNode(pParse, JSONB_INT+t, j-i, &z[i]);
return j;
}
case '}': {
pParse->iErr = i;
return -2; /* End of {...} */
}
case ']': {
|
| ︙ | ︙ | |||
204355 204356 204357 204358 204359 204360 204361 |
case 0: {
return 0; /* End of file */
}
case 0x09:
case 0x0a:
case 0x0d:
case 0x20: {
| | < < | 204855 204856 204857 204858 204859 204860 204861 204862 204863 204864 204865 204866 204867 204868 204869 |
case 0: {
return 0; /* End of file */
}
case 0x09:
case 0x0a:
case 0x0d:
case 0x20: {
i += 1 + (u32)strspn(&z[i+1], jsonSpaces);
goto json_parse_restart;
}
case 0x0b:
case 0x0c:
case '/':
case 0xc2:
case 0xe1:
|
| ︙ | ︙ | |||
204379 204380 204381 204382 204383 204384 204385 |
goto json_parse_restart;
}
pParse->iErr = i;
return -1;
}
case 'n': {
if( strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){
| | | | > > > > | | > > > > > | > > > > > > > > > > > > > > > > > > > > | > | < > > > > | < > | > > > > > | | > > | < | > > | > > > > > | > > | | > > > > > > > > | | > > > > > | < > > > | > > > | > > > | | | | > | > > > | > > > | > > > | > > > | | | | > | > > > > | | > | | | > > > > > > > > > > > > > > > > > > > | < > | < > > > > > > > > > > > | < > > > > > | < < < < < < < > > > > > | < < > > > | < < > | > > > | < | < > | < | > | | | < > | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < | > > > > > > > > > > > > > > > | > > > > > | < > | | > | > | > > > > > | < | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > | < < | < > | | | < < < < < < > | | < < < > | | < | | | < > | < | > > > > > > > > > > > | | > > > > > | | > > > > > > > > > > > > > > > > > > > > > | < | | < < | | > > > > > | < < < < < | < < > | > > > > > > > > > > > | > > | | > > > > | | | > | | < | > > > | | < | < | < < < < < | > > | < | | < < < | | > | > > > > > > | < > | > > > | | > | | > | | | > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > | | < | > | < < | | | > | | < > | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > | > > | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > > > > > > > > | | | | < > > > > > > | > > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > > > > > > > | > > | < | > < | > > > | < | | > | < < > | < | > > | > > > > > > | < > | | | | < < | | | | > > | > > > > > > > | > > > | > > > | | > > | < > | | > | > > > | > > > | | | | | | > | > > > > > > > > > > > > > > > > > | > > > > > | < > | | > | | | > | > > > > > > > | < > > | > | | > > > > > > > > > > > > > | > > > | > > | | > > > > | | > > > > > > > > > > > > > > > > > | > > | | < | > > | < > | | | < > > | | > > > > | > > > | > > > > > > > | < > > > > | < | > | | > > > > > | < > > > > > | < < > | > | > > > > < < > > > > > < > > > | > | > | | > > > > > | | > > > | > > > > > > > > | | > > > > > > > > > | | | > > | > > > > > > > > > > > > > > | | > > | < | > > | > > > > > > | > > > > > > | < | > > | > > | < > | > > > > > > > > > > > > > > > > > > > | | > > > | | > > | | | < > | > > > > > > > > | | > > > > > > < < > > | | | | | > > > | > > > > > > | > | | < > > > | < < < < < > > | < < < | > > > > > | > | | > > > > > > > | > > > > | > > > > > | > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > < < | > > > > | | < > > | < < | > > > > > > > > > > > > > > | | > > > > > > | > > | < < > | < > | < < > > > | < | < > > > > | | > > > > > > > > > > > | < < < > | | | > > > | > > > > > | < > | > | | < < > > | | > > > > > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > | > > | > > > > > > > > > | > > | > > | | | > | | | | < < < < < < < < < | > > | > > > > > > > > | < | | | | > > > | > > > > > | > > > > | < | > > > > > > > > > > | < | < | < < | > > > > > > > | < > | > > > > | > | | | < | < < < < < < < < < < < < < < < < | < < < < < | < < < < < < | | | | | | | < | | | < | | | | > | > > > > | > | < < | < < | | < < | | | > > | > | < | < < | | > > | > > > > > > | 204877 204878 204879 204880 204881 204882 204883 204884 204885 204886 204887 204888 204889 204890 204891 204892 204893 204894 204895 204896 204897 204898 204899 204900 204901 204902 204903 204904 204905 204906 204907 204908 204909 204910 204911 204912 204913 204914 204915 204916 204917 204918 204919 204920 204921 204922 204923 204924 204925 204926 204927 204928 204929 204930 204931 204932 204933 204934 204935 204936 204937 204938 204939 204940 204941 204942 204943 204944 204945 204946 204947 204948 204949 204950 204951 204952 204953 204954 204955 204956 204957 204958 204959 204960 204961 204962 204963 204964 204965 204966 204967 204968 204969 204970 204971 204972 204973 204974 204975 204976 204977 204978 204979 204980 204981 204982 204983 204984 204985 204986 204987 204988 204989 204990 204991 204992 204993 204994 204995 204996 204997 204998 204999 205000 205001 205002 205003 205004 205005 205006 205007 205008 205009 205010 205011 205012 205013 205014 205015 205016 205017 205018 205019 205020 205021 205022 205023 205024 205025 205026 205027 205028 205029 205030 205031 205032 205033 205034 205035 205036 205037 205038 205039 205040 205041 205042 205043 205044 205045 205046 205047 205048 205049 205050 205051 205052 205053 205054 205055 205056 205057 205058 205059 205060 205061 205062 205063 205064 205065 205066 205067 205068 205069 205070 205071 205072 205073 205074 205075 205076 205077 205078 205079 205080 205081 205082 205083 205084 205085 205086 205087 205088 205089 205090 205091 205092 205093 205094 205095 205096 205097 205098 205099 205100 205101 205102 205103 205104 205105 205106 205107 205108 205109 205110 205111 205112 205113 205114 205115 205116 205117 205118 205119 205120 205121 205122 205123 205124 205125 205126 205127 205128 205129 205130 205131 205132 205133 205134 205135 205136 205137 205138 205139 205140 205141 205142 205143 205144 205145 205146 205147 205148 205149 205150 205151 205152 205153 205154 205155 205156 205157 205158 205159 205160 205161 205162 205163 205164 205165 205166 205167 205168 205169 205170 205171 205172 205173 205174 205175 205176 205177 205178 205179 205180 205181 205182 205183 205184 205185 205186 205187 205188 205189 205190 205191 205192 205193 205194 205195 205196 205197 205198 205199 205200 205201 205202 205203 205204 205205 205206 205207 205208 205209 205210 205211 205212 205213 205214 205215 205216 205217 205218 205219 205220 205221 205222 205223 205224 205225 205226 205227 205228 205229 205230 205231 205232 205233 205234 205235 205236 205237 205238 205239 205240 205241 205242 205243 205244 205245 205246 205247 205248 205249 205250 205251 205252 205253 205254 205255 205256 205257 205258 205259 205260 205261 205262 205263 205264 205265 205266 205267 205268 205269 205270 205271 205272 205273 205274 205275 205276 205277 205278 205279 205280 205281 205282 205283 205284 205285 205286 205287 205288 205289 205290 205291 205292 205293 205294 205295 205296 205297 205298 205299 205300 205301 205302 205303 205304 205305 205306 205307 205308 205309 205310 205311 205312 205313 205314 205315 205316 205317 205318 205319 205320 205321 205322 205323 205324 205325 205326 205327 205328 205329 205330 205331 205332 205333 205334 205335 205336 205337 205338 205339 205340 205341 205342 205343 205344 205345 205346 205347 205348 205349 205350 205351 205352 205353 205354 205355 205356 205357 205358 205359 205360 205361 205362 205363 205364 205365 205366 205367 205368 205369 205370 205371 205372 205373 205374 205375 205376 205377 205378 205379 205380 205381 205382 205383 205384 205385 205386 205387 205388 205389 205390 205391 205392 205393 205394 205395 205396 205397 205398 205399 205400 205401 205402 205403 205404 205405 205406 205407 205408 205409 205410 205411 205412 205413 205414 205415 205416 205417 205418 205419 205420 205421 205422 205423 205424 205425 205426 205427 205428 205429 205430 205431 205432 205433 205434 205435 205436 205437 205438 205439 205440 205441 205442 205443 205444 205445 205446 205447 205448 205449 205450 205451 205452 205453 205454 205455 205456 205457 205458 205459 205460 205461 205462 205463 205464 205465 205466 205467 205468 205469 205470 205471 205472 205473 205474 205475 205476 205477 205478 205479 205480 205481 205482 205483 205484 205485 205486 205487 205488 205489 205490 205491 205492 205493 205494 205495 205496 205497 205498 205499 205500 205501 205502 205503 205504 205505 205506 205507 205508 205509 205510 205511 205512 205513 205514 205515 205516 205517 205518 205519 205520 205521 205522 205523 205524 205525 205526 205527 205528 205529 205530 205531 205532 205533 205534 205535 205536 205537 205538 205539 205540 205541 205542 205543 205544 205545 205546 205547 205548 205549 205550 205551 205552 205553 205554 205555 205556 205557 205558 205559 205560 205561 205562 205563 205564 205565 205566 205567 205568 205569 205570 205571 205572 205573 205574 205575 205576 205577 205578 205579 205580 205581 205582 205583 205584 205585 205586 205587 205588 205589 205590 205591 205592 205593 205594 205595 205596 205597 205598 205599 205600 205601 205602 205603 205604 205605 205606 205607 205608 205609 205610 205611 205612 205613 205614 205615 205616 205617 205618 205619 205620 205621 205622 205623 205624 205625 205626 205627 205628 205629 205630 205631 205632 205633 205634 205635 205636 205637 205638 205639 205640 205641 205642 205643 205644 205645 205646 205647 205648 205649 205650 205651 205652 205653 205654 205655 205656 205657 205658 205659 205660 205661 205662 205663 205664 205665 205666 205667 205668 205669 205670 205671 205672 205673 205674 205675 205676 205677 205678 205679 205680 205681 205682 205683 205684 205685 205686 205687 205688 205689 205690 205691 205692 205693 205694 205695 205696 205697 205698 205699 205700 205701 205702 205703 205704 205705 205706 205707 205708 205709 205710 205711 205712 205713 205714 205715 205716 205717 205718 205719 205720 205721 205722 205723 205724 205725 205726 205727 205728 205729 205730 205731 205732 205733 205734 205735 205736 205737 205738 205739 205740 205741 205742 205743 205744 205745 205746 205747 205748 205749 205750 205751 205752 205753 205754 205755 205756 205757 205758 205759 205760 205761 205762 205763 205764 205765 205766 205767 205768 205769 205770 205771 205772 205773 205774 205775 205776 205777 205778 205779 205780 205781 205782 205783 205784 205785 205786 205787 205788 205789 205790 205791 205792 205793 205794 205795 205796 205797 205798 205799 205800 205801 205802 205803 205804 205805 205806 205807 205808 205809 205810 205811 205812 205813 205814 205815 205816 205817 205818 205819 205820 205821 205822 205823 205824 205825 205826 205827 205828 205829 205830 205831 205832 205833 205834 205835 205836 205837 205838 205839 205840 205841 205842 205843 205844 205845 205846 205847 205848 205849 205850 205851 205852 205853 205854 205855 205856 205857 205858 205859 205860 205861 205862 205863 205864 205865 205866 205867 205868 205869 205870 205871 205872 205873 205874 205875 205876 205877 205878 205879 205880 205881 205882 205883 205884 205885 205886 205887 205888 205889 205890 205891 205892 205893 205894 205895 205896 205897 205898 205899 205900 205901 205902 205903 205904 205905 205906 205907 205908 205909 205910 205911 205912 205913 205914 205915 205916 205917 205918 205919 205920 205921 205922 205923 205924 205925 205926 205927 205928 205929 205930 205931 205932 205933 205934 205935 205936 205937 205938 205939 205940 205941 205942 205943 205944 205945 205946 205947 205948 205949 205950 205951 205952 205953 205954 205955 205956 205957 205958 205959 205960 205961 205962 205963 205964 205965 205966 205967 205968 205969 205970 205971 205972 205973 205974 205975 205976 205977 205978 205979 205980 205981 205982 205983 205984 205985 205986 205987 205988 205989 205990 205991 205992 205993 205994 205995 205996 205997 205998 205999 206000 206001 206002 206003 206004 206005 206006 206007 206008 206009 206010 206011 206012 206013 206014 206015 206016 206017 206018 206019 206020 206021 206022 206023 206024 206025 206026 206027 206028 206029 206030 206031 206032 206033 206034 206035 206036 206037 206038 206039 206040 206041 206042 206043 206044 206045 206046 206047 206048 206049 206050 206051 206052 206053 206054 206055 206056 206057 206058 206059 206060 206061 206062 206063 206064 206065 206066 206067 206068 206069 206070 206071 206072 206073 206074 206075 206076 206077 206078 206079 206080 206081 206082 206083 206084 206085 206086 206087 206088 206089 206090 206091 206092 206093 206094 206095 206096 206097 206098 206099 206100 206101 206102 206103 206104 206105 206106 206107 206108 206109 206110 206111 206112 206113 206114 206115 206116 206117 206118 206119 206120 206121 206122 206123 206124 206125 206126 206127 206128 206129 206130 206131 206132 206133 206134 206135 206136 206137 206138 206139 206140 206141 206142 206143 206144 206145 206146 206147 206148 206149 206150 206151 206152 206153 206154 206155 206156 206157 206158 206159 206160 206161 206162 206163 206164 206165 206166 206167 206168 206169 206170 206171 206172 206173 206174 206175 206176 206177 206178 206179 206180 206181 206182 206183 206184 206185 206186 206187 206188 206189 206190 206191 206192 206193 206194 206195 206196 206197 206198 206199 206200 206201 206202 206203 206204 206205 206206 206207 206208 206209 206210 206211 206212 206213 206214 206215 206216 206217 206218 206219 206220 206221 206222 206223 206224 206225 206226 206227 206228 206229 206230 206231 206232 206233 206234 206235 206236 206237 206238 206239 206240 206241 206242 206243 206244 206245 206246 206247 206248 206249 206250 206251 206252 206253 206254 206255 206256 206257 206258 206259 206260 206261 206262 206263 206264 206265 206266 206267 206268 206269 206270 206271 206272 206273 206274 206275 206276 206277 206278 206279 206280 206281 206282 206283 206284 206285 206286 206287 206288 206289 206290 206291 206292 206293 206294 206295 206296 206297 206298 206299 206300 206301 206302 206303 206304 206305 206306 206307 206308 206309 206310 206311 206312 206313 206314 206315 206316 206317 206318 206319 206320 206321 206322 206323 206324 206325 206326 206327 206328 206329 206330 206331 206332 206333 206334 206335 206336 206337 206338 206339 206340 206341 206342 206343 206344 206345 206346 206347 206348 206349 206350 206351 206352 206353 206354 206355 206356 206357 206358 206359 206360 206361 206362 206363 206364 206365 206366 206367 206368 206369 206370 206371 206372 206373 206374 206375 206376 206377 206378 206379 206380 206381 206382 206383 206384 206385 206386 206387 206388 206389 206390 206391 206392 206393 206394 206395 206396 206397 206398 206399 206400 206401 206402 206403 206404 206405 206406 206407 206408 206409 206410 206411 206412 206413 206414 206415 206416 206417 206418 206419 206420 206421 206422 206423 206424 206425 206426 206427 206428 206429 206430 206431 206432 206433 206434 206435 206436 206437 206438 206439 206440 206441 206442 206443 206444 206445 206446 206447 206448 206449 206450 206451 206452 206453 206454 206455 206456 206457 206458 206459 206460 206461 206462 206463 206464 206465 206466 206467 206468 206469 206470 206471 206472 206473 206474 206475 206476 206477 206478 206479 206480 206481 206482 206483 206484 206485 206486 206487 206488 206489 206490 206491 206492 206493 206494 206495 206496 206497 206498 206499 206500 206501 206502 206503 206504 206505 206506 206507 206508 206509 206510 206511 206512 206513 206514 206515 206516 206517 206518 206519 206520 206521 206522 206523 206524 206525 206526 206527 206528 206529 206530 206531 206532 206533 206534 206535 206536 206537 206538 206539 206540 206541 206542 206543 206544 206545 206546 206547 206548 206549 206550 206551 206552 206553 206554 206555 206556 206557 206558 206559 206560 206561 206562 206563 206564 206565 206566 206567 206568 206569 |
goto json_parse_restart;
}
pParse->iErr = i;
return -1;
}
case 'n': {
if( strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){
jsonBlobAppendOneByte(pParse, JSONB_NULL);
return i+4;
}
/* fall-through into the default case that checks for NaN */
}
default: {
u32 k;
int nn;
c = z[i];
for(k=0; k<sizeof(aNanInfName)/sizeof(aNanInfName[0]); k++){
if( c!=aNanInfName[k].c1 && c!=aNanInfName[k].c2 ) continue;
nn = aNanInfName[k].n;
if( sqlite3StrNICmp(&z[i], aNanInfName[k].zMatch, nn)!=0 ){
continue;
}
if( sqlite3Isalnum(z[i+nn]) ) continue;
if( aNanInfName[k].eType==JSONB_FLOAT ){
jsonBlobAppendNode(pParse, JSONB_FLOAT, 5, "9e999");
}else{
jsonBlobAppendOneByte(pParse, JSONB_NULL);
}
pParse->hasNonstd = 1;
return i + nn;
}
pParse->iErr = i;
return -1; /* Syntax error */
}
} /* End switch(z[i]) */
}
/*
** Parse a complete JSON string. Return 0 on success or non-zero if there
** are any errors. If an error occurs, free all memory held by pParse,
** but not pParse itself.
**
** pParse must be initialized to an empty parse object prior to calling
** this routine.
*/
static int jsonConvertTextToBlob(
JsonParse *pParse, /* Initialize and fill this JsonParse object */
sqlite3_context *pCtx /* Report errors here */
){
int i;
const char *zJson = pParse->zJson;
i = jsonXlateTextToBlob(pParse, 0);
if( pParse->oom ) i = -1;
if( i>0 ){
#ifdef SQLITE_DEBUG
assert( pParse->iDepth==0 );
if( sqlite3Config.bJsonSelfcheck ){
assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 );
}
#endif
while( jsonIsspace(zJson[i]) ) i++;
if( zJson[i] ){
i += json5Whitespace(&zJson[i]);
if( zJson[i] ){
if( pCtx ) sqlite3_result_error(pCtx, "malformed JSON", -1);
jsonParseReset(pParse);
return 1;
}
pParse->hasNonstd = 1;
}
}
if( i<=0 ){
if( pCtx!=0 ){
if( pParse->oom ){
sqlite3_result_error_nomem(pCtx);
}else{
sqlite3_result_error(pCtx, "malformed JSON", -1);
}
}
jsonParseReset(pParse);
return 1;
}
return 0;
}
/*
** The input string pStr is a well-formed JSON text string. Convert
** this into the JSONB format and make it the return value of the
** SQL function.
*/
static void jsonReturnStringAsBlob(JsonString *pStr){
JsonParse px;
memset(&px, 0, sizeof(px));
jsonStringTerminate(pStr);
px.zJson = pStr->zBuf;
px.nJson = pStr->nUsed;
(void)jsonXlateTextToBlob(&px, 0);
if( px.oom ){
sqlite3_free(px.aBlob);
sqlite3_result_error_nomem(pStr->pCtx);
}else{
assert( px.nBlobAlloc>0 );
assert( !px.bReadOnly );
sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, sqlite3_free);
}
}
/* The byte at index i is a node type-code. This routine
** determines the payload size for that node and writes that
** payload size in to *pSz. It returns the offset from i to the
** beginning of the payload. Return 0 on error.
*/
static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
u8 x;
u32 sz;
u32 n;
if( NEVER(i>pParse->nBlob) ){
*pSz = 0;
return 0;
}
x = pParse->aBlob[i]>>4;
if( x<=11 ){
sz = x;
n = 1;
}else if( x==12 ){
if( i+1>=pParse->nBlob ){
*pSz = 0;
return 0;
}
sz = pParse->aBlob[i+1];
n = 2;
}else if( x==13 ){
if( i+2>=pParse->nBlob ){
*pSz = 0;
return 0;
}
sz = (pParse->aBlob[i+1]<<8) + pParse->aBlob[i+2];
n = 3;
}else if( x==14 ){
if( i+4>=pParse->nBlob ){
*pSz = 0;
return 0;
}
sz = ((u32)pParse->aBlob[i+1]<<24) + (pParse->aBlob[i+2]<<16) +
(pParse->aBlob[i+3]<<8) + pParse->aBlob[i+4];
n = 5;
}else{
if( i+8>=pParse->nBlob
|| pParse->aBlob[i+1]!=0
|| pParse->aBlob[i+2]!=0
|| pParse->aBlob[i+3]!=0
|| pParse->aBlob[i+4]!=0
){
*pSz = 0;
return 0;
}
sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) +
(pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
n = 9;
}
if( i+sz+n > pParse->nBlob
&& i+sz+n > pParse->nBlob-pParse->delta
){
sz = 0;
n = 0;
}
*pSz = sz;
return n;
}
/*
** Translate the binary JSONB representation of JSON beginning at
** pParse->aBlob[i] into a JSON text string. Append the JSON
** text onto the end of pOut. Return the index in pParse->aBlob[]
** of the first byte past the end of the element that is translated.
**
** If an error is detected in the BLOB input, the pOut->eErr flag
** might get set to JSTRING_MALFORMED. But not all BLOB input errors
** are detected. So a malformed JSONB input might either result
** in an error, or in incorrect JSON.
**
** The pOut->eErr JSTRING_OOM flag is set on a OOM.
*/
static u32 jsonXlateBlobToText(
const JsonParse *pParse, /* the complete parse of the JSON */
u32 i, /* Start rendering at this index */
JsonString *pOut /* Write JSON here */
){
u32 sz, n, j, iEnd;
n = jsonbPayloadSize(pParse, i, &sz);
if( n==0 ){
pOut->eErr |= JSTRING_MALFORMED;
return pParse->nBlob+1;
}
switch( pParse->aBlob[i] & 0x0f ){
case JSONB_NULL: {
jsonAppendRawNZ(pOut, "null", 4);
return i+1;
}
case JSONB_TRUE: {
jsonAppendRawNZ(pOut, "true", 4);
return i+1;
}
case JSONB_FALSE: {
jsonAppendRawNZ(pOut, "false", 5);
return i+1;
}
case JSONB_INT:
case JSONB_FLOAT: {
jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
break;
}
case JSONB_INT5: { /* Integer literal in hexadecimal notation */
u32 k = 2;
sqlite3_uint64 u = 0;
const char *zIn = (const char*)&pParse->aBlob[i+n];
int bOverflow = 0;
if( zIn[0]=='-' ){
jsonAppendChar(pOut, '-');
k++;
}else if( zIn[0]=='+' ){
k++;
}
for(; k<sz; k++){
if( !sqlite3Isxdigit(zIn[k]) ){
pOut->eErr |= JSTRING_MALFORMED;
break;
}else if( (u>>60)!=0 ){
bOverflow = 1;
}else{
u = u*16 + sqlite3HexToInt(zIn[k]);
}
}
jsonPrintf(100,pOut,bOverflow?"9.0e999":"%llu", u);
break;
}
case JSONB_FLOAT5: { /* Float literal missing digits beside "." */
u32 k = 0;
const char *zIn = (const char*)&pParse->aBlob[i+n];
if( zIn[0]=='-' ){
jsonAppendChar(pOut, '-');
k++;
}
if( zIn[k]=='.' ){
jsonAppendChar(pOut, '0');
}
for(; k<sz; k++){
jsonAppendChar(pOut, zIn[k]);
if( zIn[k]=='.' && (k+1==sz || !sqlite3Isdigit(zIn[k+1])) ){
jsonAppendChar(pOut, '0');
}
}
break;
}
case JSONB_TEXT:
case JSONB_TEXTJ: {
jsonAppendChar(pOut, '"');
jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
jsonAppendChar(pOut, '"');
break;
}
case JSONB_TEXT5: {
const char *zIn;
u32 k;
u32 sz2 = sz;
zIn = (const char*)&pParse->aBlob[i+n];
jsonAppendChar(pOut, '"');
while( sz2>0 ){
for(k=0; k<sz2 && zIn[k]!='\\' && zIn[k]!='"'; k++){}
if( k>0 ){
jsonAppendRawNZ(pOut, zIn, k);
if( k>=sz2 ){
break;
}
zIn += k;
sz2 -= k;
}
if( zIn[0]=='"' ){
jsonAppendRawNZ(pOut, "\\\"", 2);
zIn++;
sz2--;
continue;
}
assert( zIn[0]=='\\' );
assert( sz2>=1 );
if( sz2<2 ){
pOut->eErr |= JSTRING_MALFORMED;
break;
}
switch( (u8)zIn[1] ){
case '\'':
jsonAppendChar(pOut, '\'');
break;
case 'v':
jsonAppendRawNZ(pOut, "\\u0009", 6);
break;
case 'x':
if( sz2<4 ){
pOut->eErr |= JSTRING_MALFORMED;
sz2 = 2;
break;
}
jsonAppendRawNZ(pOut, "\\u00", 4);
jsonAppendRawNZ(pOut, &zIn[2], 2);
zIn += 2;
sz2 -= 2;
break;
case '0':
jsonAppendRawNZ(pOut, "\\u0000", 6);
break;
case '\r':
if( sz2>2 && zIn[2]=='\n' ){
zIn++;
sz2--;
}
break;
case '\n':
break;
case 0xe2:
/* '\' followed by either U+2028 or U+2029 is ignored as
** whitespace. Not that in UTF8, U+2028 is 0xe2 0x80 0x29.
** U+2029 is the same except for the last byte */
if( sz2<4
|| 0x80!=(u8)zIn[2]
|| (0xa8!=(u8)zIn[3] && 0xa9!=(u8)zIn[3])
){
pOut->eErr |= JSTRING_MALFORMED;
sz2 = 2;
break;
}
zIn += 2;
sz2 -= 2;
break;
default:
jsonAppendRawNZ(pOut, zIn, 2);
break;
}
assert( sz2>=2 );
zIn += 2;
sz2 -= 2;
}
jsonAppendChar(pOut, '"');
break;
}
case JSONB_TEXTRAW: {
jsonAppendString(pOut, (const char*)&pParse->aBlob[i+n], sz);
break;
}
case JSONB_ARRAY: {
jsonAppendChar(pOut, '[');
j = i+n;
iEnd = j+sz;
while( j<iEnd ){
j = jsonXlateBlobToText(pParse, j, pOut);
jsonAppendChar(pOut, ',');
}
if( sz>0 ) pOut->nUsed--;
jsonAppendChar(pOut, ']');
break;
}
case JSONB_OBJECT: {
int x = 0;
jsonAppendChar(pOut, '{');
j = i+n;
iEnd = j+sz;
while( j<iEnd ){
j = jsonXlateBlobToText(pParse, j, pOut);
jsonAppendChar(pOut, (x++ & 1) ? ',' : ':');
}
if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED;
if( sz>0 ) pOut->nUsed--;
jsonAppendChar(pOut, '}');
break;
}
default: {
pOut->eErr |= JSTRING_MALFORMED;
break;
}
}
return i+n+sz;
}
/* Return true if the input pJson
**
** For performance reasons, this routine does not do a detailed check of the
** input BLOB to ensure that it is well-formed. Hence, false positives are
** possible. False negatives should never occur, however.
*/
static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){
u32 sz, n;
const u8 *aBlob;
int nBlob;
JsonParse s;
if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0;
aBlob = sqlite3_value_blob(pJson);
nBlob = sqlite3_value_bytes(pJson);
if( nBlob<1 ) return 0;
if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0;
memset(&s, 0, sizeof(s));
s.aBlob = (u8*)aBlob;
s.nBlob = nBlob;
n = jsonbPayloadSize(&s, 0, &sz);
if( n==0 ) return 0;
if( sz+n!=(u32)nBlob ) return 0;
if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0;
return sz+n==(u32)nBlob;
}
/*
** Given that a JSONB_ARRAY object starts at offset i, return
** the number of entries in that array.
*/
static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
u32 n, sz, i, iEnd;
u32 k = 0;
n = jsonbPayloadSize(pParse, iRoot, &sz);
iEnd = iRoot+n+sz;
for(i=iRoot+n; n>0 && i<iEnd; i+=sz+n, k++){
n = jsonbPayloadSize(pParse, i, &sz);
}
return k;
}
/*
** Edit the payload size of the element at iRoot by the amount in
** pParse->delta.
*/
static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){
u32 sz = 0;
u32 nBlob;
assert( pParse->delta!=0 );
assert( pParse->nBlobAlloc >= pParse->nBlob );
nBlob = pParse->nBlob;
pParse->nBlob = pParse->nBlobAlloc;
(void)jsonbPayloadSize(pParse, iRoot, &sz);
pParse->nBlob = nBlob;
sz += pParse->delta;
pParse->delta += jsonBlobChangePayloadSize(pParse, iRoot, sz);
}
/*
** Modify the JSONB blob at pParse->aBlob by removing nDel bytes of
** content beginning at iDel, and replacing them with nIns bytes of
** content given by aIns.
**
** nDel may be zero, in which case no bytes are removed. But iDel is
** still important as new bytes will be insert beginning at iDel.
**
** aIns may be zero, in which case space is created to hold nIns bytes
** beginning at iDel, but that space is uninitialized.
**
** Set pParse->oom if an OOM occurs.
*/
static void jsonBlobEdit(
JsonParse *pParse, /* The JSONB to be modified is in pParse->aBlob */
u32 iDel, /* First byte to be removed */
u32 nDel, /* Number of bytes to remove */
const u8 *aIns, /* Content to insert */
u32 nIns /* Bytes of content to insert */
){
i64 d = (i64)nIns - (i64)nDel;
if( d!=0 ){
if( pParse->nBlob + d > pParse->nBlobAlloc ){
jsonBlobExpand(pParse, pParse->nBlob+d);
if( pParse->oom ) return;
}
memmove(&pParse->aBlob[iDel+nIns],
&pParse->aBlob[iDel+nDel],
pParse->nBlob - (iDel+nDel));
pParse->nBlob += d;
pParse->delta += d;
}
if( nIns && aIns ) memcpy(&pParse->aBlob[iDel], aIns, nIns);
}
/*
** Return the number of escaped newlines to be ignored.
** An escaped newline is a one of the following byte sequences:
**
** 0x5c 0x0a
** 0x5c 0x0d
** 0x5c 0x0d 0x0a
** 0x5c 0xe2 0x80 0xa8
** 0x5c 0xe2 0x80 0xa9
*/
static u32 jsonBytesToBypass(const char *z, u32 n){
u32 i = 0;
while( i+1<n ){
if( z[i]!='\\' ) return i;
if( z[i+1]=='\n' ){
i += 2;
continue;
}
if( z[i+1]=='\r' ){
if( i+2<n && z[i+2]=='\n' ){
i += 3;
}else{
i += 2;
}
continue;
}
if( 0xe2==(u8)z[i+1]
&& i+3<n
&& 0x80==(u8)z[i+2]
&& (0xa8==(u8)z[i+3] || 0xa9==(u8)z[i+3])
){
i += 4;
continue;
}
break;
}
return i;
}
/*
** Input z[0..n] defines JSON escape sequence including the leading '\\'.
** Decode that escape sequence into a single character. Write that
** character into *piOut. Return the number of bytes in the escape sequence.
*/
static u32 jsonUnescapeOneChar(const char *z, u32 n, u32 *piOut){
assert( n>0 );
assert( z[0]=='\\' );
if( n<2 ){
*piOut = 0xFFFD;
return n;
}
switch( (u8)z[1] ){
case 'u': {
u32 v, vlo;
if( n<6 ){
*piOut = 0xFFFD;
return n;
}
v = jsonHexToInt4(&z[2]);
if( (v & 0xfc00)==0xd800
&& n>=12
&& z[6]=='\\'
&& z[7]=='u'
&& ((vlo = jsonHexToInt4(&z[8]))&0xfc00)==0xdc00
){
*piOut = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000;
return 12;
}else{
*piOut = v;
return 6;
}
}
case 'b': { *piOut = '\b'; return 2; }
case 'f': { *piOut = '\f'; return 2; }
case 'n': { *piOut = '\n'; return 2; }
case 'r': { *piOut = '\r'; return 2; }
case 't': { *piOut = '\t'; return 2; }
case 'v': { *piOut = '\v'; return 2; }
case '0': { *piOut = 0; return 2; }
case '\'':
case '"':
case '/':
case '\\':{ *piOut = z[1]; return 2; }
case 'x': {
if( n<4 ){
*piOut = 0xFFFD;
return n;
}
*piOut = (jsonHexToInt(z[2])<<4) | jsonHexToInt(z[3]);
return 4;
}
case 0xe2:
case '\r':
case '\n': {
u32 nSkip = jsonBytesToBypass(z, n);
if( nSkip==0 ){
*piOut = 0xFFFD;
return n;
}else if( nSkip==n ){
*piOut = 0;
return n;
}else if( z[nSkip]=='\\' ){
return nSkip + jsonUnescapeOneChar(&z[nSkip], n-nSkip, piOut);
}else{
int sz = sqlite3Utf8ReadLimited((u8*)&z[nSkip], n-nSkip, piOut);
return nSkip + sz;
}
}
default: {
*piOut = 0xFFFD;
return 2;
}
}
}
/*
** Compare two object labels. Return 1 if they are equal and
** 0 if they differ.
**
** In this version, we know that one or the other or both of the
** two comparands contains an escape sequence.
*/
static SQLITE_NOINLINE int jsonLabelCompareEscaped(
const char *zLeft, /* The left label */
u32 nLeft, /* Size of the left label in bytes */
int rawLeft, /* True if zLeft contains no escapes */
const char *zRight, /* The right label */
u32 nRight, /* Size of the right label in bytes */
int rawRight /* True if zRight is escape-free */
){
u32 cLeft, cRight;
assert( rawLeft==0 || rawRight==0 );
while( 1 /*exit-by-return*/ ){
if( nLeft==0 ){
cLeft = 0;
}else if( rawLeft || zLeft[0]!='\\' ){
cLeft = ((u8*)zLeft)[0];
if( cLeft>=0xc0 ){
int sz = sqlite3Utf8ReadLimited((u8*)zLeft, nLeft, &cLeft);
zLeft += sz;
nLeft -= sz;
}else{
zLeft++;
nLeft--;
}
}else{
u32 n = jsonUnescapeOneChar(zLeft, nLeft, &cLeft);
zLeft += n;
assert( n<=nLeft );
nLeft -= n;
}
if( nRight==0 ){
cRight = 0;
}else if( rawRight || zRight[0]!='\\' ){
cRight = ((u8*)zRight)[0];
if( cRight>=0xc0 ){
int sz = sqlite3Utf8ReadLimited((u8*)zRight, nRight, &cRight);
zRight += sz;
nRight -= sz;
}else{
zRight++;
nRight--;
}
}else{
u32 n = jsonUnescapeOneChar(zRight, nRight, &cRight);
zRight += n;
assert( n<=nRight );
nRight -= n;
}
if( cLeft!=cRight ) return 0;
if( cLeft==0 ) return 1;
}
}
/*
** Compare two object labels. Return 1 if they are equal and
** 0 if they differ. Return -1 if an OOM occurs.
*/
static int jsonLabelCompare(
const char *zLeft, /* The left label */
u32 nLeft, /* Size of the left label in bytes */
int rawLeft, /* True if zLeft contains no escapes */
const char *zRight, /* The right label */
u32 nRight, /* Size of the right label in bytes */
int rawRight /* True if zRight is escape-free */
){
if( rawLeft && rawRight ){
/* Simpliest case: Neither label contains escapes. A simple
** memcmp() is sufficient. */
if( nLeft!=nRight ) return 0;
return memcmp(zLeft, zRight, nLeft)==0;
}else{
return jsonLabelCompareEscaped(zLeft, nLeft, rawLeft,
zRight, nRight, rawRight);
}
}
/*
** Error returns from jsonLookupStep()
*/
#define JSON_LOOKUP_ERROR 0xffffffff
#define JSON_LOOKUP_NOTFOUND 0xfffffffe
#define JSON_LOOKUP_PATHERROR 0xfffffffd
#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
/* Forward declaration */
static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
/* This helper routine for jsonLookupStep() populates pIns with
** binary data that is to be inserted into pParse.
**
** In the common case, pIns just points to pParse->aIns and pParse->nIns.
** But if the zPath of the original edit operation includes path elements
** that go deeper, additional substructure must be created.
**
** For example:
**
** json_insert('{}', '$.a.b.c', 123);
**
** The search stops at '$.a' But additional substructure must be
** created for the ".b.c" part of the patch so that the final result
** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with
** the binary equivalent of {"b":{"c":123}} so that it can be inserted.
**
** The caller is responsible for resetting pIns when it has finished
** using the substructure.
*/
static u32 jsonCreateEditSubstructure(
JsonParse *pParse, /* The original JSONB that is being edited */
JsonParse *pIns, /* Populate this with the blob data to insert */
const char *zTail /* Tail of the path that determins substructure */
){
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
int rc;
memset(pIns, 0, sizeof(*pIns));
if( zTail[0]==0 ){
/* No substructure. Just insert what is given in pParse. */
pIns->aBlob = pParse->aIns;
pIns->nBlob = pParse->nIns;
rc = 0;
}else{
/* Construct the binary substructure */
pIns->nBlob = 1;
pIns->aBlob = (u8*)&emptyObject[zTail[0]=='.'];
pIns->eEdit = pParse->eEdit;
pIns->nIns = pParse->nIns;
pIns->aIns = pParse->aIns;
rc = jsonLookupStep(pIns, 0, zTail, 0);
pParse->oom |= pIns->oom;
}
return rc; /* Error code only */
}
/*
** Search along zPath to find the Json element specified. Return an
** index into pParse->aBlob[] for the start of that element's value.
**
** If the value found by this routine is the value half of label/value pair
** within an object, then set pPath->iLabel to the start of the corresponding
** label, before returning.
**
** Return one of the JSON_LOOKUP error codes if problems are seen.
**
** This routine will also modify the blob. If pParse->eEdit is one of
** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be
** made to the selected value. If an edit is performed, then the return
** value does not necessarily point to the select element. If an edit
** is performed, the return value is only useful for detecting error
** conditions.
*/
static u32 jsonLookupStep(
JsonParse *pParse, /* The JSON to search */
u32 iRoot, /* Begin the search at this element of aBlob[] */
const char *zPath, /* The path to search */
u32 iLabel /* Label if iRoot is a value of in an object */
){
u32 i, j, k, nKey, sz, n, iEnd, rc;
const char *zKey;
u8 x;
if( zPath[0]==0 ){
if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){
n = jsonbPayloadSize(pParse, iRoot, &sz);
sz += n;
if( pParse->eEdit==JEDIT_DEL ){
if( iLabel>0 ){
sz += iRoot - iLabel;
iRoot = iLabel;
}
jsonBlobEdit(pParse, iRoot, sz, 0, 0);
}else if( pParse->eEdit==JEDIT_INS ){
/* Already exists, so json_insert() is a no-op */
}else{
/* json_set() or json_replace() */
jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns);
}
}
pParse->iLabel = iLabel;
return iRoot;
}
if( zPath[0]=='.' ){
int rawKey = 1;
x = pParse->aBlob[iRoot];
zPath++;
if( zPath[0]=='"' ){
zKey = zPath + 1;
for(i=1; zPath[i] && zPath[i]!='"'; i++){}
nKey = i-1;
if( zPath[i] ){
i++;
}else{
return JSON_LOOKUP_PATHERROR;
}
testcase( nKey==0 );
rawKey = memchr(zKey, '\\', nKey)==0;
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
if( nKey==0 ){
return JSON_LOOKUP_PATHERROR;
}
}
if( (x & 0x0f)!=JSONB_OBJECT ) return JSON_LOOKUP_NOTFOUND;
n = jsonbPayloadSize(pParse, iRoot, &sz);
j = iRoot + n; /* j is the index of a label */
iEnd = j+sz;
while( j<iEnd ){
int rawLabel;
const char *zLabel;
x = pParse->aBlob[j] & 0x0f;
if( x<JSONB_TEXT || x>JSONB_TEXTRAW ) return JSON_LOOKUP_ERROR;
n = jsonbPayloadSize(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
k = j+n; /* k is the index of the label text */
if( k+sz>=iEnd ) return JSON_LOOKUP_ERROR;
zLabel = (const char*)&pParse->aBlob[k];
rawLabel = x==JSONB_TEXT || x==JSONB_TEXTRAW;
if( jsonLabelCompare(zKey, nKey, rawKey, zLabel, sz, rawLabel) ){
u32 v = k+sz; /* v is the index of the value */
if( ((pParse->aBlob[v])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR;
n = jsonbPayloadSize(pParse, v, &sz);
if( n==0 || v+n+sz>iEnd ) return JSON_LOOKUP_ERROR;
assert( j>0 );
rc = jsonLookupStep(pParse, v, &zPath[i], j);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return rc;
}
j = k+sz;
if( ((pParse->aBlob[j])&0x0f)>JSONB_OBJECT ) return JSON_LOOKUP_ERROR;
n = jsonbPayloadSize(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
j += n+sz;
}
if( j>iEnd ) return JSON_LOOKUP_ERROR;
if( pParse->eEdit>=JEDIT_INS ){
u32 nIns; /* Total bytes to insert (label+value) */
JsonParse v; /* BLOB encoding of the value to be inserted */
JsonParse ix; /* Header of the label to be inserted */
testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET );
memset(&ix, 0, sizeof(ix));
jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
pParse->oom |= ix.oom;
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
if( !JSON_LOOKUP_ISERROR(rc)
&& jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob)
){
assert( !pParse->oom );
nIns = ix.nBlob + nKey + v.nBlob;
jsonBlobEdit(pParse, j, 0, 0, nIns);
if( !pParse->oom ){
assert( pParse->aBlob!=0 ); /* Because pParse->oom!=0 */
assert( ix.aBlob!=0 ); /* Because pPasre->oom!=0 */
memcpy(&pParse->aBlob[j], ix.aBlob, ix.nBlob);
k = j + ix.nBlob;
memcpy(&pParse->aBlob[k], zKey, nKey);
k += nKey;
memcpy(&pParse->aBlob[k], v.aBlob, v.nBlob);
if( ALWAYS(pParse->delta) ) jsonAfterEditSizeAdjust(pParse, iRoot);
}
}
jsonParseReset(&v);
jsonParseReset(&ix);
return rc;
}
}else if( zPath[0]=='[' ){
x = pParse->aBlob[iRoot] & 0x0f;
if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND;
n = jsonbPayloadSize(pParse, iRoot, &sz);
k = 0;
i = 1;
while( sqlite3Isdigit(zPath[i]) ){
k = k*10 + zPath[i] - '0';
i++;
}
if( i<2 || zPath[i]!=']' ){
if( zPath[1]=='#' ){
k = jsonbArrayCount(pParse, iRoot);
i = 2;
if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){
unsigned int nn = 0;
i = 3;
do{
nn = nn*10 + zPath[i] - '0';
i++;
}while( sqlite3Isdigit(zPath[i]) );
if( nn>k ) return JSON_LOOKUP_NOTFOUND;
k -= nn;
}
if( zPath[i]!=']' ){
return JSON_LOOKUP_PATHERROR;
}
}else{
return JSON_LOOKUP_PATHERROR;
}
}
j = iRoot+n;
iEnd = j+sz;
while( j<iEnd ){
if( k==0 ){
rc = jsonLookupStep(pParse, j, &zPath[i+1], 0);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return rc;
}
k--;
n = jsonbPayloadSize(pParse, j, &sz);
if( n==0 ) return JSON_LOOKUP_ERROR;
j += n+sz;
}
if( j>iEnd ) return JSON_LOOKUP_ERROR;
if( k>0 ) return JSON_LOOKUP_NOTFOUND;
if( pParse->eEdit>=JEDIT_INS ){
JsonParse v;
testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET );
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
if( !JSON_LOOKUP_ISERROR(rc)
&& jsonBlobMakeEditable(pParse, v.nBlob)
){
assert( !pParse->oom );
jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob);
}
jsonParseReset(&v);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return rc;
}
}else{
return JSON_LOOKUP_PATHERROR;
}
return JSON_LOOKUP_NOTFOUND;
}
/*
** Convert a JSON BLOB into text and make that text the return value
** of an SQL function.
*/
static void jsonReturnTextJsonFromBlob(
sqlite3_context *ctx,
const u8 *aBlob,
u32 nBlob
){
JsonParse x;
JsonString s;
if( NEVER(aBlob==0) ) return;
memset(&x, 0, sizeof(x));
x.aBlob = (u8*)aBlob;
x.nBlob = nBlob;
jsonStringInit(&s, ctx);
jsonXlateBlobToText(&x, 0, &s);
jsonReturnString(&s, 0, 0);
}
/*
** Return the value of the BLOB node at index i.
**
** If the value is a primitive, return it as an SQL value.
** If the value is an array or object, return it as either
** JSON text or the BLOB encoding, depending on the JSON_B flag
** on the userdata.
*/
static void jsonReturnFromBlob(
JsonParse *pParse, /* Complete JSON parse tree */
u32 i, /* Index of the node */
sqlite3_context *pCtx, /* Return value for this function */
int textOnly /* return text JSON. Disregard user-data */
){
u32 n, sz;
int rc;
sqlite3 *db = sqlite3_context_db_handle(pCtx);
n = jsonbPayloadSize(pParse, i, &sz);
if( n==0 ){
sqlite3_result_error(pCtx, "malformed JSON", -1);
return;
}
switch( pParse->aBlob[i] & 0x0f ){
case JSONB_NULL: {
if( sz ) goto returnfromblob_malformed;
sqlite3_result_null(pCtx);
break;
}
case JSONB_TRUE: {
if( sz ) goto returnfromblob_malformed;
sqlite3_result_int(pCtx, 1);
break;
}
case JSONB_FALSE: {
if( sz ) goto returnfromblob_malformed;
sqlite3_result_int(pCtx, 0);
break;
}
case JSONB_INT5:
case JSONB_INT: {
sqlite3_int64 iRes = 0;
char *z;
int bNeg = 0;
char x;
if( sz==0 ) goto returnfromblob_malformed;
x = (char)pParse->aBlob[i+n];
if( x=='-' ){
if( sz<2 ) goto returnfromblob_malformed;
n++;
sz--;
bNeg = 1;
}
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
if( z==0 ) goto returnfromblob_oom;
rc = sqlite3DecOrHexToI64(z, &iRes);
sqlite3DbFree(db, z);
if( rc==0 ){
sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes);
}else if( rc==3 && bNeg ){
sqlite3_result_int64(pCtx, SMALLEST_INT64);
}else if( rc==1 ){
goto returnfromblob_malformed;
}else{
if( bNeg ){ n--; sz++; }
goto to_double;
}
break;
}
case JSONB_FLOAT5:
case JSONB_FLOAT: {
double r;
char *z;
if( sz==0 ) goto returnfromblob_malformed;
to_double:
z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz);
if( z==0 ) goto returnfromblob_oom;
rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
sqlite3DbFree(db, z);
if( rc<=0 ) goto returnfromblob_malformed;
sqlite3_result_double(pCtx, r);
break;
}
case JSONB_TEXTRAW:
case JSONB_TEXT: {
sqlite3_result_text(pCtx, (char*)&pParse->aBlob[i+n], sz,
SQLITE_TRANSIENT);
break;
}
case JSONB_TEXT5:
case JSONB_TEXTJ: {
/* Translate JSON formatted string into raw text */
u32 iIn, iOut;
const char *z;
char *zOut;
u32 nOut = sz;
z = (const char*)&pParse->aBlob[i+n];
zOut = sqlite3_malloc( nOut+1 );
if( zOut==0 ) goto returnfromblob_oom;
for(iIn=iOut=0; iIn<sz; iIn++){
char c = z[iIn];
if( c=='\\' ){
u32 v;
u32 szEscape = jsonUnescapeOneChar(&z[iIn], sz-iIn, &v);
if( v<=0x7f ){
zOut[iOut++] = (char)v;
}else if( v==0xfffd ){
/* Silently ignore illegal unicode */
}else if( v<=0x7ff ){
assert( szEscape>=2 );
zOut[iOut++] = (char)(0xc0 | (v>>6));
zOut[iOut++] = 0x80 | (v&0x3f);
}else if( v<0x10000 ){
assert( szEscape>=3 );
zOut[iOut++] = 0xe0 | (v>>12);
zOut[iOut++] = 0x80 | ((v>>6)&0x3f);
zOut[iOut++] = 0x80 | (v&0x3f);
}else{
assert( szEscape>=4 );
zOut[iOut++] = 0xf0 | (v>>18);
zOut[iOut++] = 0x80 | ((v>>12)&0x3f);
zOut[iOut++] = 0x80 | ((v>>6)&0x3f);
zOut[iOut++] = 0x80 | (v&0x3f);
}
iIn += szEscape - 1;
}else{
zOut[iOut++] = c;
}
} /* end for() */
assert( iOut<=nOut );
zOut[iOut] = 0;
sqlite3_result_text(pCtx, zOut, iOut, sqlite3_free);
break;
}
case JSONB_ARRAY:
case JSONB_OBJECT: {
int flags = textOnly ? 0 : SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx));
if( flags & JSON_BLOB ){
sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT);
}else{
jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n);
}
break;
}
default: {
goto returnfromblob_malformed;
}
}
return;
returnfromblob_oom:
sqlite3_result_error_nomem(pCtx);
return;
returnfromblob_malformed:
sqlite3_result_error(pCtx, "malformed JSON", -1);
return;
}
/*
** pArg is a function argument that might be an SQL value or a JSON
** value. Figure out what it is and encode it as a JSONB blob.
** Return the results in pParse.
**
** pParse is uninitialized upon entry. This routine will handle the
** initialization of pParse. The result will be contained in
** pParse->aBlob and pParse->nBlob. pParse->aBlob might be dynamically
** allocated (if pParse->nBlobAlloc is greater than zero) in which case
** the caller is responsible for freeing the space allocated to pParse->aBlob
** when it has finished with it. Or pParse->aBlob might be a static string
** or a value obtained from sqlite3_value_blob(pArg).
**
** If the argument is a BLOB that is clearly not a JSONB, then this
** function might set an error message in ctx and return non-zero.
** It might also set an error message and return non-zero on an OOM error.
*/
static int jsonFunctionArgToBlob(
sqlite3_context *ctx,
sqlite3_value *pArg,
JsonParse *pParse
){
int eType = sqlite3_value_type(pArg);
static u8 aNull[] = { 0x00 };
memset(pParse, 0, sizeof(pParse[0]));
switch( eType ){
default: {
pParse->aBlob = aNull;
pParse->nBlob = 1;
return 0;
}
case SQLITE_BLOB: {
if( jsonFuncArgMightBeBinary(pArg) ){
pParse->aBlob = (u8*)sqlite3_value_blob(pArg);
pParse->nBlob = sqlite3_value_bytes(pArg);
}else{
sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
return 1;
}
break;
}
case SQLITE_TEXT: {
const char *zJson = (const char*)sqlite3_value_text(pArg);
int nJson = sqlite3_value_bytes(pArg);
if( zJson==0 ) return 1;
if( sqlite3_value_subtype(pArg)==JSON_SUBTYPE ){
pParse->zJson = (char*)zJson;
pParse->nJson = nJson;
if( jsonConvertTextToBlob(pParse, ctx) ){
sqlite3_result_error(ctx, "malformed JSON", -1);
sqlite3_free(pParse->aBlob);
memset(pParse, 0, sizeof(pParse[0]));
return 1;
}
}else{
jsonBlobAppendNode(pParse, JSONB_TEXTRAW, nJson, zJson);
}
break;
}
case SQLITE_FLOAT:
case SQLITE_INTEGER: {
int n = sqlite3_value_bytes(pArg);
const char *z = (const char*)sqlite3_value_text(pArg);
int e = eType==SQLITE_INTEGER ? JSONB_INT : JSONB_FLOAT;
if( z==0 ) return 1;
jsonBlobAppendNode(pParse, e, n, z);
break;
}
}
if( pParse->oom ){
sqlite3_result_error_nomem(ctx);
return 1;
}else{
return 0;
}
}
/*
** Generate a bad path error.
**
** If ctx is not NULL then push the error message into ctx and return NULL.
** If ctx is NULL, then return the text of the error message.
*/
static char *jsonBadPathError(
sqlite3_context *ctx, /* The function call containing the error */
const char *zPath /* The path with the problem */
){
char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath);
if( ctx==0 ) return zMsg;
if( zMsg ){
sqlite3_result_error(ctx, zMsg, -1);
sqlite3_free(zMsg);
}else{
sqlite3_result_error_nomem(ctx);
}
return 0;
}
/* argv[0] is a BLOB that seems likely to be a JSONB. Subsequent
** arguments come in parse where each pair contains a JSON path and
** content to insert or set at that patch. Do the updates
** and return the result.
**
** The specific operation is determined by eEdit, which can be one
** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET.
*/
static void jsonInsertIntoBlob(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv,
int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */
){
int i;
u32 rc = 0;
const char *zPath = 0;
int flgs;
JsonParse *p;
JsonParse ax;
assert( (argc&1)==1 );
flgs = argc==1 ? 0 : JSON_EDITABLE;
p = jsonParseFuncArg(ctx, argv[0], flgs);
if( p==0 ) return;
for(i=1; i<argc-1; i+=2){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ) continue;
zPath = (const char*)sqlite3_value_text(argv[i]);
if( zPath==0 ){
sqlite3_result_error_nomem(ctx);
jsonParseFree(p);
return;
}
if( zPath[0]!='$' ) goto jsonInsertIntoBlob_patherror;
if( jsonFunctionArgToBlob(ctx, argv[i+1], &ax) ){
jsonParseReset(&ax);
jsonParseFree(p);
return;
}
if( zPath[1]==0 ){
if( eEdit==JEDIT_REPL || eEdit==JEDIT_SET ){
jsonBlobEdit(p, 0, p->nBlob, ax.aBlob, ax.nBlob);
}
rc = 0;
}else{
p->eEdit = eEdit;
p->nIns = ax.nBlob;
p->aIns = ax.aBlob;
p->delta = 0;
rc = jsonLookupStep(p, 0, zPath+1, 0);
}
jsonParseReset(&ax);
if( rc==JSON_LOOKUP_NOTFOUND ) continue;
if( JSON_LOOKUP_ISERROR(rc) ) goto jsonInsertIntoBlob_patherror;
}
jsonReturnParse(ctx, p);
jsonParseFree(p);
return;
jsonInsertIntoBlob_patherror:
jsonParseFree(p);
if( rc==JSON_LOOKUP_ERROR ){
sqlite3_result_error(ctx, "malformed JSON", -1);
}else{
jsonBadPathError(ctx, zPath);
}
return;
}
/*
** Make a copy of a JsonParse object. The copy will be editable.
*/
/*
** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob,
** from the SQL function argument pArg. Return a pointer to the new
** JsonParse object.
**
** Ownership of the new JsonParse object is passed to the caller. The
** caller should invoke jsonParseFree() on the return value when it
** has finished using it.
**
** If any errors are detected, an appropriate error messages is set
** using sqlite3_result_error() or the equivalent and this routine
** returns NULL. This routine also returns NULL if the pArg argument
** is an SQL NULL value, but no error message is set in that case. This
** is so that SQL functions that are given NULL arguments will return
** a NULL value.
*/
static JsonParse *jsonParseFuncArg(
sqlite3_context *ctx,
sqlite3_value *pArg,
u32 flgs
){
int eType; /* Datatype of pArg */
JsonParse *p = 0; /* Value to be returned */
JsonParse *pFromCache = 0; /* Value taken from cache */
assert( ctx!=0 );
eType = sqlite3_value_type(pArg);
if( eType==SQLITE_NULL ){
return 0;
}
pFromCache = jsonCacheSearch(ctx, pArg);
if( pFromCache ){
pFromCache->nJPRef++;
if( (flgs & JSON_EDITABLE)==0 ){
return pFromCache;
}
}
rebuild_from_cache:
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) goto json_pfa_oom;
memset(p, 0, sizeof(*p));
p->nJPRef = 1;
if( pFromCache!=0 ){
u32 nBlob = pFromCache->nBlob;
p->aBlob = sqlite3_malloc64( nBlob );
if( p->aBlob==0 ) goto json_pfa_oom;
memcpy(p->aBlob, pFromCache->aBlob, nBlob);
p->nBlobAlloc = p->nBlob = nBlob;
p->hasNonstd = pFromCache->hasNonstd;
jsonParseFree(pFromCache);
return p;
}
if( eType==SQLITE_BLOB ){
u32 n, sz = 0;
p->aBlob = (u8*)sqlite3_value_blob(pArg);
p->nBlob = (u32)sqlite3_value_bytes(pArg);
if( p->nBlob==0 ){
goto json_pfa_malformed;
}
if( NEVER(p->aBlob==0) ){
goto json_pfa_oom;
}
if( (p->aBlob[0] & 0x0f)>JSONB_OBJECT ){
goto json_pfa_malformed;
}
n = jsonbPayloadSize(p, 0, &sz);
if( n==0
|| sz+n!=p->nBlob
|| ((p->aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0)
){
goto json_pfa_malformed;
}
if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){
goto json_pfa_oom;
}
return p;
}
p->zJson = (char*)sqlite3_value_text(pArg);
p->nJson = sqlite3_value_bytes(pArg);
if( p->nJson==0 ) goto json_pfa_malformed;
if( NEVER(p->zJson==0) ) goto json_pfa_oom;
if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){
if( flgs & JSON_KEEPERROR ){
p->nErr = 1;
return p;
}else{
jsonParseFree(p);
return 0;
}
}else{
int isRCStr = sqlite3ValueIsOfClass(pArg, sqlite3RCStrUnref);
int rc;
if( !isRCStr ){
char *zNew = sqlite3RCStrNew( p->nJson );
if( zNew==0 ) goto json_pfa_oom;
memcpy(zNew, p->zJson, p->nJson);
p->zJson = zNew;
p->zJson[p->nJson] = 0;
}else{
sqlite3RCStrRef(p->zJson);
}
p->bJsonIsRCStr = 1;
rc = jsonCacheInsert(ctx, p);
if( rc==SQLITE_NOMEM ) goto json_pfa_oom;
if( flgs & JSON_EDITABLE ){
pFromCache = p;
p = 0;
goto rebuild_from_cache;
}
}
return p;
json_pfa_malformed:
if( flgs & JSON_KEEPERROR ){
p->nErr = 1;
return p;
}else{
jsonParseFree(p);
sqlite3_result_error(ctx, "malformed JSON", -1);
return 0;
}
json_pfa_oom:
jsonParseFree(pFromCache);
jsonParseFree(p);
sqlite3_result_error_nomem(ctx);
return 0;
}
/*
** Make the return value of a JSON function either the raw JSONB blob
** or make it JSON text, depending on whether the JSON_BLOB flag is
** set on the function.
*/
static void jsonReturnParse(
sqlite3_context *ctx,
JsonParse *p
){
int flgs;
if( p->oom ){
sqlite3_result_error_nomem(ctx);
return;
}
flgs = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( flgs & JSON_BLOB ){
if( p->nBlobAlloc>0 && !p->bReadOnly ){
sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_DYNAMIC);
p->nBlobAlloc = 0;
}else{
sqlite3_result_blob(ctx, p->aBlob, p->nBlob, SQLITE_TRANSIENT);
}
}else{
JsonString s;
jsonStringInit(&s, ctx);
jsonXlateBlobToText(p, 0, &s);
jsonReturnString(&s, p, ctx);
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
}
/****************************************************************************
** SQL functions used for testing and debugging
****************************************************************************/
#if SQLITE_DEBUG
/*
** Decode JSONB bytes in aBlob[] starting at iStart through but not
** including iEnd. Indent the
** content by nIndent spaces.
*/
static void jsonDebugPrintBlob(
JsonParse *pParse, /* JSON content */
u32 iStart, /* Start rendering here */
u32 iEnd, /* Do not render this byte or any byte after this one */
int nIndent /* Indent by this many spaces */
){
while( iStart<iEnd ){
u32 i, n, nn, sz = 0;
int showContent = 1;
u8 x = pParse->aBlob[iStart] & 0x0f;
u32 savedNBlob = pParse->nBlob;
printf("%5d:%*s", iStart, nIndent, "");
if( pParse->nBlobAlloc>pParse->nBlob ){
pParse->nBlob = pParse->nBlobAlloc;
}
nn = n = jsonbPayloadSize(pParse, iStart, &sz);
if( nn==0 ) nn = 1;
if( sz>0 && x<JSONB_ARRAY ){
nn += sz;
}
for(i=0; i<nn; i++) printf(" %02x", pParse->aBlob[iStart+i]);
if( n==0 ){
printf(" ERROR invalid node size\n");
iStart = n==0 ? iStart+1 : iEnd;
continue;
}
pParse->nBlob = savedNBlob;
if( iStart+n+sz>iEnd ){
iEnd = iStart+n+sz;
if( iEnd>pParse->nBlob ){
if( pParse->nBlobAlloc>0 && iEnd>pParse->nBlobAlloc ){
iEnd = pParse->nBlobAlloc;
}else{
iEnd = pParse->nBlob;
}
}
}
printf(" <-- ");
switch( x ){
case JSONB_NULL: printf("null"); break;
case JSONB_TRUE: printf("true"); break;
case JSONB_FALSE: printf("false"); break;
case JSONB_INT: printf("int"); break;
case JSONB_INT5: printf("int5"); break;
case JSONB_FLOAT: printf("float"); break;
case JSONB_FLOAT5: printf("float5"); break;
case JSONB_TEXT: printf("text"); break;
case JSONB_TEXTJ: printf("textj"); break;
case JSONB_TEXT5: printf("text5"); break;
case JSONB_TEXTRAW: printf("textraw"); break;
case JSONB_ARRAY: {
printf("array, %u bytes\n", sz);
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2);
showContent = 0;
break;
}
case JSONB_OBJECT: {
printf("object, %u bytes\n", sz);
jsonDebugPrintBlob(pParse, iStart+n, iStart+n+sz, nIndent+2);
showContent = 0;
break;
}
default: {
printf("ERROR: unknown node type\n");
showContent = 0;
break;
}
}
if( showContent ){
if( sz==0 && x<=JSONB_FALSE ){
printf("\n");
}else{
u32 i;
printf(": \"");
for(i=iStart+n; i<iStart+n+sz; i++){
u8 c = pParse->aBlob[i];
if( c<0x20 || c>=0x7f ) c = '.';
putchar(c);
}
printf("\"\n");
}
}
iStart += n + sz;
}
}
static void jsonShowParse(JsonParse *pParse){
if( pParse==0 ){
printf("NULL pointer\n");
return;
}else{
printf("nBlobAlloc = %u\n", pParse->nBlobAlloc);
printf("nBlob = %u\n", pParse->nBlob);
printf("delta = %d\n", pParse->delta);
if( pParse->nBlob==0 ) return;
printf("content (bytes 0..%u):\n", pParse->nBlob-1);
}
jsonDebugPrintBlob(pParse, 0, pParse->nBlob, 0);
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
** SQL function: json_parse(JSON)
**
** Parse JSON using jsonParseFuncArg(). Then print a dump of that
** parse on standard output.
*/
static void jsonParseFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
assert( argc==1 );
p = jsonParseFuncArg(ctx, argv[0], 0);
jsonShowParse(p);
jsonParseFree(p);
}
#endif /* SQLITE_DEBUG */
/****************************************************************************
** Scalar SQL function implementations
****************************************************************************/
/*
** Implementation of the json_quote(VALUE) function. Return a JSON value
** corresponding to the SQL value input. Mostly this means putting
** double-quotes around strings and returning the unquoted string "null"
** when given a NULL input.
*/
static void jsonQuoteFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonString jx;
UNUSED_PARAMETER(argc);
jsonStringInit(&jx, ctx);
jsonAppendSqlValue(&jx, argv[0]);
jsonReturnString(&jx, 0, 0);
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
/*
** Implementation of the json_array(VALUE,...) function. Return a JSON
** array that contains all values given in arguments. Or if any argument
** is a BLOB, throw an error.
*/
static void jsonArrayFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
int i;
JsonString jx;
jsonStringInit(&jx, ctx);
jsonAppendChar(&jx, '[');
for(i=0; i<argc; i++){
jsonAppendSeparator(&jx);
jsonAppendSqlValue(&jx, argv[i]);
}
jsonAppendChar(&jx, ']');
jsonReturnString(&jx, 0, 0);
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
/*
** json_array_length(JSON)
** json_array_length(JSON, PATH)
**
** Return the number of elements in the top-level JSON array.
** Return 0 if the input is not a well-formed JSON array.
*/
static void jsonArrayLengthFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
sqlite3_int64 cnt = 0;
u32 i;
u8 eErr = 0;
p = jsonParseFuncArg(ctx, argv[0], 0);
if( p==0 ) return;
if( argc==2 ){
const char *zPath = (const char*)sqlite3_value_text(argv[1]);
if( zPath==0 ){
jsonParseFree(p);
return;
}
i = jsonLookupStep(p, 0, zPath[0]=='$' ? zPath+1 : "@", 0);
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
/* no-op */
}else if( i==JSON_LOOKUP_PATHERROR ){
jsonBadPathError(ctx, zPath);
}else{
sqlite3_result_error(ctx, "malformed JSON", -1);
}
eErr = 1;
i = 0;
}
}else{
i = 0;
}
if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){
cnt = jsonbArrayCount(p, i);
}
if( !eErr ) sqlite3_result_int64(ctx, cnt);
jsonParseFree(p);
}
/* True if the string is all digits */
static int jsonAllDigits(const char *z, int n){
int i;
for(i=0; i<n && sqlite3Isdigit(z[i]); i++){}
return i==n;
}
/* True if the string is all alphanumerics and underscores */
static int jsonAllAlphanum(const char *z, int n){
int i;
for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){}
return i==n;
}
/*
** json_extract(JSON, PATH, ...)
** "->"(JSON,PATH)
** "->>"(JSON,PATH)
**
** Return the element described by PATH. Return NULL if that PATH element
|
| ︙ | ︙ | |||
205177 205178 205179 205180 205181 205182 205183 |
** compatibility with PG.
*/
static void jsonExtractFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
| | < < | > | | > > | > > > | > > | > > > | < | | | | | | | | | | | | | > > > > > | | | | | > | | | | > | > | > > | > > > | > > > > | | | | < > | > > > | < < < < < < < < < | > > | > | | > | | | | | | > > > | > > | | > > > > > > > > | | > > > > > | < > > > > > > > | > | < | > > > | > | | | < > > > > > > > > > > > | > > | > > > | > | | | > > > > > > > > > > > > > > | < < > > > | > > > > > | | | | > > > > | | | | | | > | | | < | < | | < | > > > > > > | > | > > > > | | > > > > > > > > | < | < > | > > > > | > > | > > > > > > > > > > > > > > > | > > | > > > > > > > > | < > > > > > > > > | > > > | < < > > > > > | | > > | | | > > | > | | | > | | < < | | < < | < | | > | < | | | > > > | 206582 206583 206584 206585 206586 206587 206588 206589 206590 206591 206592 206593 206594 206595 206596 206597 206598 206599 206600 206601 206602 206603 206604 206605 206606 206607 206608 206609 206610 206611 206612 206613 206614 206615 206616 206617 206618 206619 206620 206621 206622 206623 206624 206625 206626 206627 206628 206629 206630 206631 206632 206633 206634 206635 206636 206637 206638 206639 206640 206641 206642 206643 206644 206645 206646 206647 206648 206649 206650 206651 206652 206653 206654 206655 206656 206657 206658 206659 206660 206661 206662 206663 206664 206665 206666 206667 206668 206669 206670 206671 206672 206673 206674 206675 206676 206677 206678 206679 206680 206681 206682 206683 206684 206685 206686 206687 206688 206689 206690 206691 206692 206693 206694 206695 206696 206697 206698 206699 206700 206701 206702 206703 206704 206705 206706 206707 206708 206709 206710 206711 206712 206713 206714 206715 206716 206717 206718 206719 206720 206721 206722 206723 206724 206725 206726 206727 206728 206729 206730 206731 206732 206733 206734 206735 206736 206737 206738 206739 206740 206741 206742 206743 206744 206745 206746 206747 206748 206749 206750 206751 206752 206753 206754 206755 206756 206757 206758 206759 206760 206761 206762 206763 206764 206765 206766 206767 206768 206769 206770 206771 206772 206773 206774 206775 206776 206777 206778 206779 206780 206781 206782 206783 206784 206785 206786 206787 206788 206789 206790 206791 206792 206793 206794 206795 206796 206797 206798 206799 206800 206801 206802 206803 206804 206805 206806 206807 206808 206809 206810 206811 206812 206813 206814 206815 206816 206817 206818 206819 206820 206821 206822 206823 206824 206825 206826 206827 206828 206829 206830 206831 206832 206833 206834 206835 206836 206837 206838 206839 206840 206841 206842 206843 206844 206845 206846 206847 206848 206849 206850 206851 206852 206853 206854 206855 206856 206857 206858 206859 206860 206861 206862 206863 206864 206865 206866 206867 206868 206869 206870 206871 206872 206873 206874 206875 206876 206877 206878 206879 206880 206881 206882 206883 206884 206885 206886 206887 206888 206889 206890 206891 206892 206893 206894 206895 206896 206897 206898 206899 206900 206901 206902 206903 206904 206905 206906 206907 206908 206909 206910 206911 206912 206913 206914 206915 206916 206917 206918 206919 206920 206921 206922 206923 206924 206925 206926 206927 |
** compatibility with PG.
*/
static void jsonExtractFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p = 0; /* The parse */
int flags; /* Flags associated with the function */
int i; /* Loop counter */
JsonString jx; /* String for array result */
if( argc<2 ) return;
p = jsonParseFuncArg(ctx, argv[0], 0);
if( p==0 ) return;
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
jsonStringInit(&jx, ctx);
if( argc>2 ){
jsonAppendChar(&jx, '[');
}
for(i=1; i<argc; i++){
/* With a single PATH argument */
const char *zPath = (const char*)sqlite3_value_text(argv[i]);
int nPath;
u32 j;
if( zPath==0 ) goto json_extract_error;
nPath = sqlite3Strlen30(zPath);
if( zPath[0]=='$' ){
j = jsonLookupStep(p, 0, zPath+1, 0);
}else if( (flags & JSON_ABPATH) ){
/* The -> and ->> operators accept abbreviated PATH arguments. This
** is mostly for compatibility with PostgreSQL, but also for
** convenience.
**
** NUMBER ==> $[NUMBER] // PG compatible
** LABEL ==> $.LABEL // PG compatible
** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
*/
jsonStringInit(&jx, ctx);
if( jsonAllDigits(zPath, nPath) ){
jsonAppendRawNZ(&jx, "[", 1);
jsonAppendRaw(&jx, zPath, nPath);
jsonAppendRawNZ(&jx, "]", 2);
}else if( jsonAllAlphanum(zPath, nPath) ){
jsonAppendRawNZ(&jx, ".", 1);
jsonAppendRaw(&jx, zPath, nPath);
}else if( zPath[0]=='[' && nPath>=3 && zPath[nPath-1]==']' ){
jsonAppendRaw(&jx, zPath, nPath);
}else{
jsonAppendRawNZ(&jx, ".\"", 2);
jsonAppendRaw(&jx, zPath, nPath);
jsonAppendRawNZ(&jx, "\"", 1);
}
jsonStringTerminate(&jx);
j = jsonLookupStep(p, 0, jx.zBuf, 0);
jsonStringReset(&jx);
}else{
jsonBadPathError(ctx, zPath);
goto json_extract_error;
}
if( j<p->nBlob ){
if( argc==2 ){
if( flags & JSON_JSON ){
jsonStringInit(&jx, ctx);
jsonXlateBlobToText(p, j, &jx);
jsonReturnString(&jx, 0, 0);
jsonStringReset(&jx);
assert( (flags & JSON_BLOB)==0 );
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}else{
jsonReturnFromBlob(p, j, ctx, 0);
if( (flags & (JSON_SQL|JSON_BLOB))==0
&& (p->aBlob[j]&0x0f)>=JSONB_ARRAY
){
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
}
}else{
jsonAppendSeparator(&jx);
jsonXlateBlobToText(p, j, &jx);
}
}else if( j==JSON_LOOKUP_NOTFOUND ){
if( argc==2 ){
goto json_extract_error; /* Return NULL if not found */
}else{
jsonAppendSeparator(&jx);
jsonAppendRawNZ(&jx, "null", 4);
}
}else if( j==JSON_LOOKUP_ERROR ){
sqlite3_result_error(ctx, "malformed JSON", -1);
goto json_extract_error;
}else{
jsonBadPathError(ctx, zPath);
goto json_extract_error;
}
}
if( argc>2 ){
jsonAppendChar(&jx, ']');
jsonReturnString(&jx, 0, 0);
if( (flags & JSON_BLOB)==0 ){
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
}
json_extract_error:
jsonStringReset(&jx);
jsonParseFree(p);
return;
}
/*
** Return codes for jsonMergePatch()
*/
#define JSON_MERGE_OK 0 /* Success */
#define JSON_MERGE_BADTARGET 1 /* Malformed TARGET blob */
#define JSON_MERGE_BADPATCH 2 /* Malformed PATCH blob */
#define JSON_MERGE_OOM 3 /* Out-of-memory condition */
/*
** RFC-7396 MergePatch for two JSONB blobs.
**
** pTarget is the target. pPatch is the patch. The target is updated
** in place. The patch is read-only.
**
** The original RFC-7396 algorithm is this:
**
** define MergePatch(Target, Patch):
** if Patch is an Object:
** if Target is not an Object:
** Target = {} # Ignore the contents and set it to an empty Object
** for each Name/Value pair in Patch:
** if Value is null:
** if Name exists in Target:
** remove the Name/Value pair from Target
** else:
** Target[Name] = MergePatch(Target[Name], Value)
** return Target
** else:
** return Patch
**
** Here is an equivalent algorithm restructured to show the actual
** implementation:
**
** 01 define MergePatch(Target, Patch):
** 02 if Patch is not an Object:
** 03 return Patch
** 04 else: // if Patch is an Object
** 05 if Target is not an Object:
** 06 Target = {}
** 07 for each Name/Value pair in Patch:
** 08 if Name exists in Target:
** 09 if Value is null:
** 10 remove the Name/Value pair from Target
** 11 else
** 12 Target[name] = MergePatch(Target[Name], Value)
** 13 else if Value is not NULL:
** 14 if Value is not an Object:
** 15 Target[name] = Value
** 16 else:
** 17 Target[name] = MergePatch('{}',value)
** 18 return Target
** |
** ^---- Line numbers referenced in comments in the implementation
*/
static int jsonMergePatch(
JsonParse *pTarget, /* The JSON parser that contains the TARGET */
u32 iTarget, /* Index of TARGET in pTarget->aBlob[] */
const JsonParse *pPatch, /* The PATCH */
u32 iPatch /* Index of PATCH in pPatch->aBlob[] */
){
u8 x; /* Type of a single node */
u32 n, sz=0; /* Return values from jsonbPayloadSize() */
u32 iTCursor; /* Cursor position while scanning the target object */
u32 iTStart; /* First label in the target object */
u32 iTEndBE; /* Original first byte past end of target, before edit */
u32 iTEnd; /* Current first byte past end of target */
u8 eTLabel; /* Node type of the target label */
u32 iTLabel = 0; /* Index of the label */
u32 nTLabel = 0; /* Header size in bytes for the target label */
u32 szTLabel = 0; /* Size of the target label payload */
u32 iTValue = 0; /* Index of the target value */
u32 nTValue = 0; /* Header size of the target value */
u32 szTValue = 0; /* Payload size for the target value */
u32 iPCursor; /* Cursor position while scanning the patch */
u32 iPEnd; /* First byte past the end of the patch */
u8 ePLabel; /* Node type of the patch label */
u32 iPLabel; /* Start of patch label */
u32 nPLabel; /* Size of header on the patch label */
u32 szPLabel; /* Payload size of the patch label */
u32 iPValue; /* Start of patch value */
u32 nPValue; /* Header size for the patch value */
u32 szPValue; /* Payload size of the patch value */
assert( iTarget>=0 && iTarget<pTarget->nBlob );
assert( iPatch>=0 && iPatch<pPatch->nBlob );
x = pPatch->aBlob[iPatch] & 0x0f;
if( x!=JSONB_OBJECT ){ /* Algorithm line 02 */
u32 szPatch; /* Total size of the patch, header+payload */
u32 szTarget; /* Total size of the target, header+payload */
n = jsonbPayloadSize(pPatch, iPatch, &sz);
szPatch = n+sz;
sz = 0;
n = jsonbPayloadSize(pTarget, iTarget, &sz);
szTarget = n+sz;
jsonBlobEdit(pTarget, iTarget, szTarget, pPatch->aBlob+iPatch, szPatch);
return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK; /* Line 03 */
}
x = pTarget->aBlob[iTarget] & 0x0f;
if( x!=JSONB_OBJECT ){ /* Algorithm line 05 */
n = jsonbPayloadSize(pTarget, iTarget, &sz);
jsonBlobEdit(pTarget, iTarget+n, sz, 0, 0);
x = pTarget->aBlob[iTarget];
pTarget->aBlob[iTarget] = (x & 0xf0) | JSONB_OBJECT;
}
n = jsonbPayloadSize(pPatch, iPatch, &sz);
if( NEVER(n==0) ) return JSON_MERGE_BADPATCH;
iPCursor = iPatch+n;
iPEnd = iPCursor+sz;
n = jsonbPayloadSize(pTarget, iTarget, &sz);
if( NEVER(n==0) ) return JSON_MERGE_BADTARGET;
iTStart = iTarget+n;
iTEndBE = iTStart+sz;
while( iPCursor<iPEnd ){ /* Algorithm line 07 */
iPLabel = iPCursor;
ePLabel = pPatch->aBlob[iPCursor] & 0x0f;
if( ePLabel<JSONB_TEXT || ePLabel>JSONB_TEXTRAW ){
return JSON_MERGE_BADPATCH;
}
nPLabel = jsonbPayloadSize(pPatch, iPCursor, &szPLabel);
if( nPLabel==0 ) return JSON_MERGE_BADPATCH;
iPValue = iPCursor + nPLabel + szPLabel;
if( iPValue>=iPEnd ) return JSON_MERGE_BADPATCH;
nPValue = jsonbPayloadSize(pPatch, iPValue, &szPValue);
if( nPValue==0 ) return JSON_MERGE_BADPATCH;
iPCursor = iPValue + nPValue + szPValue;
if( iPCursor>iPEnd ) return JSON_MERGE_BADPATCH;
iTCursor = iTStart;
iTEnd = iTEndBE + pTarget->delta;
while( iTCursor<iTEnd ){
int isEqual; /* true if the patch and target labels match */
iTLabel = iTCursor;
eTLabel = pTarget->aBlob[iTCursor] & 0x0f;
if( eTLabel<JSONB_TEXT || eTLabel>JSONB_TEXTRAW ){
return JSON_MERGE_BADTARGET;
}
nTLabel = jsonbPayloadSize(pTarget, iTCursor, &szTLabel);
if( nTLabel==0 ) return JSON_MERGE_BADTARGET;
iTValue = iTLabel + nTLabel + szTLabel;
if( iTValue>=iTEnd ) return JSON_MERGE_BADTARGET;
nTValue = jsonbPayloadSize(pTarget, iTValue, &szTValue);
if( nTValue==0 ) return JSON_MERGE_BADTARGET;
if( iTValue + nTValue + szTValue > iTEnd ) return JSON_MERGE_BADTARGET;
isEqual = jsonLabelCompare(
(const char*)&pPatch->aBlob[iPLabel+nPLabel],
szPLabel,
(ePLabel==JSONB_TEXT || ePLabel==JSONB_TEXTRAW),
(const char*)&pTarget->aBlob[iTLabel+nTLabel],
szTLabel,
(eTLabel==JSONB_TEXT || eTLabel==JSONB_TEXTRAW));
if( isEqual ) break;
iTCursor = iTValue + nTValue + szTValue;
}
x = pPatch->aBlob[iPValue] & 0x0f;
if( iTCursor<iTEnd ){
/* A match was found. Algorithm line 08 */
if( x==0 ){
/* Patch value is NULL. Algorithm line 09 */
jsonBlobEdit(pTarget, iTLabel, nTLabel+szTLabel+nTValue+szTValue, 0,0);
/* vvvvvv----- No OOM on a delete-only edit */
if( NEVER(pTarget->oom) ) return JSON_MERGE_OOM;
}else{
/* Algorithm line 12 */
int rc, savedDelta = pTarget->delta;
pTarget->delta = 0;
rc = jsonMergePatch(pTarget, iTValue, pPatch, iPValue);
if( rc ) return rc;
pTarget->delta += savedDelta;
}
}else if( x>0 ){ /* Algorithm line 13 */
/* No match and patch value is not NULL */
u32 szNew = szPLabel+nPLabel;
if( (pPatch->aBlob[iPValue] & 0x0f)!=JSONB_OBJECT ){ /* Line 14 */
jsonBlobEdit(pTarget, iTEnd, 0, 0, szPValue+nPValue+szNew);
if( pTarget->oom ) return JSON_MERGE_OOM;
memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew);
memcpy(&pTarget->aBlob[iTEnd+szNew],
&pPatch->aBlob[iPValue], szPValue+nPValue);
}else{
int rc, savedDelta;
jsonBlobEdit(pTarget, iTEnd, 0, 0, szNew+1);
if( pTarget->oom ) return JSON_MERGE_OOM;
memcpy(&pTarget->aBlob[iTEnd], &pPatch->aBlob[iPLabel], szNew);
pTarget->aBlob[iTEnd+szNew] = 0x00;
savedDelta = pTarget->delta;
pTarget->delta = 0;
rc = jsonMergePatch(pTarget, iTEnd+szNew,pPatch,iPValue);
if( rc ) return rc;
pTarget->delta += savedDelta;
}
}
}
if( pTarget->delta ) jsonAfterEditSizeAdjust(pTarget, iTarget);
return pTarget->oom ? JSON_MERGE_OOM : JSON_MERGE_OK;
}
/*
** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
** object that is the result of running the RFC 7396 MergePatch() algorithm
** on the two arguments.
*/
static void jsonPatchFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *pTarget; /* The TARGET */
JsonParse *pPatch; /* The PATCH */
int rc; /* Result code */
UNUSED_PARAMETER(argc);
assert( argc==2 );
pTarget = jsonParseFuncArg(ctx, argv[0], JSON_EDITABLE);
if( pTarget==0 ) return;
pPatch = jsonParseFuncArg(ctx, argv[1], 0);
if( pPatch ){
rc = jsonMergePatch(pTarget, 0, pPatch, 0);
if( rc==JSON_MERGE_OK ){
jsonReturnParse(ctx, pTarget);
}else if( rc==JSON_MERGE_OOM ){
sqlite3_result_error_nomem(ctx);
}else{
sqlite3_result_error(ctx, "malformed JSON", -1);
}
jsonParseFree(pPatch);
}
jsonParseFree(pTarget);
}
/*
** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
** object that contains all name/value given in arguments. Or if any name
** is not a string or if any value is a BLOB, throw an error.
|
| ︙ | ︙ | |||
205377 205378 205379 205380 205381 205382 205383 |
u32 n;
if( argc&1 ){
sqlite3_result_error(ctx, "json_object() requires an even number "
"of arguments", -1);
return;
}
| | | | | | | < | > | | | | | < | < < < < < | | | > > | < | | < < < < < < | < < | | < < < < < | < < < < | | < < < < | < < < < < < < < < | < < < | < | < < < < < | | < < < < < < < < < < | | < < < | < < | | | < < < < | < | | < < | < < | < < < < < < < | < < < < < < < < < < < < < < < | < < < | | | < < < < < < < < < < < < < < < < < < < < | | | > > > > > | > > > > > | < > | < | | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > | > > > > > > > > | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > | > > | | > > > > > | | | > | | > > | < < < < > | < | < > | < | < < < < < | < < < < > | > > < | | | | > | > > | > > > | < > | < > | | | > > > > > > | < | > | | | | > > | > > > > | | > > > > | 206937 206938 206939 206940 206941 206942 206943 206944 206945 206946 206947 206948 206949 206950 206951 206952 206953 206954 206955 206956 206957 206958 206959 206960 206961 206962 206963 206964 206965 206966 206967 206968 206969 206970 206971 206972 206973 206974 206975 206976 206977 206978 206979 206980 206981 206982 206983 206984 206985 206986 206987 206988 206989 206990 206991 206992 206993 206994 206995 206996 206997 206998 206999 207000 207001 207002 207003 207004 207005 207006 207007 207008 207009 207010 207011 207012 207013 207014 207015 207016 207017 207018 207019 207020 207021 207022 207023 207024 207025 207026 207027 207028 207029 207030 207031 207032 207033 207034 207035 207036 207037 207038 207039 207040 207041 207042 207043 207044 207045 207046 207047 207048 207049 207050 207051 207052 207053 207054 207055 207056 207057 207058 207059 207060 207061 207062 207063 207064 207065 207066 207067 207068 207069 207070 207071 207072 207073 207074 207075 207076 207077 207078 207079 207080 207081 207082 207083 207084 207085 207086 207087 207088 207089 207090 207091 207092 207093 207094 207095 207096 207097 207098 207099 207100 207101 207102 207103 207104 207105 207106 207107 207108 207109 207110 207111 207112 207113 207114 207115 207116 207117 207118 207119 207120 207121 207122 207123 207124 207125 207126 207127 207128 207129 207130 207131 207132 207133 207134 207135 207136 207137 207138 207139 207140 207141 207142 207143 207144 207145 207146 207147 207148 207149 207150 207151 207152 207153 207154 207155 207156 207157 207158 207159 207160 207161 207162 207163 207164 207165 207166 207167 207168 207169 207170 207171 207172 207173 207174 207175 207176 207177 207178 207179 207180 207181 207182 207183 207184 207185 207186 207187 207188 207189 207190 207191 207192 207193 207194 207195 207196 207197 207198 207199 207200 207201 207202 207203 207204 207205 207206 207207 207208 207209 207210 207211 207212 207213 207214 207215 207216 207217 207218 207219 207220 207221 207222 207223 207224 207225 207226 207227 207228 207229 207230 207231 207232 207233 207234 207235 207236 207237 207238 207239 207240 207241 207242 207243 207244 207245 207246 207247 207248 207249 207250 207251 207252 207253 207254 207255 207256 207257 207258 207259 207260 207261 207262 207263 207264 207265 207266 207267 207268 207269 207270 207271 207272 207273 207274 207275 207276 207277 207278 207279 207280 207281 207282 207283 207284 207285 207286 207287 207288 207289 207290 207291 207292 207293 207294 207295 207296 207297 207298 207299 207300 207301 207302 207303 207304 207305 207306 207307 207308 207309 207310 207311 207312 207313 207314 207315 207316 207317 207318 207319 207320 207321 207322 207323 207324 207325 207326 207327 207328 207329 207330 207331 207332 207333 207334 207335 207336 207337 207338 207339 207340 207341 207342 207343 207344 207345 207346 207347 207348 |
u32 n;
if( argc&1 ){
sqlite3_result_error(ctx, "json_object() requires an even number "
"of arguments", -1);
return;
}
jsonStringInit(&jx, ctx);
jsonAppendChar(&jx, '{');
for(i=0; i<argc; i+=2){
if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
jsonStringReset(&jx);
return;
}
jsonAppendSeparator(&jx);
z = (const char*)sqlite3_value_text(argv[i]);
n = sqlite3_value_bytes(argv[i]);
jsonAppendString(&jx, z, n);
jsonAppendChar(&jx, ':');
jsonAppendSqlValue(&jx, argv[i+1]);
}
jsonAppendChar(&jx, '}');
jsonReturnString(&jx, 0, 0);
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
/*
** json_remove(JSON, PATH, ...)
**
** Remove the named elements from JSON and return the result. malformed
** JSON or PATH arguments result in an error.
*/
static void jsonRemoveFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
const char *zPath = 0; /* Path of element to be removed */
int i; /* Loop counter */
u32 rc; /* Subroutine return code */
if( argc<1 ) return;
p = jsonParseFuncArg(ctx, argv[0], argc>1 ? JSON_EDITABLE : 0);
if( p==0 ) return;
for(i=1; i<argc; i++){
zPath = (const char*)sqlite3_value_text(argv[i]);
if( zPath==0 ){
goto json_remove_done;
}
if( zPath[0]!='$' ){
goto json_remove_patherror;
}
if( zPath[1]==0 ){
/* json_remove(j,'$') returns NULL */
goto json_remove_done;
}
p->eEdit = JEDIT_DEL;
p->delta = 0;
rc = jsonLookupStep(p, 0, zPath+1, 0);
if( JSON_LOOKUP_ISERROR(rc) ){
if( rc==JSON_LOOKUP_NOTFOUND ){
continue; /* No-op */
}else if( rc==JSON_LOOKUP_PATHERROR ){
jsonBadPathError(ctx, zPath);
}else{
sqlite3_result_error(ctx, "malformed JSON", -1);
}
goto json_remove_done;
}
}
jsonReturnParse(ctx, p);
jsonParseFree(p);
return;
json_remove_patherror:
jsonBadPathError(ctx, zPath);
json_remove_done:
jsonParseFree(p);
return;
}
/*
** json_replace(JSON, PATH, VALUE, ...)
**
** Replace the value at PATH with VALUE. If PATH does not already exist,
** this routine is a no-op. If JSON or PATH is malformed, throw an error.
*/
static void jsonReplaceFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
if( argc<1 ) return;
if( (argc&1)==0 ) {
jsonWrongNumArgs(ctx, "replace");
return;
}
jsonInsertIntoBlob(ctx, argc, argv, JEDIT_REPL);
}
/*
** json_set(JSON, PATH, VALUE, ...)
**
** Set the value at PATH to VALUE. Create the PATH if it does not already
** exist. Overwrite existing values that do exist.
** If JSON or PATH is malformed, throw an error.
**
** json_insert(JSON, PATH, VALUE, ...)
**
** Create PATH and initialize it to VALUE. If PATH already exists, this
** routine is a no-op. If JSON or PATH is malformed, throw an error.
*/
static void jsonSetFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
int bIsSet = (flags&JSON_ISSET)!=0;
if( argc<1 ) return;
if( (argc&1)==0 ) {
jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
return;
}
jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS);
}
/*
** json_type(JSON)
** json_type(JSON, PATH)
**
** Return the top-level "type" of a JSON string. json_type() raises an
** error if either the JSON or PATH inputs are not well-formed.
*/
static void jsonTypeFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
const char *zPath = 0;
u32 i;
p = jsonParseFuncArg(ctx, argv[0], 0);
if( p==0 ) return;
if( argc==2 ){
zPath = (const char*)sqlite3_value_text(argv[1]);
if( zPath==0 ) goto json_type_done;
if( zPath[0]!='$' ){
jsonBadPathError(ctx, zPath);
goto json_type_done;
}
i = jsonLookupStep(p, 0, zPath+1, 0);
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
/* no-op */
}else if( i==JSON_LOOKUP_PATHERROR ){
jsonBadPathError(ctx, zPath);
}else{
sqlite3_result_error(ctx, "malformed JSON", -1);
}
goto json_type_done;
}
}else{
i = 0;
}
sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC);
json_type_done:
jsonParseFree(p);
}
/*
** json_valid(JSON)
** json_valid(JSON, FLAGS)
**
** Check the JSON argument to see if it is well-formed. The FLAGS argument
** encodes the various constraints on what is meant by "well-formed":
**
** 0x01 Canonical RFC-8259 JSON text
** 0x02 JSON text with optional JSON-5 extensions
** 0x04 Superficially appears to be JSONB
** 0x08 Strictly well-formed JSONB
**
** If the FLAGS argument is omitted, it defaults to 1. Useful values for
** FLAGS include:
**
** 1 Strict canonical JSON text
** 2 JSON text perhaps with JSON-5 extensions
** 4 Superficially appears to be JSONB
** 5 Canonical JSON text or superficial JSONB
** 6 JSON-5 text or superficial JSONB
** 8 Strict JSONB
** 9 Canonical JSON text or strict JSONB
** 10 JSON-5 text or strict JSONB
**
** Other flag combinations are redundant. For example, every canonical
** JSON text is also well-formed JSON-5 text, so FLAG values 2 and 3
** are the same. Similarly, any input that passes a strict JSONB validation
** will also pass the superficial validation so 12 through 15 are the same
** as 8 through 11 respectively.
**
** This routine runs in linear time to validate text and when doing strict
** JSONB validation. Superficial JSONB validation is constant time,
** assuming the BLOB is already in memory. The performance advantage
** of superficial JSONB validation is why that option is provided.
** Application developers can choose to do fast superficial validation or
** slower strict validation, according to their specific needs.
**
** Only the lower four bits of the FLAGS argument are currently used.
** Higher bits are reserved for future expansion. To facilitate
** compatibility, the current implementation raises an error if any bit
** in FLAGS is set other than the lower four bits.
**
** The original circa 2015 implementation of the JSON routines in
** SQLite only supported canonical RFC-8259 JSON text and the json_valid()
** function only accepted one argument. That is why the default value
** for the FLAGS argument is 1, since FLAGS=1 causes this routine to only
** recognize canonical RFC-8259 JSON text as valid. The extra FLAGS
** argument was added when the JSON routines were extended to support
** JSON5-like extensions and binary JSONB stored in BLOBs.
**
** Return Values:
**
** * Raise an error if FLAGS is outside the range of 1 to 15.
** * Return NULL if the input is NULL
** * Return 1 if the input is well-formed.
** * Return 0 if the input is not well-formed.
*/
static void jsonValidFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
u8 flags = 1;
u8 res = 0;
if( argc==2 ){
i64 f = sqlite3_value_int64(argv[1]);
if( f<1 || f>15 ){
sqlite3_result_error(ctx, "FLAGS parameter to json_valid() must be"
" between 1 and 15", -1);
return;
}
flags = f & 0x0f;
}
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_NULL: {
#ifdef SQLITE_LEGACY_JSON_VALID
/* Incorrect legacy behavior was to return FALSE for a NULL input */
sqlite3_result_int(ctx, 0);
#endif
return;
}
case SQLITE_BLOB: {
if( (flags & 0x0c)!=0 && jsonFuncArgMightBeBinary(argv[0]) ){
if( flags & 0x04 ){
/* Superficial checking only - accomplished by the
** jsonFuncArgMightBeBinary() call above. */
res = 1;
}else{
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
** no errors occur, call that a "strict check". */
JsonParse px;
u32 iErr;
memset(&px, 0, sizeof(px));
px.aBlob = (u8*)sqlite3_value_blob(argv[0]);
px.nBlob = sqlite3_value_bytes(argv[0]);
iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
res = iErr==0;
}
}
break;
}
default: {
JsonParse px;
if( (flags & 0x3)==0 ) break;
memset(&px, 0, sizeof(px));
p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR);
if( p ){
if( p->oom ){
sqlite3_result_error_nomem(ctx);
}else if( p->nErr ){
/* no-op */
}else if( (flags & 0x02)!=0 || p->hasNonstd==0 ){
res = 1;
}
jsonParseFree(p);
}else{
sqlite3_result_error_nomem(ctx);
}
break;
}
}
sqlite3_result_int(ctx, res);
}
/*
** json_error_position(JSON)
**
** If the argument is NULL, return NULL
**
** If the argument is BLOB, do a full validity check and return non-zero
** if the check fails. The return value is the approximate 1-based offset
** to the byte of the element that contains the first error.
**
** Otherwise interpret the argument is TEXT (even if it is numeric) and
** return the 1-based character position for where the parser first recognized
** that the input was not valid JSON, or return 0 if the input text looks
** ok. JSON-5 extensions are accepted.
*/
static void jsonErrorFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
i64 iErrPos = 0; /* Error position to be returned */
JsonParse s;
assert( argc==1 );
UNUSED_PARAMETER(argc);
memset(&s, 0, sizeof(s));
if( jsonFuncArgMightBeBinary(argv[0]) ){
s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
s.nBlob = sqlite3_value_bytes(argv[0]);
iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
}else{
s.zJson = (char*)sqlite3_value_text(argv[0]);
if( s.zJson==0 ) return; /* NULL input or OOM */
s.nJson = sqlite3_value_bytes(argv[0]);
if( jsonConvertTextToBlob(&s,0) ){
if( s.oom ){
iErrPos = -1;
}else{
/* Convert byte-offset s.iErr into a character offset */
u32 k;
assert( s.zJson!=0 ); /* Because s.oom is false */
for(k=0; k<s.iErr && ALWAYS(s.zJson[k]); k++){
if( (s.zJson[k] & 0xc0)!=0x80 ) iErrPos++;
}
iErrPos++;
}
}
}
jsonParseReset(&s);
if( iErrPos<0 ){
sqlite3_result_error_nomem(ctx);
}else{
sqlite3_result_int64(ctx, iErrPos);
}
}
/****************************************************************************
** Aggregate SQL function implementations
****************************************************************************/
/*
** json_group_array(VALUE)
**
** Return a JSON array composed of all values in the aggregate.
*/
static void jsonArrayStep(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonString *pStr;
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '[');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
jsonAppendSqlValue(pStr, argv[0]);
}
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
int flags;
pStr->pCtx = ctx;
jsonAppendChar(pStr, ']');
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
}else if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(pStr);
if( isFinal ){
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
}else{
pStr->nUsed--;
}
return;
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
pStr->bStatic ? SQLITE_TRANSIENT :
sqlite3RCStrUnref);
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
| ︙ | ︙ | |||
205855 205856 205857 205858 205859 205860 205861 |
JsonString *pStr;
const char *z;
u32 n;
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
| | | | > > > | > > > > | | > > > > | 207423 207424 207425 207426 207427 207428 207429 207430 207431 207432 207433 207434 207435 207436 207437 207438 207439 207440 207441 207442 207443 207444 207445 207446 207447 207448 207449 207450 207451 207452 207453 207454 207455 207456 207457 207458 207459 207460 207461 207462 207463 207464 207465 207466 207467 207468 |
JsonString *pStr;
const char *z;
u32 n;
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
z = (const char*)sqlite3_value_text(argv[0]);
n = sqlite3Strlen30(z);
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendSqlValue(pStr, argv[1]);
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
int flags;
jsonAppendChar(pStr, '}');
pStr->pCtx = ctx;
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
}else if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(pStr);
if( isFinal ){
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
}else{
pStr->nUsed--;
}
return;
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
pStr->bStatic ? SQLITE_TRANSIENT :
sqlite3RCStrUnref);
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
| ︙ | ︙ | |||
205903 205904 205905 205906 205907 205908 205909 205910 205911 205912 205913 |
#ifndef SQLITE_OMIT_VIRTUALTABLE
/****************************************************************************
** The json_each virtual table
****************************************************************************/
typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
| > > > > > > > > > < | > | | > > | > > > > > > > | | 207482 207483 207484 207485 207486 207487 207488 207489 207490 207491 207492 207493 207494 207495 207496 207497 207498 207499 207500 207501 207502 207503 207504 207505 207506 207507 207508 207509 207510 207511 207512 207513 207514 207515 207516 207517 207518 207519 207520 207521 207522 207523 207524 207525 207526 207527 207528 207529 207530 207531 207532 207533 207534 207535 207536 |
#ifndef SQLITE_OMIT_VIRTUALTABLE
/****************************************************************************
** The json_each virtual table
****************************************************************************/
typedef struct JsonParent JsonParent;
struct JsonParent {
u32 iHead; /* Start of object or array */
u32 iValue; /* Start of the value */
u32 iEnd; /* First byte past the end */
u32 nPath; /* Length of path */
i64 iKey; /* Key for JSONB_ARRAY */
};
typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
u32 i; /* Index in sParse.aBlob[] of current row */
u32 iEnd; /* EOF when i equals or exceeds this value */
u32 nRoot; /* Size of the root path in bytes */
u8 eType; /* Type of the container for element i */
u8 bRecursive; /* True for json_tree(). False for json_each() */
u32 nParent; /* Current nesting depth */
u32 nParentAlloc; /* Space allocated for aParent[] */
JsonParent *aParent; /* Parent elements of i */
sqlite3 *db; /* Database connection */
JsonString path; /* Current path */
JsonParse sParse; /* Parse of the input JSON */
};
typedef struct JsonEachConnection JsonEachConnection;
struct JsonEachConnection {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
};
/* Constructor for the json_each virtual table */
static int jsonEachConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
JsonEachConnection *pNew;
int rc;
/* Column numbers */
#define JEACH_KEY 0
#define JEACH_VALUE 1
#define JEACH_TYPE 2
#define JEACH_ATOM 3
|
| ︙ | ︙ | |||
205951 205952 205953 205954 205955 205956 205957 |
UNUSED_PARAMETER(argv);
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(pAux);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
"json HIDDEN,root HIDDEN)");
if( rc==SQLITE_OK ){
| | > > > > < > > > > > < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < > > | | | < | > | | > | > | | < | | < < | < < < | | < | > | | | > > < > | < | > < > | > > | | < < < < < < < < | | < < | | < | < < < < < < | > > > > > < > > | > > | < < | > > | < | > > | < > > | > > | | | > > | < < < < < < < < < < < < | > > | < | | > | | | < | | | > | > > > < > > > > > > > | | | | > | | | | > | < | | < < < < < | < < | < < | > | < < < < < < < | | > | | < < < < < < | > > > | | > | 207548 207549 207550 207551 207552 207553 207554 207555 207556 207557 207558 207559 207560 207561 207562 207563 207564 207565 207566 207567 207568 207569 207570 207571 207572 207573 207574 207575 207576 207577 207578 207579 207580 207581 207582 207583 207584 207585 207586 207587 207588 207589 207590 207591 207592 207593 207594 207595 207596 207597 207598 207599 207600 207601 207602 207603 207604 207605 207606 207607 207608 207609 207610 207611 207612 207613 207614 207615 207616 207617 207618 207619 207620 207621 207622 207623 207624 207625 207626 207627 207628 207629 207630 207631 207632 207633 207634 207635 207636 207637 207638 207639 207640 207641 207642 207643 207644 207645 207646 207647 207648 207649 207650 207651 207652 207653 207654 207655 207656 207657 207658 207659 207660 207661 207662 207663 207664 207665 207666 207667 207668 207669 207670 207671 207672 207673 207674 207675 207676 207677 207678 207679 207680 207681 207682 207683 207684 207685 207686 207687 207688 207689 207690 207691 207692 207693 207694 207695 207696 207697 207698 207699 207700 207701 207702 207703 207704 207705 207706 207707 207708 207709 207710 207711 207712 207713 207714 207715 207716 207717 207718 207719 207720 207721 207722 207723 207724 207725 207726 207727 207728 207729 207730 207731 207732 207733 207734 207735 207736 207737 207738 207739 207740 207741 207742 207743 207744 207745 207746 207747 207748 207749 207750 207751 207752 207753 207754 207755 207756 207757 207758 207759 207760 207761 207762 207763 207764 207765 207766 207767 207768 207769 207770 207771 207772 207773 207774 207775 207776 207777 207778 207779 207780 207781 207782 207783 207784 207785 207786 207787 207788 207789 207790 207791 207792 207793 207794 207795 207796 207797 207798 207799 207800 207801 207802 207803 207804 207805 207806 207807 207808 207809 207810 207811 207812 207813 207814 207815 207816 207817 207818 207819 207820 207821 207822 207823 207824 207825 207826 207827 207828 207829 207830 207831 207832 207833 207834 207835 207836 207837 207838 207839 207840 207841 207842 207843 207844 207845 207846 207847 207848 207849 207850 207851 207852 207853 207854 207855 207856 |
UNUSED_PARAMETER(argv);
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(pAux);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
"json HIDDEN,root HIDDEN)");
if( rc==SQLITE_OK ){
pNew = (JsonEachConnection*)(*ppVtab = sqlite3_malloc( sizeof(*pNew) ));
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
pNew->db = db;
}
return rc;
}
/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/* constructor for a JsonEachCursor object for json_each(). */
static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
JsonEachConnection *pVtab = (JsonEachConnection*)p;
JsonEachCursor *pCur;
UNUSED_PARAMETER(p);
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = pVtab->db;
jsonStringZero(&pCur->path);
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/* constructor for a JsonEachCursor object for json_tree(). */
static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
int rc = jsonEachOpenEach(p, ppCursor);
if( rc==SQLITE_OK ){
JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
pCur->bRecursive = 1;
}
return rc;
}
/* Reset a JsonEachCursor back to its original state. Free any memory
** held. */
static void jsonEachCursorReset(JsonEachCursor *p){
jsonParseReset(&p->sParse);
jsonStringReset(&p->path);
sqlite3DbFree(p->db, p->aParent);
p->iRowid = 0;
p->i = 0;
p->aParent = 0;
p->nParent = 0;
p->nParentAlloc = 0;
p->iEnd = 0;
p->eType = 0;
}
/* Destructor for a jsonEachCursor object */
static int jsonEachClose(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
jsonEachCursorReset(p);
sqlite3_free(cur);
return SQLITE_OK;
}
/* Return TRUE if the jsonEachCursor object has been advanced off the end
** of the JSON object */
static int jsonEachEof(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
return p->i >= p->iEnd;
}
/*
** If the cursor is currently pointing at the label of a object entry,
** then return the index of the value. For all other cases, return the
** current pointer position, which is the value.
*/
static int jsonSkipLabel(JsonEachCursor *p){
if( p->eType==JSONB_OBJECT ){
u32 sz = 0;
u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz);
return p->i + n + sz;
}else{
return p->i;
}
}
/*
** Append the path name for the current element.
*/
static void jsonAppendPathName(JsonEachCursor *p){
assert( p->nParent>0 );
assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT );
if( p->eType==JSONB_ARRAY ){
jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey);
}else{
u32 n, sz = 0, k, i;
const char *z;
int needQuote = 0;
n = jsonbPayloadSize(&p->sParse, p->i, &sz);
k = p->i + n;
z = (const char*)&p->sParse.aBlob[k];
if( sz==0 || !sqlite3Isalpha(z[0]) ){
needQuote = 1;
}else{
for(i=0; i<sz; i++){
if( !sqlite3Isalnum(z[i]) ){
needQuote = 1;
break;
}
}
}
if( needQuote ){
jsonPrintf(sz+4,&p->path,".\"%.*s\"", sz, z);
}else{
jsonPrintf(sz+2,&p->path,".%.*s", sz, z);
}
}
}
/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
int rc = SQLITE_OK;
if( p->bRecursive ){
u8 x;
u8 levelChange = 0;
u32 n, sz = 0;
u32 i = jsonSkipLabel(p);
x = p->sParse.aBlob[i] & 0x0f;
n = jsonbPayloadSize(&p->sParse, i, &sz);
if( x==JSONB_OBJECT || x==JSONB_ARRAY ){
JsonParent *pParent;
if( p->nParent>=p->nParentAlloc ){
JsonParent *pNew;
u64 nNew;
nNew = p->nParentAlloc*2 + 3;
pNew = sqlite3DbRealloc(p->db, p->aParent, sizeof(JsonParent)*nNew);
if( pNew==0 ) return SQLITE_NOMEM;
p->nParentAlloc = (u32)nNew;
p->aParent = pNew;
}
levelChange = 1;
pParent = &p->aParent[p->nParent];
pParent->iHead = p->i;
pParent->iValue = i;
pParent->iEnd = i + n + sz;
pParent->iKey = -1;
pParent->nPath = (u32)p->path.nUsed;
if( p->eType && p->nParent ){
jsonAppendPathName(p);
if( p->path.eErr ) rc = SQLITE_NOMEM;
}
p->nParent++;
p->i = i + n;
}else{
p->i = i + n + sz;
}
while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){
p->nParent--;
p->path.nUsed = p->aParent[p->nParent].nPath;
levelChange = 1;
}
if( levelChange ){
if( p->nParent>0 ){
JsonParent *pParent = &p->aParent[p->nParent-1];
u32 iVal = pParent->iValue;
p->eType = p->sParse.aBlob[iVal] & 0x0f;
}else{
p->eType = 0;
}
}
}else{
u32 n, sz = 0;
u32 i = jsonSkipLabel(p);
n = jsonbPayloadSize(&p->sParse, i, &sz);
p->i = i + n + sz;
}
if( p->eType==JSONB_ARRAY && p->nParent ){
p->aParent[p->nParent-1].iKey++;
}
p->iRowid++;
return rc;
}
/* Length of the path for rowid==0 in bRecursive mode.
*/
static int jsonEachPathLength(JsonEachCursor *p){
u32 n = p->path.nUsed;
char *z = p->path.zBuf;
if( p->iRowid==0 && p->bRecursive && n>=2 ){
while( n>1 ){
n--;
if( z[n]=='[' || z[n]=='.' ){
u32 x, sz = 0;
char cSaved = z[n];
z[n] = 0;
assert( p->sParse.eEdit==0 );
x = jsonLookupStep(&p->sParse, 0, z+1, 0);
z[n] = cSaved;
if( JSON_LOOKUP_ISERROR(x) ) continue;
if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break;
}
}
}
return n;
}
/* Return the value of a column */
static int jsonEachColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int iColumn /* Which column to return */
){
JsonEachCursor *p = (JsonEachCursor*)cur;
switch( iColumn ){
case JEACH_KEY: {
if( p->nParent==0 ){
u32 n, j;
if( p->nRoot==1 ) break;
j = jsonEachPathLength(p);
n = p->nRoot - j;
if( n==0 ){
break;
}else if( p->path.zBuf[j]=='[' ){
i64 x;
sqlite3Atoi64(&p->path.zBuf[j+1], &x, n-1, SQLITE_UTF8);
sqlite3_result_int64(ctx, x);
}else if( p->path.zBuf[j+1]=='"' ){
sqlite3_result_text(ctx, &p->path.zBuf[j+2], n-3, SQLITE_TRANSIENT);
}else{
sqlite3_result_text(ctx, &p->path.zBuf[j+1], n-1, SQLITE_TRANSIENT);
}
break;
}
if( p->eType==JSONB_OBJECT ){
jsonReturnFromBlob(&p->sParse, p->i, ctx, 1);
}else{
assert( p->eType==JSONB_ARRAY );
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
}
break;
}
case JEACH_VALUE: {
u32 i = jsonSkipLabel(p);
jsonReturnFromBlob(&p->sParse, i, ctx, 1);
break;
}
case JEACH_TYPE: {
u32 i = jsonSkipLabel(p);
u8 eType = p->sParse.aBlob[i] & 0x0f;
sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC);
break;
}
case JEACH_ATOM: {
u32 i = jsonSkipLabel(p);
if( (p->sParse.aBlob[i] & 0x0f)<JSONB_ARRAY ){
jsonReturnFromBlob(&p->sParse, i, ctx, 1);
}
break;
}
case JEACH_ID: {
sqlite3_result_int64(ctx, (sqlite3_int64)p->i);
break;
}
case JEACH_PARENT: {
if( p->nParent>0 && p->bRecursive ){
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead);
}
break;
}
case JEACH_FULLKEY: {
u64 nBase = p->path.nUsed;
if( p->nParent ) jsonAppendPathName(p);
sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
SQLITE_TRANSIENT, SQLITE_UTF8);
p->path.nUsed = nBase;
break;
}
case JEACH_PATH: {
u32 n = jsonEachPathLength(p);
sqlite3_result_text64(ctx, p->path.zBuf, n,
SQLITE_TRANSIENT, SQLITE_UTF8);
break;
}
default: {
sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC);
break;
}
case JEACH_JSON: {
if( p->sParse.zJson==0 ){
sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
SQLITE_STATIC);
}else{
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
}
break;
}
}
return SQLITE_OK;
}
/* Return the current rowid value */
|
| ︙ | ︙ | |||
206299 206300 206301 206302 206303 206304 206305 |
/* Start a search on a new JSON string */
static int jsonEachFilter(
sqlite3_vtab_cursor *cur,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
JsonEachCursor *p = (JsonEachCursor*)cur;
| < | < < | > | > | > > > > | < | | > | < < | < | < < | | | < < < < < < > > | < | | > | | > | > | | | > | | > > > > > > | < | < < > > > | | > | < < < < < < < < < < < | > | | > > > | | > | > > > > > > > > > > > | > | > > > > | | 207933 207934 207935 207936 207937 207938 207939 207940 207941 207942 207943 207944 207945 207946 207947 207948 207949 207950 207951 207952 207953 207954 207955 207956 207957 207958 207959 207960 207961 207962 207963 207964 207965 207966 207967 207968 207969 207970 207971 207972 207973 207974 207975 207976 207977 207978 207979 207980 207981 207982 207983 207984 207985 207986 207987 207988 207989 207990 207991 207992 207993 207994 207995 207996 207997 207998 207999 208000 208001 208002 208003 208004 208005 208006 208007 208008 208009 208010 208011 208012 208013 208014 208015 208016 208017 208018 208019 208020 208021 208022 208023 208024 208025 208026 208027 208028 208029 208030 208031 208032 208033 208034 208035 208036 208037 208038 208039 208040 |
/* Start a search on a new JSON string */
static int jsonEachFilter(
sqlite3_vtab_cursor *cur,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
JsonEachCursor *p = (JsonEachCursor*)cur;
const char *zRoot = 0;
u32 i, n, sz;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(argc);
jsonEachCursorReset(p);
if( idxNum==0 ) return SQLITE_OK;
memset(&p->sParse, 0, sizeof(p->sParse));
p->sParse.nJPRef = 1;
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
if( jsonFuncArgMightBeBinary(argv[0]) ){
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
}else{
goto json_each_malformed_input;
}
}else{
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
if( p->sParse.zJson==0 ){
p->i = p->iEnd = 0;
return SQLITE_OK;
}
if( jsonConvertTextToBlob(&p->sParse, 0) ){
if( p->sParse.oom ){
return SQLITE_NOMEM;
}
goto json_each_malformed_input;
}
}
if( idxNum==3 ){
zRoot = (const char*)sqlite3_value_text(argv[1]);
if( zRoot==0 ) return SQLITE_OK;
if( zRoot[0]!='$' ){
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
p->nRoot = sqlite3Strlen30(zRoot);
if( zRoot[1]==0 ){
i = p->i = 0;
p->eType = 0;
}else{
i = jsonLookupStep(&p->sParse, 0, zRoot+1, 0);
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
p->i = 0;
p->eType = 0;
p->iEnd = 0;
return SQLITE_OK;
}
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
if( p->sParse.iLabel ){
p->i = p->sParse.iLabel;
p->eType = JSONB_OBJECT;
}else{
p->i = i;
p->eType = JSONB_ARRAY;
}
}
jsonAppendRaw(&p->path, zRoot, p->nRoot);
}else{
i = p->i = 0;
p->eType = 0;
p->nRoot = 1;
jsonAppendRaw(&p->path, "$", 1);
}
p->nParent = 0;
n = jsonbPayloadSize(&p->sParse, i, &sz);
p->iEnd = i+n+sz;
if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){
p->i = i + n;
p->eType = p->sParse.aBlob[i] & 0x0f;
p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent));
if( p->aParent==0 ) return SQLITE_NOMEM;
p->nParent = 1;
p->nParentAlloc = 1;
p->aParent[0].iKey = 0;
p->aParent[0].iEnd = p->iEnd;
p->aParent[0].iHead = p->i;
p->aParent[0].iValue = i;
}
return SQLITE_OK;
json_each_malformed_input:
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
/* The methods of the json_each virtual table */
static sqlite3_module jsonEachModule = {
0, /* iVersion */
0, /* xCreate */
jsonEachConnect, /* xConnect */
|
| ︙ | ︙ | |||
206447 206448 206449 206450 206451 206452 206453 |
/*
** Register JSON functions.
*/
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
static FuncDef aJsonFunc[] = {
| | | | | | | < | > | > | | | | > | | | > | > | > | | > | > | > | | | > | | < > > > > > > | 208095 208096 208097 208098 208099 208100 208101 208102 208103 208104 208105 208106 208107 208108 208109 208110 208111 208112 208113 208114 208115 208116 208117 208118 208119 208120 208121 208122 208123 208124 208125 208126 208127 208128 208129 208130 208131 208132 208133 208134 208135 208136 208137 208138 208139 208140 208141 208142 208143 208144 208145 208146 208147 208148 208149 208150 208151 208152 208153 208154 208155 208156 |
/*
** Register JSON functions.
*/
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
static FuncDef aJsonFunc[] = {
/* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */
/* | | */
/* Uses cache ------, | | ,---- Returns JSONB */
/* | | | | */
/* Number of arguments ---, | | | | ,--- Flags */
/* | | | | | | */
JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc),
JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc),
JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc),
JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc),
JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc),
JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc),
JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc),
JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc),
JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc),
JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc),
JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc),
JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc),
JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc),
JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc),
JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc),
JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc),
JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc),
JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc),
JFUNCTION(json_valid, 2,1,0, 0,0,0, jsonValidFunc),
#if SQLITE_DEBUG
JFUNCTION(json_parse, 1,1,0, 0,0,0, jsonParseFunc),
#endif
WAGGREGATE(json_group_array, 1, 0, 0,
jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|
SQLITE_DETERMINISTIC),
WAGGREGATE(jsonb_group_array, 1, JSON_BLOB, 0,
jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC),
WAGGREGATE(json_group_object, 2, 0, 0,
jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC),
WAGGREGATE(jsonb_group_object,2, JSON_BLOB, 0,
jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|
SQLITE_DETERMINISTIC)
};
sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
#endif
}
|
| ︙ | ︙ | |||
227776 227777 227778 227779 227780 227781 227782 227783 227784 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
| > > > > > > > > > > > > > > > > > > > > > > > > > | | 229438 229439 229440 229441 229442 229443 229444 229445 229446 229447 229448 229449 229450 229451 229452 229453 229454 229455 229456 229457 229458 229459 229460 229461 229462 229463 229464 229465 229466 229467 229468 229469 229470 229471 229472 229473 229474 229475 229476 229477 229478 229479 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
**
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase iPhrase of the current
** query. Before returning, output parameter *ppToken is set to point
** to a buffer containing the requested token, and *pnToken to the
** size of this buffer in bytes.
**
** The output text is not a copy of the query text that specified the
** token. It is the output of the tokenizer module. For tokendata=1
** tables, this includes any embedded 0x00 and trailing data.
**
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase hit iIdx within the
** current row. Output variable (*ppToken) is set to point to a buffer
** containing the matching document token, and (*pnToken) to the size
** of that buffer in bytes. This API is not available if the specified
** token matches a prefix query term. In that case both output variables
** are always set to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 3 */
void *(*xUserData)(Fts5Context*);
int (*xColumnCount)(Fts5Context*);
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
| ︙ | ︙ | |||
227813 227814 227815 227816 227817 227818 227819 227820 227821 227822 227823 227824 227825 227826 | void *(*xGetAuxdata)(Fts5Context*, int bClear); int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); }; /* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* | > > > > > > > | 229500 229501 229502 229503 229504 229505 229506 229507 229508 229509 229510 229511 229512 229513 229514 229515 229516 229517 229518 229519 229520 |
void *(*xGetAuxdata)(Fts5Context*, int bClear);
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
/* Below this point are iVersion>=3 only */
int (*xQueryToken)(Fts5Context*,
int iPhrase, int iToken,
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
|
| ︙ | ︙ | |||
228287 228288 228289 228290 228291 228292 228293 228294 228295 228296 228297 228298 228299 228300 | int nPrefix; /* Number of prefix indexes */ int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ int eContent; /* An FTS5_CONTENT value */ int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */ char *zContent; /* content table */ char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ int eDetail; /* FTS5_DETAIL_XXX value */ char *zContentExprlist; Fts5Tokenizer *pTok; fts5_tokenizer *pTokApi; int bLock; /* True when table is preparing statement */ int ePattern; /* FTS_PATTERN_XXX constant */ | > | 229981 229982 229983 229984 229985 229986 229987 229988 229989 229990 229991 229992 229993 229994 229995 | int nPrefix; /* Number of prefix indexes */ int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ int eContent; /* An FTS5_CONTENT value */ int bContentlessDelete; /* "contentless_delete=" option (dflt==0) */ char *zContent; /* content table */ char *zContentRowid; /* "content_rowid=" option value */ int bColumnsize; /* "columnsize=" option value (dflt==1) */ int bTokendata; /* "tokendata=" option value (dflt==0) */ int eDetail; /* FTS5_DETAIL_XXX value */ char *zContentExprlist; Fts5Tokenizer *pTok; fts5_tokenizer *pTokApi; int bLock; /* True when table is preparing statement */ int ePattern; /* FTS_PATTERN_XXX constant */ |
| ︙ | ︙ | |||
228475 228476 228477 228478 228479 228480 228481 | }; #define sqlite3Fts5IterEof(x) ((x)->bEof) /* ** Values used as part of the flags argument passed to IndexQuery(). */ | | | | | | | | > > | 230170 230171 230172 230173 230174 230175 230176 230177 230178 230179 230180 230181 230182 230183 230184 230185 230186 230187 230188 230189 230190 230191 230192 230193 230194 230195 230196 | }; #define sqlite3Fts5IterEof(x) ((x)->bEof) /* ** Values used as part of the flags argument passed to IndexQuery(). */ #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ /* The following are used internally by the fts5_index.c module. They are ** defined here only to make it easier to avoid clashes with the flags ** above. */ #define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 #define FTS5INDEX_QUERY_NOOUTPUT 0x0020 #define FTS5INDEX_QUERY_SKIPHASH 0x0040 #define FTS5INDEX_QUERY_NOTOKENDATA 0x0080 #define FTS5INDEX_QUERY_SCANONETERM 0x0100 /* ** Create/destroy an Fts5Index object. */ static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); static int sqlite3Fts5IndexClose(Fts5Index *p); |
| ︙ | ︙ | |||
228554 228555 228556 228557 228558 228559 228560 228561 228562 228563 228564 228565 228566 228567 | */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); static int sqlite3Fts5IterNextScan(Fts5IndexIter*); static void *sqlite3Fts5StructureRef(Fts5Index*); static void sqlite3Fts5StructureRelease(void*); static int sqlite3Fts5StructureTest(Fts5Index*, void*); /* ** Insert or remove data to or from the index. Each time a document is ** added to or removed from the index, this function is called one or more ** times. ** ** For an insert, it must be called once for each token in the new document. | > > > > | 230251 230252 230253 230254 230255 230256 230257 230258 230259 230260 230261 230262 230263 230264 230265 230266 230267 230268 | */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); static int sqlite3Fts5IterNextScan(Fts5IndexIter*); static void *sqlite3Fts5StructureRef(Fts5Index*); static void sqlite3Fts5StructureRelease(void*); static int sqlite3Fts5StructureTest(Fts5Index*, void*); /* ** Used by xInstToken(): */ static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*); /* ** Insert or remove data to or from the index. Each time a document is ** added to or removed from the index, this function is called one or more ** times. ** ** For an insert, it must be called once for each token in the new document. |
| ︙ | ︙ | |||
228630 228631 228632 228633 228634 228635 228636 228637 228638 228639 228640 228641 228642 228643 | static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); static int sqlite3Fts5IndexReset(Fts5Index *p); static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin); static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid); /* ** End of interface to code in fts5_index.c. **************************************************************************/ /************************************************************************** ** Interface to code in fts5_varint.c. | > > > > > > > | 230331 230332 230333 230334 230335 230336 230337 230338 230339 230340 230341 230342 230343 230344 230345 230346 230347 230348 230349 230350 230351 |
static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
static int sqlite3Fts5IndexReset(Fts5Index *p);
static int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
static int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin);
static int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid);
static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter*);
/* Used to populate hash tables for xInstToken in detail=none/column mode. */
static int sqlite3Fts5IndexIterWriteTokendata(
Fts5IndexIter*, const char*, int, i64 iRowid, int iCol, int iOff
);
/*
** End of interface to code in fts5_index.c.
**************************************************************************/
/**************************************************************************
** Interface to code in fts5_varint.c.
|
| ︙ | ︙ | |||
228736 228737 228738 228739 228740 228741 228742 228743 228744 228745 228746 228747 228748 228749 | Fts5Hash*, /* Hash table to query */ const char *pTerm, int nTerm /* Query prefix */ ); static void sqlite3Fts5HashScanNext(Fts5Hash*); static int sqlite3Fts5HashScanEof(Fts5Hash*); static void sqlite3Fts5HashScanEntry(Fts5Hash *, const char **pzTerm, /* OUT: term (nul-terminated) */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ); /* | > | 230444 230445 230446 230447 230448 230449 230450 230451 230452 230453 230454 230455 230456 230457 230458 | Fts5Hash*, /* Hash table to query */ const char *pTerm, int nTerm /* Query prefix */ ); static void sqlite3Fts5HashScanNext(Fts5Hash*); static int sqlite3Fts5HashScanEof(Fts5Hash*); static void sqlite3Fts5HashScanEntry(Fts5Hash *, const char **pzTerm, /* OUT: term (nul-terminated) */ int *pnTerm, /* OUT: Size of term in bytes */ const u8 **ppDoclist, /* OUT: pointer to doclist */ int *pnDoclist /* OUT: size of doclist in bytes */ ); /* |
| ︙ | ︙ | |||
228861 228862 228863 228864 228865 228866 228867 228868 228869 228870 228871 228872 228873 228874 |
Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int
);
static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64);
static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**);
static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
/*******************************************
** The fts5_expr.c API above this point is used by the other hand-written
** C code in this module. The interfaces below this point are called by
** the parser code in fts5parse.y. */
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...);
| > > > > | 230570 230571 230572 230573 230574 230575 230576 230577 230578 230579 230580 230581 230582 230583 230584 230585 230586 230587 |
Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int
);
static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64);
static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**);
static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
static int sqlite3Fts5ExprQueryToken(Fts5Expr*, int, int, const char**, int*);
static int sqlite3Fts5ExprInstToken(Fts5Expr*, i64, int, int, int, int, const char**, int*);
static void sqlite3Fts5ExprClearTokens(Fts5Expr*);
/*******************************************
** The fts5_expr.c API above this point is used by the other hand-written
** C code in this module. The interfaces below this point are called by
** the parser code in fts5parse.y. */
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...);
|
| ︙ | ︙ | |||
230677 230678 230679 230680 230681 230682 230683 230684 230685 230686 230687 230688 230689 230690 |
if( rc==SQLITE_OK ){
rc = fts5CInstIterNext(&p->iter);
}
}
if( iPos==p->iRangeEnd ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
}
return rc;
}
| > > > > > > > > | 232390 232391 232392 232393 232394 232395 232396 232397 232398 232399 232400 232401 232402 232403 232404 232405 232406 232407 232408 232409 232410 232411 |
if( rc==SQLITE_OK ){
rc = fts5CInstIterNext(&p->iter);
}
}
if( iPos==p->iRangeEnd ){
if( p->bOpen ){
if( p->iter.iStart>=0 && iPos>=p->iter.iStart ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
}
fts5HighlightAppend(&rc, p, p->zClose, -1);
p->bOpen = 0;
}
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
}
return rc;
}
|
| ︙ | ︙ | |||
231278 231279 231280 231281 231282 231283 231284 231285 231286 231287 231288 231289 231290 231291 |
int *pRc,
Fts5Buffer *pBuf,
u32 nData,
const u8 *pData
){
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
}
/*
** Append the nul-terminated string zStr to the buffer pBuf. This function
| > | 232999 233000 233001 233002 233003 233004 233005 233006 233007 233008 233009 233010 233011 233012 233013 |
int *pRc,
Fts5Buffer *pBuf,
u32 nData,
const u8 *pData
){
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
assert( pBuf->p!=0 );
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
}
/*
** Append the nul-terminated string zStr to the buffer pBuf. This function
|
| ︙ | ︙ | |||
231379 231380 231381 231382 231383 231384 231385 231386 231387 231388 231389 231390 231391 231392 231393 231394 231395 231396 231397 231398 231399 |
static int sqlite3Fts5PoslistNext64(
const u8 *a, int n, /* Buffer containing poslist */
int *pi, /* IN/OUT: Offset within a[] */
i64 *piOff /* IN/OUT: Current offset */
){
int i = *pi;
if( i>=n ){
/* EOF */
*piOff = -1;
return 1;
}else{
i64 iOff = *piOff;
u32 iVal;
fts5FastGetVarint32(a, i, iVal);
if( iVal<=1 ){
if( iVal==0 ){
*pi = i;
return 0;
}
fts5FastGetVarint32(a, i, iVal);
| > > | 233101 233102 233103 233104 233105 233106 233107 233108 233109 233110 233111 233112 233113 233114 233115 233116 233117 233118 233119 233120 233121 233122 233123 |
static int sqlite3Fts5PoslistNext64(
const u8 *a, int n, /* Buffer containing poslist */
int *pi, /* IN/OUT: Offset within a[] */
i64 *piOff /* IN/OUT: Current offset */
){
int i = *pi;
assert( a!=0 || i==0 );
if( i>=n ){
/* EOF */
*piOff = -1;
return 1;
}else{
i64 iOff = *piOff;
u32 iVal;
assert( a!=0 );
fts5FastGetVarint32(a, i, iVal);
if( iVal<=1 ){
if( iVal==0 ){
*pi = i;
return 0;
}
fts5FastGetVarint32(a, i, iVal);
|
| ︙ | ︙ | |||
232016 232017 232018 232019 232020 232021 232022 232023 232024 232025 232026 232027 232028 232029 |
};
if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){
*pzErr = sqlite3_mprintf("malformed detail=... directive");
}
return rc;
}
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
return SQLITE_ERROR;
}
/*
** Allocate an instance of the default tokenizer ("simple") at
| > > > > > > > > > > | 233740 233741 233742 233743 233744 233745 233746 233747 233748 233749 233750 233751 233752 233753 233754 233755 233756 233757 233758 233759 233760 233761 233762 233763 |
};
if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){
*pzErr = sqlite3_mprintf("malformed detail=... directive");
}
return rc;
}
if( sqlite3_strnicmp("tokendata", zCmd, nCmd)==0 ){
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
*pzErr = sqlite3_mprintf("malformed tokendata=... directive");
rc = SQLITE_ERROR;
}else{
pConfig->bTokendata = (zArg[0]=='1');
}
return rc;
}
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
return SQLITE_ERROR;
}
/*
** Allocate an instance of the default tokenizer ("simple") at
|
| ︙ | ︙ | |||
232750 232751 232752 232753 232754 232755 232756 |
/*
** An instance of the following structure represents a single search term
** or term prefix.
*/
struct Fts5ExprTerm {
u8 bPrefix; /* True for a prefix term */
u8 bFirst; /* True if token must be first in column */
| | > > | 234484 234485 234486 234487 234488 234489 234490 234491 234492 234493 234494 234495 234496 234497 234498 234499 234500 |
/*
** An instance of the following structure represents a single search term
** or term prefix.
*/
struct Fts5ExprTerm {
u8 bPrefix; /* True for a prefix term */
u8 bFirst; /* True if token must be first in column */
char *pTerm; /* Term data */
int nQueryTerm; /* Effective size of term in bytes */
int nFullTerm; /* Size of term in bytes incl. tokendata */
Fts5IndexIter *pIter; /* Iterator for this term */
Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */
};
/*
** A phrase. One or more terms that must appear in a contiguous sequence
** within a document for it to match.
|
| ︙ | ︙ | |||
233617 233618 233619 233620 233621 233622 233623 |
for(p=pTerm; p; p=p->pSynonym){
int rc;
if( p->pIter ){
sqlite3Fts5IterClose(p->pIter);
p->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
| | | 235353 235354 235355 235356 235357 235358 235359 235360 235361 235362 235363 235364 235365 235366 235367 |
for(p=pTerm; p; p=p->pSynonym){
int rc;
if( p->pIter ){
sqlite3Fts5IterClose(p->pIter);
p->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
pExpr->pIndex, p->pTerm, p->nQueryTerm,
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
pNear->pColset,
&p->pIter
);
assert( (rc==SQLITE_OK)==(p->pIter!=0) );
if( rc!=SQLITE_OK ) return rc;
|
| ︙ | ︙ | |||
234254 234255 234256 234257 234258 234259 234260 |
static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
if( pPhrase ){
int i;
for(i=0; i<pPhrase->nTerm; i++){
Fts5ExprTerm *pSyn;
Fts5ExprTerm *pNext;
Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
| | | 235990 235991 235992 235993 235994 235995 235996 235997 235998 235999 236000 236001 236002 236003 236004 |
static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
if( pPhrase ){
int i;
for(i=0; i<pPhrase->nTerm; i++){
Fts5ExprTerm *pSyn;
Fts5ExprTerm *pNext;
Fts5ExprTerm *pTerm = &pPhrase->aTerm[i];
sqlite3_free(pTerm->pTerm);
sqlite3Fts5IterClose(pTerm->pIter);
for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){
pNext = pSyn->pSynonym;
sqlite3Fts5IterClose(pSyn->pIter);
fts5BufferFree((Fts5Buffer*)&pSyn[1]);
sqlite3_free(pSyn);
}
|
| ︙ | ︙ | |||
234352 234353 234354 234355 234356 234357 234358 234359 234360 234361 234362 234363 234364 234365 |
}
return pRet;
}
typedef struct TokenCtx TokenCtx;
struct TokenCtx {
Fts5ExprPhrase *pPhrase;
int rc;
};
/*
** Callback for tokenizing terms used by ParseTerm().
*/
static int fts5ParseTokenize(
| > | 236088 236089 236090 236091 236092 236093 236094 236095 236096 236097 236098 236099 236100 236101 236102 |
}
return pRet;
}
typedef struct TokenCtx TokenCtx;
struct TokenCtx {
Fts5ExprPhrase *pPhrase;
Fts5Config *pConfig;
int rc;
};
/*
** Callback for tokenizing terms used by ParseTerm().
*/
static int fts5ParseTokenize(
|
| ︙ | ︙ | |||
234385 234386 234387 234388 234389 234390 234391 |
Fts5ExprTerm *pSyn;
sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
if( pSyn==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pSyn, 0, (size_t)nByte);
| | > > > > | | 236122 236123 236124 236125 236126 236127 236128 236129 236130 236131 236132 236133 236134 236135 236136 236137 236138 236139 236140 236141 |
Fts5ExprTerm *pSyn;
sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
if( pSyn==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pSyn, 0, (size_t)nByte);
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
if( pCtx->pConfig->bTokendata ){
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
}
memcpy(pSyn->pTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
}
}else{
Fts5ExprTerm *pTerm;
if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){
Fts5ExprPhrase *pNew;
|
| ︙ | ︙ | |||
234411 234412 234413 234414 234415 234416 234417 |
pNew->nTerm = nNew - SZALLOC;
}
}
if( rc==SQLITE_OK ){
pTerm = &pPhrase->aTerm[pPhrase->nTerm++];
memset(pTerm, 0, sizeof(Fts5ExprTerm));
| | > > > > | 236152 236153 236154 236155 236156 236157 236158 236159 236160 236161 236162 236163 236164 236165 236166 236167 236168 236169 236170 |
pNew->nTerm = nNew - SZALLOC;
}
}
if( rc==SQLITE_OK ){
pTerm = &pPhrase->aTerm[pPhrase->nTerm++];
memset(pTerm, 0, sizeof(Fts5ExprTerm));
pTerm->pTerm = sqlite3Fts5Strndup(&rc, pToken, nToken);
pTerm->nFullTerm = pTerm->nQueryTerm = nToken;
if( pCtx->pConfig->bTokendata && rc==SQLITE_OK ){
pTerm->nQueryTerm = (int)strlen(pTerm->pTerm);
}
}
}
pCtx->rc = rc;
return rc;
}
|
| ︙ | ︙ | |||
234478 234479 234480 234481 234482 234483 234484 234485 234486 234487 234488 234489 234490 234491 |
Fts5Config *pConfig = pParse->pConfig;
TokenCtx sCtx; /* Context object passed to callback */
int rc; /* Tokenize return code */
char *z = 0;
memset(&sCtx, 0, sizeof(TokenCtx));
sCtx.pPhrase = pAppend;
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
int n;
sqlite3Fts5Dequote(z);
n = (int)strlen(z);
| > | 236223 236224 236225 236226 236227 236228 236229 236230 236231 236232 236233 236234 236235 236236 236237 |
Fts5Config *pConfig = pParse->pConfig;
TokenCtx sCtx; /* Context object passed to callback */
int rc; /* Tokenize return code */
char *z = 0;
memset(&sCtx, 0, sizeof(TokenCtx));
sCtx.pPhrase = pAppend;
sCtx.pConfig = pConfig;
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
int n;
sqlite3Fts5Dequote(z);
n = (int)strlen(z);
|
| ︙ | ︙ | |||
234527 234528 234529 234530 234531 234532 234533 |
Fts5Expr *pExpr,
int iPhrase,
Fts5Expr **ppNew
){
int rc = SQLITE_OK; /* Return code */
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
| | < | 236273 236274 236275 236276 236277 236278 236279 236280 236281 236282 236283 236284 236285 236286 236287 |
Fts5Expr *pExpr,
int iPhrase,
Fts5Expr **ppNew
){
int rc = SQLITE_OK; /* Return code */
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
pOrig = pExpr->apExprPhrase[iPhrase];
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
if( rc==SQLITE_OK ){
pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
|
| ︙ | ︙ | |||
234559 234560 234561 234562 234563 234564 234565 234566 234567 234568 234569 |
}
pNew->pRoot->pNear->pColset = pColset;
}
}
if( pOrig->nTerm ){
int i; /* Used to iterate through phrase terms */
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
| > < | < | 236304 236305 236306 236307 236308 236309 236310 236311 236312 236313 236314 236315 236316 236317 236318 236319 236320 236321 236322 236323 |
}
pNew->pRoot->pNear->pColset = pColset;
}
}
if( pOrig->nTerm ){
int i; /* Used to iterate through phrase terms */
sCtx.pConfig = pExpr->pConfig;
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
rc = fts5ParseTokenize((void*)&sCtx, tflags, p->pTerm,p->nFullTerm,0,0);
tflags = FTS5_TOKEN_COLOCATED;
}
if( rc==SQLITE_OK ){
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
}
}
|
| ︙ | ︙ | |||
234946 234947 234948 234949 234950 234951 234952 234953 234954 |
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
&pParse->rc, sizeof(Fts5ExprPhrase)
);
if( pPhrase ){
if( parseGrowPhraseArray(pParse) ){
fts5ExprPhraseFree(pPhrase);
}else{
pParse->apPhrase[pParse->nPhrase++] = pPhrase;
pPhrase->nTerm = 1;
| > > | < < > > | 236690 236691 236692 236693 236694 236695 236696 236697 236698 236699 236700 236701 236702 236703 236704 236705 236706 236707 236708 236709 236710 |
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
&pParse->rc, sizeof(Fts5ExprPhrase)
);
if( pPhrase ){
if( parseGrowPhraseArray(pParse) ){
fts5ExprPhraseFree(pPhrase);
}else{
Fts5ExprTerm *p = &pNear->apPhrase[0]->aTerm[ii];
Fts5ExprTerm *pTo = &pPhrase->aTerm[0];
pParse->apPhrase[pParse->nPhrase++] = pPhrase;
pPhrase->nTerm = 1;
pTo->pTerm = sqlite3Fts5Strndup(&pParse->rc, p->pTerm, p->nFullTerm);
pTo->nQueryTerm = p->nQueryTerm;
pTo->nFullTerm = p->nFullTerm;
pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
);
}
}
}
|
| ︙ | ︙ | |||
235135 235136 235137 235138 235139 235140 235141 |
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
/* Determine the maximum amount of space required. */
for(p=pTerm; p; p=p->pSynonym){
| | | > | | 236881 236882 236883 236884 236885 236886 236887 236888 236889 236890 236891 236892 236893 236894 236895 236896 236897 236898 236899 236900 236901 236902 236903 236904 236905 |
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
/* Determine the maximum amount of space required. */
for(p=pTerm; p; p=p->pSynonym){
nByte += pTerm->nQueryTerm * 2 + 3 + 2;
}
zQuoted = sqlite3_malloc64(nByte);
if( zQuoted ){
int i = 0;
for(p=pTerm; p; p=p->pSynonym){
char *zIn = p->pTerm;
char *zEnd = &zIn[p->nQueryTerm];
zQuoted[i++] = '"';
while( zIn<zEnd ){
if( *zIn=='"' ) zQuoted[i++] = '"';
zQuoted[i++] = *zIn++;
}
zQuoted[i++] = '"';
if( p->pSynonym ) zQuoted[i++] = '|';
}
if( pTerm->bPrefix ){
|
| ︙ | ︙ | |||
235222 235223 235224 235225 235226 235227 235228 |
if( zRet==0 ) return 0;
for(i=0; i<pNear->nPhrase; i++){
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
zRet = fts5PrintfAppend(zRet, " {");
for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
| | | > > | 236969 236970 236971 236972 236973 236974 236975 236976 236977 236978 236979 236980 236981 236982 236983 236984 236985 236986 |
if( zRet==0 ) return 0;
for(i=0; i<pNear->nPhrase; i++){
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
zRet = fts5PrintfAppend(zRet, " {");
for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
Fts5ExprTerm *p = &pPhrase->aTerm[iTerm];
zRet = fts5PrintfAppend(zRet, "%s%.*s", iTerm==0?"":" ",
p->nQueryTerm, p->pTerm
);
if( pPhrase->aTerm[iTerm].bPrefix ){
zRet = fts5PrintfAppend(zRet, "*");
}
}
if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
if( zRet==0 ) return 0;
|
| ︙ | ︙ | |||
235623 235624 235625 235626 235627 235628 235629 235630 235631 235632 235633 235634 235635 235636 235637 235638 235639 235640 235641 235642 235643 235644 |
static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
int i;
for(i=0; i<pColset->nCol; i++){
if( pColset->aiCol[i]==iCol ) return 1;
}
return 0;
}
static int fts5ExprPopulatePoslistsCb(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iUnused1, /* Byte offset of token within input text */
int iUnused2 /* Byte offset of end of token within input text */
){
Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
Fts5Expr *pExpr = p->pExpr;
int i;
UNUSED_PARAM2(iUnused1, iUnused2);
| > > > > > > > > > > > > > | > > > | | < | | > > > > > > > | 237372 237373 237374 237375 237376 237377 237378 237379 237380 237381 237382 237383 237384 237385 237386 237387 237388 237389 237390 237391 237392 237393 237394 237395 237396 237397 237398 237399 237400 237401 237402 237403 237404 237405 237406 237407 237408 237409 237410 237411 237412 237413 237414 237415 237416 237417 237418 237419 237420 237421 237422 237423 237424 237425 237426 237427 237428 237429 237430 237431 237432 237433 237434 237435 |
static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
int i;
for(i=0; i<pColset->nCol; i++){
if( pColset->aiCol[i]==iCol ) return 1;
}
return 0;
}
/*
** pToken is a buffer nToken bytes in size that may or may not contain
** an embedded 0x00 byte. If it does, return the number of bytes in
** the buffer before the 0x00. If it does not, return nToken.
*/
static int fts5QueryTerm(const char *pToken, int nToken){
int ii;
for(ii=0; ii<nToken && pToken[ii]; ii++){}
return ii;
}
static int fts5ExprPopulatePoslistsCb(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iUnused1, /* Byte offset of token within input text */
int iUnused2 /* Byte offset of end of token within input text */
){
Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
Fts5Expr *pExpr = p->pExpr;
int i;
int nQuery = nToken;
i64 iRowid = pExpr->pRoot->iRowid;
UNUSED_PARAM2(iUnused1, iUnused2);
if( nQuery>FTS5_MAX_TOKEN_SIZE ) nQuery = FTS5_MAX_TOKEN_SIZE;
if( pExpr->pConfig->bTokendata ){
nQuery = fts5QueryTerm(pToken, nQuery);
}
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++;
for(i=0; i<pExpr->nPhrase; i++){
Fts5ExprTerm *pT;
if( p->aPopulator[i].bOk==0 ) continue;
for(pT=&pExpr->apExprPhrase[i]->aTerm[0]; pT; pT=pT->pSynonym){
if( (pT->nQueryTerm==nQuery || (pT->nQueryTerm<nQuery && pT->bPrefix))
&& memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
){
int rc = sqlite3Fts5PoslistWriterAppend(
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
);
if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
int iCol = p->iOff>>32;
int iTokOff = p->iOff & 0x7FFFFFFF;
rc = sqlite3Fts5IndexIterWriteTokendata(
pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
);
}
if( rc ) return rc;
break;
}
}
}
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
235785 235786 235787 235788 235789 235790 235791 235792 235793 235794 235795 235796 235797 235798 |
}else{
*ppCollist = 0;
*pnCollist = 0;
}
return rc;
}
/*
** 2014 August 11
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 237556 237557 237558 237559 237560 237561 237562 237563 237564 237565 237566 237567 237568 237569 237570 237571 237572 237573 237574 237575 237576 237577 237578 237579 237580 237581 237582 237583 237584 237585 237586 237587 237588 237589 237590 237591 237592 237593 237594 237595 237596 237597 237598 237599 237600 237601 237602 237603 237604 237605 237606 237607 237608 237609 237610 237611 237612 237613 237614 237615 237616 237617 237618 237619 237620 237621 237622 237623 237624 237625 237626 237627 237628 237629 237630 237631 237632 237633 237634 237635 237636 237637 237638 237639 237640 237641 237642 237643 237644 237645 237646 |
}else{
*ppCollist = 0;
*pnCollist = 0;
}
return rc;
}
/*
** Does the work of the fts5_api.xQueryToken() API method.
*/
static int sqlite3Fts5ExprQueryToken(
Fts5Expr *pExpr,
int iPhrase,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5ExprPhrase *pPhrase = 0;
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
return SQLITE_RANGE;
}
pPhrase = pExpr->apExprPhrase[iPhrase];
if( iToken<0 || iToken>=pPhrase->nTerm ){
return SQLITE_RANGE;
}
*ppOut = pPhrase->aTerm[iToken].pTerm;
*pnOut = pPhrase->aTerm[iToken].nFullTerm;
return SQLITE_OK;
}
/*
** Does the work of the fts5_api.xInstToken() API method.
*/
static int sqlite3Fts5ExprInstToken(
Fts5Expr *pExpr,
i64 iRowid,
int iPhrase,
int iCol,
int iOff,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5ExprPhrase *pPhrase = 0;
Fts5ExprTerm *pTerm = 0;
int rc = SQLITE_OK;
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
return SQLITE_RANGE;
}
pPhrase = pExpr->apExprPhrase[iPhrase];
if( iToken<0 || iToken>=pPhrase->nTerm ){
return SQLITE_RANGE;
}
pTerm = &pPhrase->aTerm[iToken];
if( pTerm->bPrefix==0 ){
if( pExpr->pConfig->bTokendata ){
rc = sqlite3Fts5IterToken(
pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
);
}else{
*ppOut = pTerm->pTerm;
*pnOut = pTerm->nFullTerm;
}
}
return rc;
}
/*
** Clear the token mappings for all Fts5IndexIter objects mannaged by
** the expression passed as the only argument.
*/
static void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
int ii;
for(ii=0; ii<pExpr->nPhrase; ii++){
Fts5ExprTerm *pT;
for(pT=&pExpr->apExprPhrase[ii]->aTerm[0]; pT; pT=pT->pSynonym){
sqlite3Fts5IndexIterClearTokendata(pT->pIter);
}
}
}
/*
** 2014 August 11
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
|
| ︙ | ︙ | |||
235824 235825 235826 235827 235828 235829 235830 | int nSlot; /* Size of aSlot[] array */ Fts5HashEntry *pScan; /* Current ordered scan item */ Fts5HashEntry **aSlot; /* Array of hash slots */ }; /* ** Each entry in the hash table is represented by an object of the | | | | | > > > > > | 237672 237673 237674 237675 237676 237677 237678 237679 237680 237681 237682 237683 237684 237685 237686 237687 237688 237689 237690 237691 237692 237693 237694 | int nSlot; /* Size of aSlot[] array */ Fts5HashEntry *pScan; /* Current ordered scan item */ Fts5HashEntry **aSlot; /* Array of hash slots */ }; /* ** Each entry in the hash table is represented by an object of the ** following type. Each object, its key, and its current data are stored ** in a single memory allocation. The key immediately follows the object ** in memory. The position list data immediately follows the key data ** in memory. ** ** The key is Fts5HashEntry.nKey bytes in size. It consists of a single ** byte identifying the index (either the main term index or a prefix-index), ** followed by the term data. For example: "0token". There is no ** nul-terminator - in this case nKey=6. ** ** The data that follows the key is in a similar, but not identical format ** to the doclist data stored in the database. It is: ** ** * Rowid, as a varint ** * Position list, without 0x00 terminator. ** * Size of previous position list and rowid, as a 4 byte |
| ︙ | ︙ | |||
235962 235963 235964 235965 235966 235967 235968 |
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
for(i=0; i<pHash->nSlot; i++){
while( apOld[i] ){
unsigned int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
| | < | 237815 237816 237817 237818 237819 237820 237821 237822 237823 237824 237825 237826 237827 237828 237829 |
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
for(i=0; i<pHash->nSlot; i++){
while( apOld[i] ){
unsigned int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), p->nKey);
p->pHashNext = apNew[iHash];
apNew[iHash] = p;
}
}
sqlite3_free(apOld);
pHash->nSlot = nNew;
|
| ︙ | ︙ | |||
236047 236048 236049 236050 236051 236052 236053 |
bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
/* Attempt to locate an existing hash entry */
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
char *zKey = fts5EntryKey(p);
if( zKey[0]==bByte
| | | 237899 237900 237901 237902 237903 237904 237905 237906 237907 237908 237909 237910 237911 237912 237913 |
bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
/* Attempt to locate an existing hash entry */
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
char *zKey = fts5EntryKey(p);
if( zKey[0]==bByte
&& p->nKey==nToken+1
&& memcmp(&zKey[1], pToken, nToken)==0
){
break;
}
}
/* If an existing hash entry cannot be found, create a new one. */
|
| ︙ | ︙ | |||
236077 236078 236079 236080 236081 236082 236083 |
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = (int)nByte;
zKey = fts5EntryKey(p);
zKey[0] = bByte;
memcpy(&zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
| | | | 237929 237930 237931 237932 237933 237934 237935 237936 237937 237938 237939 237940 237941 237942 237943 237944 237945 |
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = (int)nByte;
zKey = fts5EntryKey(p);
zKey[0] = bByte;
memcpy(&zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
p->nKey = nToken+1;
zKey[nToken+1] = '\0';
p->nData = nToken+1 + sizeof(Fts5HashEntry);
p->pHashNext = pHash->aSlot[iHash];
pHash->aSlot[iHash] = p;
pHash->nEntry++;
/* Add the first rowid field to the hash-entry */
p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
p->iRowid = iRowid;
|
| ︙ | ︙ | |||
236196 236197 236198 236199 236200 236201 236202 |
if( p1==0 ){
*ppOut = p2;
p2 = 0;
}else if( p2==0 ){
*ppOut = p1;
p1 = 0;
}else{
| < > | > > > | > | > | 238048 238049 238050 238051 238052 238053 238054 238055 238056 238057 238058 238059 238060 238061 238062 238063 238064 238065 238066 238067 238068 238069 238070 238071 238072 |
if( p1==0 ){
*ppOut = p2;
p2 = 0;
}else if( p2==0 ){
*ppOut = p1;
p1 = 0;
}else{
char *zKey1 = fts5EntryKey(p1);
char *zKey2 = fts5EntryKey(p2);
int nMin = MIN(p1->nKey, p2->nKey);
int cmp = memcmp(zKey1, zKey2, nMin);
if( cmp==0 ){
cmp = p1->nKey - p2->nKey;
}
assert( cmp!=0 );
if( cmp>0 ){
/* p2 is smaller */
*ppOut = p2;
ppOut = &p2->pScanNext;
p2 = p2->pScanNext;
}else{
/* p1 is smaller */
*ppOut = p1;
|
| ︙ | ︙ | |||
236243 236244 236245 236246 236247 236248 236249 |
if( !ap ) return SQLITE_NOMEM;
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
Fts5HashEntry *pIter;
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
if( pTerm==0
| | | 238100 238101 238102 238103 238104 238105 238106 238107 238108 238109 238110 238111 238112 238113 238114 |
if( !ap ) return SQLITE_NOMEM;
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
Fts5HashEntry *pIter;
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
if( pTerm==0
|| (pIter->nKey>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
){
Fts5HashEntry *pEntry = pIter;
pEntry->pScanNext = 0;
for(i=0; ap[i]; i++){
pEntry = fts5HashEntryMerge(pEntry, ap[i]);
ap[i] = 0;
}
|
| ︙ | ︙ | |||
236282 236283 236284 236285 236286 236287 236288 |
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
char *zKey = 0;
Fts5HashEntry *p;
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
| < | | | 238139 238140 238141 238142 238143 238144 238145 238146 238147 238148 238149 238150 238151 238152 238153 238154 238155 238156 238157 |
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
char *zKey = 0;
Fts5HashEntry *p;
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
if( nTerm==p->nKey && memcmp(zKey, pTerm, nTerm)==0 ) break;
}
if( p ){
int nHashPre = sizeof(Fts5HashEntry) + nTerm;
int nList = p->nData - nHashPre;
u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10));
if( pRet ){
Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre];
memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList);
nList += fts5HashAddPoslistSize(pHash, p, pFaux);
*pnDoclist = nList;
|
| ︙ | ︙ | |||
236348 236349 236350 236351 236352 236353 236354 236355 236356 236357 236358 236359 236360 |
static int sqlite3Fts5HashScanEof(Fts5Hash *p){
return (p->pScan==0);
}
static void sqlite3Fts5HashScanEntry(
Fts5Hash *pHash,
const char **pzTerm, /* OUT: term (nul-terminated) */
const u8 **ppDoclist, /* OUT: pointer to doclist */
int *pnDoclist /* OUT: size of doclist in bytes */
){
Fts5HashEntry *p;
if( (p = pHash->pScan) ){
char *zKey = fts5EntryKey(p);
| > | > | | > | 238204 238205 238206 238207 238208 238209 238210 238211 238212 238213 238214 238215 238216 238217 238218 238219 238220 238221 238222 238223 238224 238225 238226 238227 238228 238229 238230 238231 238232 238233 |
static int sqlite3Fts5HashScanEof(Fts5Hash *p){
return (p->pScan==0);
}
static void sqlite3Fts5HashScanEntry(
Fts5Hash *pHash,
const char **pzTerm, /* OUT: term (nul-terminated) */
int *pnTerm, /* OUT: Size of term in bytes */
const u8 **ppDoclist, /* OUT: pointer to doclist */
int *pnDoclist /* OUT: size of doclist in bytes */
){
Fts5HashEntry *p;
if( (p = pHash->pScan) ){
char *zKey = fts5EntryKey(p);
int nTerm = p->nKey;
fts5HashAddPoslistSize(pHash, p, 0);
*pzTerm = zKey;
*pnTerm = nTerm;
*ppDoclist = (const u8*)&zKey[nTerm];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm);
}else{
*pzTerm = 0;
*pnTerm = 0;
*ppDoclist = 0;
*pnDoclist = 0;
}
}
/*
** 2014 May 31
|
| ︙ | ︙ | |||
236691 236692 236693 236694 236695 236696 236697 236698 236699 236700 236701 236702 236703 236704 |
typedef struct Fts5PageWriter Fts5PageWriter;
typedef struct Fts5SegIter Fts5SegIter;
typedef struct Fts5DoclistIter Fts5DoclistIter;
typedef struct Fts5SegWriter Fts5SegWriter;
typedef struct Fts5Structure Fts5Structure;
typedef struct Fts5StructureLevel Fts5StructureLevel;
typedef struct Fts5StructureSegment Fts5StructureSegment;
struct Fts5Data {
u8 *p; /* Pointer to buffer containing record */
int nn; /* Size of record in bytes */
int szLeaf; /* Size of leaf without page-index */
};
| > > > | 238550 238551 238552 238553 238554 238555 238556 238557 238558 238559 238560 238561 238562 238563 238564 238565 238566 |
typedef struct Fts5PageWriter Fts5PageWriter;
typedef struct Fts5SegIter Fts5SegIter;
typedef struct Fts5DoclistIter Fts5DoclistIter;
typedef struct Fts5SegWriter Fts5SegWriter;
typedef struct Fts5Structure Fts5Structure;
typedef struct Fts5StructureLevel Fts5StructureLevel;
typedef struct Fts5StructureSegment Fts5StructureSegment;
typedef struct Fts5TokenDataIter Fts5TokenDataIter;
typedef struct Fts5TokenDataMap Fts5TokenDataMap;
typedef struct Fts5TombstoneArray Fts5TombstoneArray;
struct Fts5Data {
u8 *p; /* Pointer to buffer containing record */
int nn; /* Size of record in bytes */
int szLeaf; /* Size of leaf without page-index */
};
|
| ︙ | ︙ | |||
236725 236726 236727 236728 236729 236730 236731 236732 236733 236734 236735 236736 236737 236738 236739 236740 236741 236742 236743 236744 236745 236746 | i64 iWriteRowid; /* Rowid for current doc being written */ int bDelete; /* Current write is a delete */ int nContentlessDelete; /* Number of contentless delete ops */ int nPendingRow; /* Number of INSERT in hash table */ /* Error state. */ int rc; /* Current error code */ /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ sqlite3_stmt *pDeleteFromIdx; sqlite3_stmt *pDataVersion; i64 iStructVersion; /* data_version when pStruct read */ Fts5Structure *pStruct; /* Current db structure (or NULL) */ | > > | 238587 238588 238589 238590 238591 238592 238593 238594 238595 238596 238597 238598 238599 238600 238601 238602 238603 238604 238605 238606 238607 238608 238609 238610 | i64 iWriteRowid; /* Rowid for current doc being written */ int bDelete; /* Current write is a delete */ int nContentlessDelete; /* Number of contentless delete ops */ int nPendingRow; /* Number of INSERT in hash table */ /* Error state. */ int rc; /* Current error code */ int flushRc; /* State used by the fts5DataXXX() functions. */ sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; sqlite3_stmt *pIdxNextSelect; int nRead; /* Total number of blocks read */ sqlite3_stmt *pDeleteFromIdx; sqlite3_stmt *pDataVersion; i64 iStructVersion; /* data_version when pStruct read */ Fts5Structure *pStruct; /* Current db structure (or NULL) */ |
| ︙ | ︙ | |||
236886 236887 236888 236889 236890 236891 236892 |
struct Fts5SegIter {
Fts5StructureSegment *pSeg; /* Segment to iterate through */
int flags; /* Mask of configuration flags */
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
i64 iLeafOffset; /* Byte offset within current leaf */
| | < | 238750 238751 238752 238753 238754 238755 238756 238757 238758 238759 238760 238761 238762 238763 238764 |
struct Fts5SegIter {
Fts5StructureSegment *pSeg; /* Segment to iterate through */
int flags; /* Mask of configuration flags */
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
i64 iLeafOffset; /* Byte offset within current leaf */
Fts5TombstoneArray *pTombArray; /* Array of tombstone pages */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
/* The page and offset from which the current term was read. The offset
** is the offset of the first rowid in the current doclist. */
int iTermLeafPgno;
|
| ︙ | ︙ | |||
236913 236914 236915 236916 236917 236918 236919 236920 236921 236922 236923 236924 236925 236926 |
/* Variables populated based on current entry. */
Fts5Buffer term; /* Current term */
i64 iRowid; /* Current rowid */
int nPos; /* Number of bytes in current position list */
u8 bDel; /* True if the delete flag is set */
};
/*
** Argument is a pointer to an Fts5Data structure that contains a
** leaf page.
*/
#define ASSERT_SZLEAF_OK(x) assert( \
(x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
| > > > > > > > > > | 238776 238777 238778 238779 238780 238781 238782 238783 238784 238785 238786 238787 238788 238789 238790 238791 238792 238793 238794 238795 238796 238797 238798 |
/* Variables populated based on current entry. */
Fts5Buffer term; /* Current term */
i64 iRowid; /* Current rowid */
int nPos; /* Number of bytes in current position list */
u8 bDel; /* True if the delete flag is set */
};
/*
** Array of tombstone pages. Reference counted.
*/
struct Fts5TombstoneArray {
int nRef; /* Number of pointers to this object */
int nTombstone;
Fts5Data *apTombstone[1]; /* Array of tombstone pages */
};
/*
** Argument is a pointer to an Fts5Data structure that contains a
** leaf page.
*/
#define ASSERT_SZLEAF_OK(x) assert( \
(x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
|
| ︙ | ︙ | |||
236958 236959 236960 236961 236962 236963 236964 236965 236966 236967 236968 236969 236970 236971 236972 236973 236974 236975 236976 236977 236978 236979 236980 236981 236982 236983 |
**
** aFirst[1] contains the index in aSeg[] of the iterator that points to
** the smallest key overall. aFirst[0] is unused.
**
** poslist:
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
** There is no way to tell if this is populated or not.
*/
struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5Index *pIndex; /* Index that owns this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
/* Invoked to set output variables. */
void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
int nSeg; /* Size of aSeg[] array */
int bRev; /* True to iterate in reverse order */
u8 bSkipEmpty; /* True to skip deleted entries */
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
Fts5CResult *aFirst; /* Current merge state (see above) */
Fts5SegIter aSeg[1]; /* Array of segment iterators */
};
| > > > > > > > < | 238830 238831 238832 238833 238834 238835 238836 238837 238838 238839 238840 238841 238842 238843 238844 238845 238846 238847 238848 238849 238850 238851 238852 238853 238854 238855 238856 238857 238858 238859 238860 238861 238862 238863 238864 238865 238866 238867 238868 238869 |
**
** aFirst[1] contains the index in aSeg[] of the iterator that points to
** the smallest key overall. aFirst[0] is unused.
**
** poslist:
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
** There is no way to tell if this is populated or not.
**
** pColset:
** If not NULL, points to an object containing a set of column indices.
** Only matches that occur in one of these columns will be returned.
** The Fts5Iter does not own the Fts5Colset object, and so it is not
** freed when the iterator is closed - it is owned by the upper layer.
*/
struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5TokenDataIter *pTokenDataIter;
Fts5Index *pIndex; /* Index that owns this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
/* Invoked to set output variables. */
void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
int nSeg; /* Size of aSeg[] array */
int bRev; /* True to iterate in reverse order */
u8 bSkipEmpty; /* True to skip deleted entries */
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
Fts5CResult *aFirst; /* Current merge state (see above) */
Fts5SegIter aSeg[1]; /* Array of segment iterators */
};
/*
** An instance of the following type is used to iterate through the contents
** of a doclist-index record.
**
** pData:
** Record containing the doclist-index data.
|
| ︙ | ︙ | |||
238277 238278 238279 238280 238281 238282 238283 |
pIter->xNext = fts5SegIterNext_None;
}else{
pIter->xNext = fts5SegIterNext;
}
}
/*
| | | | | > | | < | > > | 240155 240156 240157 240158 240159 240160 240161 240162 240163 240164 240165 240166 240167 240168 240169 240170 240171 240172 240173 240174 240175 240176 240177 240178 240179 240180 240181 240182 |
pIter->xNext = fts5SegIterNext_None;
}else{
pIter->xNext = fts5SegIterNext;
}
}
/*
** Allocate a tombstone hash page array object (pIter->pTombArray) for
** the iterator passed as the second argument. If an OOM error occurs,
** leave an error in the Fts5Index object.
*/
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
const int nTomb = pIter->pSeg->nPgTombstone;
if( nTomb>0 ){
int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
Fts5TombstoneArray *pNew;
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pNew ){
pNew->nTombstone = nTomb;
pNew->nRef = 1;
pIter->pTombArray = pNew;
}
}
}
/*
** Initialize the iterator object pIter to iterate through the entries in
** segment pSeg. The iterator is left pointing to the first entry when
|
| ︙ | ︙ | |||
238545 238546 238547 238548 238549 238550 238551 238552 238553 |
iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
}
pIter->iLeafOffset = iOff;
fts5SegIterLoadTerm(p, pIter, nKeep);
}else{
const u8 *pList = 0;
const char *zTerm = 0;
int nList;
sqlite3Fts5HashScanNext(p->pHash);
| > | | | 240425 240426 240427 240428 240429 240430 240431 240432 240433 240434 240435 240436 240437 240438 240439 240440 240441 240442 240443 240444 240445 240446 240447 240448 |
iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
}
pIter->iLeafOffset = iOff;
fts5SegIterLoadTerm(p, pIter, nKeep);
}else{
const u8 *pList = 0;
const char *zTerm = 0;
int nTerm = 0;
int nList;
sqlite3Fts5HashScanNext(p->pHash);
sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList);
if( pList==0 ) goto next_none_eof;
pIter->pLeaf->p = (u8*)pList;
pIter->pLeaf->nn = nList;
pIter->pLeaf->szLeaf = nList;
pIter->iEndofDoclist = nList;
sqlite3Fts5BufferSet(&p->rc,&pIter->term, nTerm, (u8*)zTerm);
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
}
if( pbNewTerm ) *pbNewTerm = 1;
}else{
goto next_none_eof;
}
|
| ︙ | ︙ | |||
238619 238620 238621 238622 238623 238624 238625 238626 238627 238628 238629 |
assert_nc( iDelta>0 );
}
pIter->iLeafOffset = iOff;
}else if( pIter->pSeg==0 ){
const u8 *pList = 0;
const char *zTerm = 0;
int nList = 0;
assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
sqlite3Fts5HashScanNext(p->pHash);
| > | | < | 240500 240501 240502 240503 240504 240505 240506 240507 240508 240509 240510 240511 240512 240513 240514 240515 240516 240517 240518 240519 240520 240521 240522 240523 240524 240525 240526 240527 240528 240529 |
assert_nc( iDelta>0 );
}
pIter->iLeafOffset = iOff;
}else if( pIter->pSeg==0 ){
const u8 *pList = 0;
const char *zTerm = 0;
int nTerm = 0;
int nList = 0;
assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
sqlite3Fts5HashScanNext(p->pHash);
sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList);
}
if( pList==0 ){
fts5DataRelease(pIter->pLeaf);
pIter->pLeaf = 0;
}else{
pIter->pLeaf->p = (u8*)pList;
pIter->pLeaf->nn = nList;
pIter->pLeaf->szLeaf = nList;
pIter->iEndofDoclist = nList+1;
sqlite3Fts5BufferSet(&p->rc, &pIter->term, nTerm, (u8*)zTerm);
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
*pbNewTerm = 1;
}
}else{
iOff = 0;
/* Next entry is not on the current page */
while( iOff==0 ){
|
| ︙ | ︙ | |||
239020 239021 239022 239023 239024 239025 239026 |
pIter->iLeafPgno = iPg - 1;
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf ){
fts5LeafSeek(p, bGe, pIter, pTerm, nTerm);
}
| | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 240901 240902 240903 240904 240905 240906 240907 240908 240909 240910 240911 240912 240913 240914 240915 240916 240917 240918 240919 240920 240921 240922 240923 240924 240925 240926 240927 240928 240929 240930 240931 240932 240933 240934 240935 240936 240937 240938 240939 240940 240941 240942 240943 240944 240945 240946 240947 240948 240949 240950 240951 240952 240953 240954 240955 240956 240957 240958 240959 240960 240961 240962 240963 240964 240965 240966 240967 240968 240969 240970 240971 240972 240973 240974 240975 240976 240977 240978 240979 240980 240981 240982 240983 240984 240985 240986 240987 240988 240989 240990 240991 240992 240993 240994 240995 240996 240997 240998 240999 241000 241001 241002 241003 241004 241005 241006 241007 241008 241009 241010 241011 241012 241013 241014 241015 241016 241017 241018 241019 241020 241021 241022 |
pIter->iLeafPgno = iPg - 1;
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf ){
fts5LeafSeek(p, bGe, pIter, pTerm, nTerm);
}
if( p->rc==SQLITE_OK && (bGe==0 || (flags & FTS5INDEX_QUERY_SCANONETERM)) ){
pIter->flags |= FTS5_SEGITER_ONETERM;
if( pIter->pLeaf ){
if( flags & FTS5INDEX_QUERY_DESC ){
pIter->flags |= FTS5_SEGITER_REVERSE;
}
if( bDlidx ){
fts5SegIterLoadDlidx(p, pIter);
}
if( flags & FTS5INDEX_QUERY_DESC ){
fts5SegIterReverse(p, pIter);
}
}
}
fts5SegIterSetNext(p, pIter);
if( 0==(flags & FTS5INDEX_QUERY_SCANONETERM) ){
fts5SegIterAllocTombstone(p, pIter);
}
/* Either:
**
** 1) an error has occurred, or
** 2) the iterator points to EOF, or
** 3) the iterator points to an entry with term (pTerm/nTerm), or
** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
** to an entry with a term greater than or equal to (pTerm/nTerm).
*/
assert_nc( p->rc!=SQLITE_OK /* 1 */
|| pIter->pLeaf==0 /* 2 */
|| fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
|| (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
);
}
/*
** SQL used by fts5SegIterNextInit() to find the page to open.
*/
static sqlite3_stmt *fts5IdxNextStmt(Fts5Index *p){
if( p->pIdxNextSelect==0 ){
Fts5Config *pConfig = p->pConfig;
fts5IndexPrepareStmt(p, &p->pIdxNextSelect, sqlite3_mprintf(
"SELECT pgno FROM '%q'.'%q_idx' WHERE "
"segid=? AND term>? ORDER BY term ASC LIMIT 1",
pConfig->zDb, pConfig->zName
));
}
return p->pIdxNextSelect;
}
/*
** This is similar to fts5SegIterSeekInit(), except that it initializes
** the segment iterator to point to the first term following the page
** with pToken/nToken on it.
*/
static void fts5SegIterNextInit(
Fts5Index *p,
const char *pTerm, int nTerm,
Fts5StructureSegment *pSeg, /* Description of segment */
Fts5SegIter *pIter /* Object to populate */
){
int iPg = -1; /* Page of segment to open */
int bDlidx = 0;
sqlite3_stmt *pSel = 0; /* SELECT to find iPg */
pSel = fts5IdxNextStmt(p);
if( pSel ){
assert( p->rc==SQLITE_OK );
sqlite3_bind_int(pSel, 1, pSeg->iSegid);
sqlite3_bind_blob(pSel, 2, pTerm, nTerm, SQLITE_STATIC);
if( sqlite3_step(pSel)==SQLITE_ROW ){
i64 val = sqlite3_column_int64(pSel, 0);
iPg = (int)(val>>1);
bDlidx = (val & 0x0001);
}
p->rc = sqlite3_reset(pSel);
sqlite3_bind_null(pSel, 2);
if( p->rc ) return;
}
memset(pIter, 0, sizeof(*pIter));
pIter->pSeg = pSeg;
pIter->flags |= FTS5_SEGITER_ONETERM;
if( iPg>=0 ){
pIter->iLeafPgno = iPg - 1;
fts5SegIterNextPage(p, pIter);
fts5SegIterSetNext(p, pIter);
}
if( pIter->pLeaf ){
const u8 *a = pIter->pLeaf->p;
int iTermOff = 0;
pIter->iPgidxOff = pIter->pLeaf->szLeaf;
pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff);
pIter->iLeafOffset = iTermOff;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
if( bDlidx ) fts5SegIterLoadDlidx(p, pIter);
assert( p->rc!=SQLITE_OK ||
fts5BufferCompareBlob(&pIter->term, (const u8*)pTerm, nTerm)>0
);
}
}
/*
** Initialize the object pIter to point to term pTerm/nTerm within the
** in-memory hash table. If there is no such term in the hash-table, the
** iterator is set to EOF.
**
** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
** an error has already occurred when this function is called, it is a no-op.
|
| ︙ | ︙ | |||
239079 239080 239081 239082 239083 239084 239085 |
assert( p->pHash );
assert( p->rc==SQLITE_OK );
if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
const u8 *pList = 0;
p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
| | < | 241035 241036 241037 241038 241039 241040 241041 241042 241043 241044 241045 241046 241047 241048 241049 |
assert( p->pHash );
assert( p->rc==SQLITE_OK );
if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
const u8 *pList = 0;
p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &n, &pList, &nList);
if( pList ){
pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
if( pLeaf ){
pLeaf->p = (u8*)pList;
}
}
|
| ︙ | ︙ | |||
239138 239139 239140 239141 239142 239143 239144 239145 239146 239147 239148 239149 239150 239151 239152 |
int ii;
for(ii=0; ii<n; ii++){
fts5DataRelease(ap[ii]);
}
sqlite3_free(ap);
}
}
/*
** Zero the iterator passed as the only argument.
*/
static void fts5SegIterClear(Fts5SegIter *pIter){
fts5BufferFree(&pIter->term);
fts5DataRelease(pIter->pLeaf);
fts5DataRelease(pIter->pNextLeaf);
| > > > > > > > > > > > > > > > > > | | 241093 241094 241095 241096 241097 241098 241099 241100 241101 241102 241103 241104 241105 241106 241107 241108 241109 241110 241111 241112 241113 241114 241115 241116 241117 241118 241119 241120 241121 241122 241123 241124 241125 241126 241127 241128 241129 241130 241131 241132 |
int ii;
for(ii=0; ii<n; ii++){
fts5DataRelease(ap[ii]);
}
sqlite3_free(ap);
}
}
/*
** Decrement the ref-count of the object passed as the only argument. If it
** reaches 0, free it and its contents.
*/
static void fts5TombstoneArrayDelete(Fts5TombstoneArray *p){
if( p ){
p->nRef--;
if( p->nRef<=0 ){
int ii;
for(ii=0; ii<p->nTombstone; ii++){
fts5DataRelease(p->apTombstone[ii]);
}
sqlite3_free(p);
}
}
}
/*
** Zero the iterator passed as the only argument.
*/
static void fts5SegIterClear(Fts5SegIter *pIter){
fts5BufferFree(&pIter->term);
fts5DataRelease(pIter->pLeaf);
fts5DataRelease(pIter->pNextLeaf);
fts5TombstoneArrayDelete(pIter->pTombArray);
fts5DlidxIterFree(pIter->pDlidx);
sqlite3_free(pIter->aRowidOffset);
memset(pIter, 0, sizeof(Fts5SegIter));
}
#ifdef SQLITE_DEBUG
|
| ︙ | ︙ | |||
239391 239392 239393 239394 239395 239396 239397 |
if( pIter->pLeaf==0 ) break;
if( bRev==0 && pIter->iRowid>=iMatch ) break;
if( bRev!=0 && pIter->iRowid<=iMatch ) break;
bMove = 1;
}while( p->rc==SQLITE_OK );
}
| < | 241363 241364 241365 241366 241367 241368 241369 241370 241371 241372 241373 241374 241375 241376 |
if( pIter->pLeaf==0 ) break;
if( bRev==0 && pIter->iRowid>=iMatch ) break;
if( bRev!=0 && pIter->iRowid<=iMatch ) break;
bMove = 1;
}while( p->rc==SQLITE_OK );
}
/*
** Free the iterator object passed as the second argument.
*/
static void fts5MultiIterFree(Fts5Iter *pIter){
if( pIter ){
int i;
for(i=0; i<pIter->nSeg; i++){
|
| ︙ | ︙ | |||
239536 239537 239538 239539 239540 239541 239542 239543 |
** Return true if the iterator passed as the only argument points
** to an segment entry for which there is a tombstone. Return false
** if there is no tombstone or if the iterator is already at EOF.
*/
static int fts5MultiIterIsDeleted(Fts5Iter *pIter){
int iFirst = pIter->aFirst[1].iFirst;
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
| > | | | | | | | | 241507 241508 241509 241510 241511 241512 241513 241514 241515 241516 241517 241518 241519 241520 241521 241522 241523 241524 241525 241526 241527 241528 241529 241530 241531 241532 241533 241534 241535 241536 241537 241538 241539 |
** Return true if the iterator passed as the only argument points
** to an segment entry for which there is a tombstone. Return false
** if there is no tombstone or if the iterator is already at EOF.
*/
static int fts5MultiIterIsDeleted(Fts5Iter *pIter){
int iFirst = pIter->aFirst[1].iFirst;
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
Fts5TombstoneArray *pArray = pSeg->pTombArray;
if( pSeg->pLeaf && pArray ){
/* Figure out which page the rowid might be present on. */
int iPg = ((u64)pSeg->iRowid) % pArray->nTombstone;
assert( iPg>=0 );
/* If tombstone hash page iPg has not yet been loaded from the
** database, load it now. */
if( pArray->apTombstone[iPg]==0 ){
pArray->apTombstone[iPg] = fts5DataRead(pIter->pIndex,
FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg)
);
if( pArray->apTombstone[iPg]==0 ) return 0;
}
return fts5IndexTombstoneQuery(
pArray->apTombstone[iPg],
pArray->nTombstone,
pSeg->iRowid
);
}
return 0;
}
|
| ︙ | ︙ | |||
240092 240093 240094 240095 240096 240097 240098 240099 240100 240101 240102 240103 240104 240105 |
}else{
pIter->xSetOutputs = fts5IterSetOutputs_Col;
}
}
}
}
/*
** Allocate a new Fts5Iter object.
**
** The new object will be used to iterate through data in structure pStruct.
** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
** is zero or greater, data from the first nSegment segments on level iLevel
| > > > > > > > > > > > > > > > > > > > > > > > > > > | 242064 242065 242066 242067 242068 242069 242070 242071 242072 242073 242074 242075 242076 242077 242078 242079 242080 242081 242082 242083 242084 242085 242086 242087 242088 242089 242090 242091 242092 242093 242094 242095 242096 242097 242098 242099 242100 242101 242102 242103 |
}else{
pIter->xSetOutputs = fts5IterSetOutputs_Col;
}
}
}
}
/*
** All the component segment-iterators of pIter have been set up. This
** functions finishes setup for iterator pIter itself.
*/
static void fts5MultiIterFinishSetup(Fts5Index *p, Fts5Iter *pIter){
int iIter;
for(iIter=pIter->nSeg-1; iIter>0; iIter--){
int iEq;
if( (iEq = fts5MultiIterDoCompare(pIter, iIter)) ){
Fts5SegIter *pSeg = &pIter->aSeg[iEq];
if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
fts5MultiIterAdvanced(p, pIter, iEq, iIter);
}
}
fts5MultiIterSetEof(pIter);
fts5AssertMultiIterSetup(p, pIter);
if( (pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter))
|| fts5MultiIterIsDeleted(pIter)
){
fts5MultiIterNext(p, pIter, 0, 0);
}else if( pIter->base.bEof==0 ){
Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
pIter->xSetOutputs(pIter, pSeg);
}
}
/*
** Allocate a new Fts5Iter object.
**
** The new object will be used to iterate through data in structure pStruct.
** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
** is zero or greater, data from the first nSegment segments on level iLevel
|
| ︙ | ︙ | |||
240173 240174 240175 240176 240177 240178 240179 |
for(iSeg=nSeg-1; iSeg>=0; iSeg--){
fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
}
}
assert( iIter==nSeg );
}
| | < < < < < < < < | < < < < < < < < < < < | 242171 242172 242173 242174 242175 242176 242177 242178 242179 242180 242181 242182 242183 242184 242185 242186 242187 242188 242189 242190 |
for(iSeg=nSeg-1; iSeg>=0; iSeg--){
fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
}
}
assert( iIter==nSeg );
}
/* If the above was successful, each component iterator now points
** to the first entry in its segment. In this case initialize the
** aFirst[] array. Or, if an error has occurred, free the iterator
** object and set the output variable to NULL. */
if( p->rc==SQLITE_OK ){
fts5MultiIterFinishSetup(p, pNew);
}else{
fts5MultiIterFree(pNew);
*ppOut = 0;
}
fts5MultiIterNew_post_check:
assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
|
| ︙ | ︙ | |||
240222 240223 240224 240225 240226 240227 240228 |
int bDesc, /* True for descending rowid order */
Fts5Iter **ppOut /* New object */
){
Fts5Iter *pNew;
pNew = fts5MultiIterAlloc(p, 2);
if( pNew ){
Fts5SegIter *pIter = &pNew->aSeg[1];
| < | 242201 242202 242203 242204 242205 242206 242207 242208 242209 242210 242211 242212 242213 242214 |
int bDesc, /* True for descending rowid order */
Fts5Iter **ppOut /* New object */
){
Fts5Iter *pNew;
pNew = fts5MultiIterAlloc(p, 2);
if( pNew ){
Fts5SegIter *pIter = &pNew->aSeg[1];
pIter->flags = FTS5_SEGITER_ONETERM;
if( pData->szLeaf>0 ){
pIter->pLeaf = pData;
pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
pIter->iEndofDoclist = pData->nn;
pNew->aFirst[1].iFirst = 1;
if( bDesc ){
|
| ︙ | ︙ | |||
240370 240371 240372 240373 240374 240375 240376 240377 240378 240379 240380 240381 240382 240383 |
*/
static void fts5IndexDiscardData(Fts5Index *p){
assert( p->pHash || p->nPendingData==0 );
if( p->pHash ){
sqlite3Fts5HashClear(p->pHash);
p->nPendingData = 0;
p->nPendingRow = 0;
}
p->nContentlessDelete = 0;
}
/*
** Return the size of the prefix, in bytes, that buffer
** (pNew/<length-unknown>) shares with buffer (pOld/nOld).
| > | 242348 242349 242350 242351 242352 242353 242354 242355 242356 242357 242358 242359 242360 242361 242362 |
*/
static void fts5IndexDiscardData(Fts5Index *p){
assert( p->pHash || p->nPendingData==0 );
if( p->pHash ){
sqlite3Fts5HashClear(p->pHash);
p->nPendingData = 0;
p->nPendingRow = 0;
p->flushRc = SQLITE_OK;
}
p->nContentlessDelete = 0;
}
/*
** Return the size of the prefix, in bytes, that buffer
** (pNew/<length-unknown>) shares with buffer (pOld/nOld).
|
| ︙ | ︙ | |||
240585 240586 240587 240588 240589 240590 240591 |
pDlidx->bPrevValid = 0;
pDlidx->pgno++;
}else{
bDone = 1;
}
if( pDlidx->bPrevValid ){
| | | 242564 242565 242566 242567 242568 242569 242570 242571 242572 242573 242574 242575 242576 242577 242578 |
pDlidx->bPrevValid = 0;
pDlidx->pgno++;
}else{
bDone = 1;
}
if( pDlidx->bPrevValid ){
iVal = (u64)iRowid - (u64)pDlidx->iPrev;
}else{
i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno);
assert( pDlidx->buf.n==0 );
sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, !bDone);
sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iPgno);
iVal = iRowid;
}
|
| ︙ | ︙ | |||
241708 241709 241710 241711 241712 241713 241714 241715 241716 241717 |
** mode. It edits the segments within the database described by argument
** pStruct to remove the entries for term zTerm, rowid iRowid.
*/
static void fts5FlushSecureDelete(
Fts5Index *p,
Fts5Structure *pStruct,
const char *zTerm,
i64 iRowid
){
const int f = FTS5INDEX_QUERY_SKIPHASH;
| > < | 243687 243688 243689 243690 243691 243692 243693 243694 243695 243696 243697 243698 243699 243700 243701 243702 243703 243704 |
** mode. It edits the segments within the database described by argument
** pStruct to remove the entries for term zTerm, rowid iRowid.
*/
static void fts5FlushSecureDelete(
Fts5Index *p,
Fts5Structure *pStruct,
const char *zTerm,
int nTerm,
i64 iRowid
){
const int f = FTS5INDEX_QUERY_SKIPHASH;
Fts5Iter *pIter = 0; /* Used to find term instance */
fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
if( fts5MultiIterEof(p, pIter)==0 ){
i64 iThis = fts5MultiIterRowid(pIter);
if( iThis<iRowid ){
fts5MultiIterNextFrom(p, pIter, iRowid);
|
| ︙ | ︙ | |||
241785 241786 241787 241788 241789 241790 241791 |
while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
const char *zTerm; /* Buffer containing term */
int nTerm; /* Size of zTerm in bytes */
const u8 *pDoclist; /* Pointer to doclist for this term */
int nDoclist; /* Size of doclist in bytes */
/* Get the term and doclist for this entry. */
| | < | 243764 243765 243766 243767 243768 243769 243770 243771 243772 243773 243774 243775 243776 243777 243778 |
while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
const char *zTerm; /* Buffer containing term */
int nTerm; /* Size of zTerm in bytes */
const u8 *pDoclist; /* Pointer to doclist for this term */
int nDoclist; /* Size of doclist in bytes */
/* Get the term and doclist for this entry. */
sqlite3Fts5HashScanEntry(pHash, &zTerm, &nTerm, &pDoclist, &nDoclist);
if( bSecureDelete==0 ){
fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm);
if( p->rc!=SQLITE_OK ) break;
assert( writer.bFirstRowidInPage==0 );
}
if( !bSecureDelete && pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
|
| ︙ | ︙ | |||
241816 241817 241818 241819 241820 241821 241822 |
/* If in secure delete mode, and if this entry in the poslist is
** in fact a delete, then edit the existing segments directly
** using fts5FlushSecureDelete(). */
if( bSecureDelete ){
if( eDetail==FTS5_DETAIL_NONE ){
if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
| | | | 243794 243795 243796 243797 243798 243799 243800 243801 243802 243803 243804 243805 243806 243807 243808 243809 243810 243811 243812 243813 243814 243815 243816 243817 243818 |
/* If in secure delete mode, and if this entry in the poslist is
** in fact a delete, then edit the existing segments directly
** using fts5FlushSecureDelete(). */
if( bSecureDelete ){
if( eDetail==FTS5_DETAIL_NONE ){
if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
iOff++;
if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
iOff++;
nDoclist = 0;
}else{
continue;
}
}
}else if( (pDoclist[iOff] & 0x01) ){
fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
if( p->rc!=SQLITE_OK || pDoclist[iOff]==0x01 ){
iOff++;
continue;
}
}
}
|
| ︙ | ︙ | |||
241952 241953 241954 241955 241956 241957 241958 241959 241960 241961 241962 241963 241964 241965 241966 241967 241968 241969 241970 241971 241972 241973 |
}
/*
** Flush any data stored in the in-memory hash tables to the database.
*/
static void fts5IndexFlush(Fts5Index *p){
/* Unless it is empty, flush the hash table to disk */
if( p->nPendingData || p->nContentlessDelete ){
assert( p->pHash );
fts5FlushOneHash(p);
if( p->rc==SQLITE_OK ){
sqlite3Fts5HashClear(p->pHash);
p->nPendingData = 0;
p->nPendingRow = 0;
p->nContentlessDelete = 0;
}
}
}
static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Index *p,
Fts5Structure *pStruct
| > > > > > > | 243930 243931 243932 243933 243934 243935 243936 243937 243938 243939 243940 243941 243942 243943 243944 243945 243946 243947 243948 243949 243950 243951 243952 243953 243954 243955 243956 243957 |
}
/*
** Flush any data stored in the in-memory hash tables to the database.
*/
static void fts5IndexFlush(Fts5Index *p){
/* Unless it is empty, flush the hash table to disk */
if( p->flushRc ){
p->rc = p->flushRc;
return;
}
if( p->nPendingData || p->nContentlessDelete ){
assert( p->pHash );
fts5FlushOneHash(p);
if( p->rc==SQLITE_OK ){
sqlite3Fts5HashClear(p->pHash);
p->nPendingData = 0;
p->nPendingRow = 0;
p->nContentlessDelete = 0;
}else if( p->nPendingData || p->nContentlessDelete ){
p->flushRc = p->rc;
}
}
}
static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Index *p,
Fts5Structure *pStruct
|
| ︙ | ︙ | |||
242446 242447 242448 242449 242450 242451 242452 | static void fts5SetupPrefixIter( Fts5Index *p, /* Index to read from */ int bDesc, /* True for "ORDER BY rowid DESC" */ int iIdx, /* Index to scan for data */ u8 *pToken, /* Buffer containing prefix to match */ int nToken, /* Size of buffer pToken in bytes */ Fts5Colset *pColset, /* Restrict matches to these columns */ | | > | > > > > > > | 244430 244431 244432 244433 244434 244435 244436 244437 244438 244439 244440 244441 244442 244443 244444 244445 244446 244447 244448 244449 244450 244451 244452 244453 244454 244455 244456 244457 244458 244459 244460 244461 244462 244463 244464 244465 244466 244467 244468 244469 244470 244471 244472 244473 244474 244475 244476 244477 244478 244479 244480 244481 244482 244483 244484 |
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
int iIdx, /* Index to scan for data */
u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
Fts5Buffer *aBuf;
int nBuf = 32;
int nMerge = 1;
void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid;
}else{
nMerge = FTS5_MERGE_NLIST-1;
nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
xMerge = fts5MergePrefixLists;
xAppend = fts5AppendPoslist;
}
aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
pStruct = fts5StructureRead(p);
assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
if( p->rc==SQLITE_OK ){
const int flags = FTS5INDEX_QUERY_SCAN
| FTS5INDEX_QUERY_SKIPEMPTY
| FTS5INDEX_QUERY_NOOUTPUT;
int i;
i64 iLastRowid = 0;
Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
Fts5Data *pData;
Fts5Buffer doclist;
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
/* If iIdx is non-zero, then it is the number of a prefix-index for
** prefixes 1 character longer than the prefix being queried for. That
** index contains all the doclists required, except for the one
** corresponding to the prefix itself. That one is extracted from the
** main term index here. */
if( iIdx!=0 ){
int dummy = 0;
const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
pToken[0] = FTS5_MAIN_PREFIX;
fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for(;
|
| ︙ | ︙ | |||
242503 242504 242505 242506 242507 242508 242509 242510 242511 242512 242513 242514 242515 242516 242517 242518 242519 242520 242521 242522 242523 242524 |
}
fts5MultiIterFree(p1);
}
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
fts5MultiIterEof(p, p1)==0;
fts5MultiIterNext2(p, p1, &bNewTerm)
){
Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
int nTerm = pSeg->term.n;
const u8 *pTerm = pSeg->term.p;
p1->xSetOutputs(p1, pSeg);
assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
if( bNewTerm ){
if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
}
if( p1->base.nData==0 ) continue;
| > < | 244494 244495 244496 244497 244498 244499 244500 244501 244502 244503 244504 244505 244506 244507 244508 244509 244510 244511 244512 244513 244514 244515 244516 244517 244518 244519 244520 244521 244522 244523 |
}
fts5MultiIterFree(p1);
}
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
fts5MultiIterEof(p, p1)==0;
fts5MultiIterNext2(p, p1, &bNewTerm)
){
Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
int nTerm = pSeg->term.n;
const u8 *pTerm = pSeg->term.p;
p1->xSetOutputs(p1, pSeg);
assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
if( bNewTerm ){
if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
}
if( p1->base.nData==0 ) continue;
if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
int i1 = i*nMerge;
int iStore;
assert( i1+nMerge<=nBuf );
for(iStore=i1; iStore<i1+nMerge; iStore++){
if( aBuf[iStore].n==0 ){
|
| ︙ | ︙ | |||
242557 242558 242559 242560 242561 242562 242563 |
}
for(iFree=i; iFree<i+nMerge; iFree++){
fts5BufferFree(&aBuf[iFree]);
}
}
fts5MultiIterFree(p1);
| | | 244548 244549 244550 244551 244552 244553 244554 244555 244556 244557 244558 244559 244560 244561 244562 |
}
for(iFree=i; iFree<i+nMerge; iFree++){
fts5BufferFree(&aBuf[iFree]);
}
}
fts5MultiIterFree(p1);
pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING);
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
fts5MultiIterNew2(p, pData, bDesc, ppIter);
}
fts5BufferFree(&doclist);
|
| ︙ | ︙ | |||
242700 242701 242702 242703 242704 242705 242706 242707 242708 242709 242710 242711 242712 242713 |
assert( p->pReader==0 );
fts5StructureInvalidate(p);
sqlite3_finalize(p->pWriter);
sqlite3_finalize(p->pDeleter);
sqlite3_finalize(p->pIdxWriter);
sqlite3_finalize(p->pIdxDeleter);
sqlite3_finalize(p->pIdxSelect);
sqlite3_finalize(p->pDataVersion);
sqlite3_finalize(p->pDeleteFromIdx);
sqlite3Fts5HashFree(p->pHash);
sqlite3_free(p->zDataTbl);
sqlite3_free(p);
}
return rc;
| > | 244691 244692 244693 244694 244695 244696 244697 244698 244699 244700 244701 244702 244703 244704 244705 |
assert( p->pReader==0 );
fts5StructureInvalidate(p);
sqlite3_finalize(p->pWriter);
sqlite3_finalize(p->pDeleter);
sqlite3_finalize(p->pIdxWriter);
sqlite3_finalize(p->pIdxDeleter);
sqlite3_finalize(p->pIdxSelect);
sqlite3_finalize(p->pIdxNextSelect);
sqlite3_finalize(p->pDataVersion);
sqlite3_finalize(p->pDeleteFromIdx);
sqlite3Fts5HashFree(p->pHash);
sqlite3_free(p->zDataTbl);
sqlite3_free(p);
}
return rc;
|
| ︙ | ︙ | |||
242794 242795 242796 242797 242798 242799 242800 242801 242802 242803 242804 242805 242806 242807 |
nByte
);
}
}
return rc;
}
/*
** Open a new iterator to iterate though all rowid that match the
** specified token or token prefix.
*/
static int sqlite3Fts5IndexQuery(
Fts5Index *p, /* FTS index to query */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 244786 244787 244788 244789 244790 244791 244792 244793 244794 244795 244796 244797 244798 244799 244800 244801 244802 244803 244804 244805 244806 244807 244808 244809 244810 244811 244812 244813 244814 244815 244816 244817 244818 244819 244820 244821 244822 244823 244824 244825 244826 244827 244828 244829 244830 244831 244832 244833 244834 244835 244836 244837 244838 244839 244840 244841 244842 244843 244844 244845 244846 244847 244848 244849 244850 244851 244852 244853 244854 244855 244856 244857 244858 244859 244860 244861 244862 244863 244864 244865 244866 244867 244868 244869 244870 244871 244872 244873 244874 244875 244876 244877 244878 244879 244880 244881 244882 244883 244884 244885 244886 244887 244888 244889 244890 244891 244892 244893 244894 244895 244896 244897 244898 244899 244900 244901 244902 244903 244904 244905 244906 244907 244908 244909 244910 244911 244912 244913 244914 244915 244916 244917 244918 244919 244920 244921 244922 244923 244924 244925 244926 244927 244928 244929 244930 244931 244932 244933 244934 244935 244936 244937 244938 244939 244940 244941 244942 244943 244944 244945 244946 244947 244948 244949 244950 244951 244952 244953 244954 244955 244956 244957 244958 244959 244960 244961 244962 244963 244964 244965 244966 244967 244968 244969 244970 244971 244972 244973 244974 244975 244976 244977 244978 244979 244980 244981 244982 244983 244984 244985 244986 244987 244988 244989 244990 244991 244992 244993 244994 244995 244996 244997 244998 244999 245000 245001 245002 245003 245004 245005 245006 245007 245008 245009 245010 245011 245012 245013 245014 245015 245016 245017 245018 245019 245020 245021 245022 245023 245024 245025 245026 245027 245028 245029 245030 245031 245032 245033 245034 245035 245036 245037 245038 245039 245040 245041 245042 245043 245044 245045 245046 245047 245048 245049 245050 245051 245052 245053 245054 245055 245056 245057 245058 245059 245060 245061 245062 245063 245064 245065 245066 245067 245068 245069 245070 245071 245072 245073 245074 245075 245076 245077 245078 245079 245080 245081 245082 245083 245084 245085 245086 245087 245088 245089 245090 245091 245092 245093 245094 245095 245096 245097 245098 245099 245100 245101 245102 245103 245104 245105 245106 245107 245108 245109 245110 245111 245112 245113 245114 245115 245116 245117 245118 245119 245120 245121 245122 245123 245124 245125 245126 245127 245128 245129 245130 245131 245132 245133 245134 245135 245136 245137 245138 245139 245140 245141 245142 245143 245144 245145 245146 245147 245148 245149 245150 245151 245152 245153 245154 245155 245156 245157 245158 245159 245160 245161 245162 245163 245164 245165 245166 245167 245168 245169 245170 245171 245172 245173 245174 245175 245176 245177 245178 245179 245180 245181 245182 245183 245184 245185 245186 245187 245188 245189 245190 245191 245192 245193 245194 245195 245196 245197 245198 245199 245200 245201 245202 245203 245204 245205 245206 245207 245208 245209 245210 245211 245212 245213 245214 245215 245216 245217 245218 245219 245220 245221 245222 245223 245224 245225 245226 245227 245228 245229 245230 245231 245232 245233 245234 245235 245236 245237 245238 245239 245240 245241 245242 245243 245244 245245 245246 245247 |
nByte
);
}
}
return rc;
}
/*
** pToken points to a buffer of size nToken bytes containing a search
** term, including the index number at the start, used on a tokendata=1
** table. This function returns true if the term in buffer pBuf matches
** token pToken/nToken.
*/
static int fts5IsTokendataPrefix(
Fts5Buffer *pBuf,
const u8 *pToken,
int nToken
){
return (
pBuf->n>=nToken
&& 0==memcmp(pBuf->p, pToken, nToken)
&& (pBuf->n==nToken || pBuf->p[nToken]==0x00)
);
}
/*
** Ensure the segment-iterator passed as the only argument points to EOF.
*/
static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
fts5DataRelease(pSeg->pLeaf);
pSeg->pLeaf = 0;
}
/*
** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
** array of these for each row it visits. Or, for an iterator used by an
** "ORDER BY rank" query, it accumulates an array of these for the entire
** query.
**
** Each instance in the array indicates the iterator (and therefore term)
** associated with position iPos of rowid iRowid. This is used by the
** xInstToken() API.
*/
struct Fts5TokenDataMap {
i64 iRowid; /* Row this token is located in */
i64 iPos; /* Position of token */
int iIter; /* Iterator token was read from */
};
/*
** An object used to supplement Fts5Iter for tokendata=1 iterators.
*/
struct Fts5TokenDataIter {
int nIter;
int nIterAlloc;
int nMap;
int nMapAlloc;
Fts5TokenDataMap *aMap;
Fts5PoslistReader *aPoslistReader;
int *aPoslistToIter;
Fts5Iter *apIter[1];
};
/*
** This function appends iterator pAppend to Fts5TokenDataIter pIn and
** returns the result.
*/
static Fts5TokenDataIter *fts5AppendTokendataIter(
Fts5Index *p, /* Index object (for error code) */
Fts5TokenDataIter *pIn, /* Current Fts5TokenDataIter struct */
Fts5Iter *pAppend /* Append this iterator */
){
Fts5TokenDataIter *pRet = pIn;
if( p->rc==SQLITE_OK ){
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
}else{
if( pIn==0 ) memset(pNew, 0, nByte);
pRet = pNew;
pNew->nIterAlloc = nAlloc;
}
}
}
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pAppend);
}else{
pRet->apIter[pRet->nIter++] = pAppend;
}
assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
return pRet;
}
/*
** Delete an Fts5TokenDataIter structure and its contents.
*/
static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
if( pSet ){
int ii;
for(ii=0; ii<pSet->nIter; ii++){
fts5MultiIterFree(pSet->apIter[ii]);
}
sqlite3_free(pSet->aPoslistReader);
sqlite3_free(pSet->aMap);
sqlite3_free(pSet);
}
}
/*
** Append a mapping to the token-map belonging to object pT.
*/
static void fts5TokendataIterAppendMap(
Fts5Index *p,
Fts5TokenDataIter *pT,
int iIter,
i64 iRowid,
i64 iPos
){
if( p->rc==SQLITE_OK ){
if( pT->nMap==pT->nMapAlloc ){
int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
int nByte = nNew * sizeof(Fts5TokenDataMap);
Fts5TokenDataMap *aNew;
aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte);
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
return;
}
pT->aMap = aNew;
pT->nMapAlloc = nNew;
}
pT->aMap[pT->nMap].iRowid = iRowid;
pT->aMap[pT->nMap].iPos = iPos;
pT->aMap[pT->nMap].iIter = iIter;
pT->nMap++;
}
}
/*
** The iterator passed as the only argument must be a tokendata=1 iterator
** (pIter->pTokenDataIter!=0). This function sets the iterator output
** variables (pIter->base.*) according to the contents of the current
** row.
*/
static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
int ii;
int nHit = 0;
i64 iRowid = SMALLEST_INT64;
int iMin = 0;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
pIter->base.nData = 0;
pIter->base.pData = 0;
for(ii=0; ii<pT->nIter; ii++){
Fts5Iter *p = pT->apIter[ii];
if( p->base.bEof==0 ){
if( nHit==0 || p->base.iRowid<iRowid ){
iRowid = p->base.iRowid;
nHit = 1;
pIter->base.pData = p->base.pData;
pIter->base.nData = p->base.nData;
iMin = ii;
}else if( p->base.iRowid==iRowid ){
nHit++;
}
}
}
if( nHit==0 ){
pIter->base.bEof = 1;
}else{
int eDetail = pIter->pIndex->pConfig->eDetail;
pIter->base.bEof = 0;
pIter->base.iRowid = iRowid;
if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1);
}else
if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
int nReader = 0;
int nByte = 0;
i64 iPrev = 0;
/* Allocate array of iterators if they are not already allocated. */
if( pT->aPoslistReader==0 ){
pT->aPoslistReader = (Fts5PoslistReader*)sqlite3Fts5MallocZero(
&pIter->pIndex->rc,
pT->nIter * (sizeof(Fts5PoslistReader) + sizeof(int))
);
if( pT->aPoslistReader==0 ) return;
pT->aPoslistToIter = (int*)&pT->aPoslistReader[pT->nIter];
}
/* Populate an iterator for each poslist that will be merged */
for(ii=0; ii<pT->nIter; ii++){
Fts5Iter *p = pT->apIter[ii];
if( iRowid==p->base.iRowid ){
pT->aPoslistToIter[nReader] = ii;
sqlite3Fts5PoslistReaderInit(
p->base.pData, p->base.nData, &pT->aPoslistReader[nReader++]
);
nByte += p->base.nData;
}
}
/* Ensure the output buffer is large enough */
if( fts5BufferGrow(&pIter->pIndex->rc, &pIter->poslist, nByte+nHit*10) ){
return;
}
/* Ensure the token-mapping is large enough */
if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){
int nNew = (pT->nMapAlloc + nByte) * 2;
Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc(
pT->aMap, nNew*sizeof(Fts5TokenDataMap)
);
if( aNew==0 ){
pIter->pIndex->rc = SQLITE_NOMEM;
return;
}
pT->aMap = aNew;
pT->nMapAlloc = nNew;
}
pIter->poslist.n = 0;
while( 1 ){
i64 iMinPos = LARGEST_INT64;
/* Find smallest position */
iMin = 0;
for(ii=0; ii<nReader; ii++){
Fts5PoslistReader *pReader = &pT->aPoslistReader[ii];
if( pReader->bEof==0 ){
if( pReader->iPos<iMinPos ){
iMinPos = pReader->iPos;
iMin = ii;
}
}
}
/* If all readers were at EOF, break out of the loop. */
if( iMinPos==LARGEST_INT64 ) break;
sqlite3Fts5PoslistSafeAppend(&pIter->poslist, &iPrev, iMinPos);
sqlite3Fts5PoslistReaderNext(&pT->aPoslistReader[iMin]);
if( eDetail==FTS5_DETAIL_FULL ){
pT->aMap[pT->nMap].iPos = iMinPos;
pT->aMap[pT->nMap].iIter = pT->aPoslistToIter[iMin];
pT->aMap[pT->nMap].iRowid = iRowid;
pT->nMap++;
}
}
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}
}
/*
** The iterator passed as the only argument must be a tokendata=1 iterator
** (pIter->pTokenDataIter!=0). This function advances the iterator. If
** argument bFrom is false, then the iterator is advanced to the next
** entry. Or, if bFrom is true, it is advanced to the first entry with
** a rowid of iFrom or greater.
*/
static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){
int ii;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
for(ii=0; ii<pT->nIter; ii++){
Fts5Iter *p = pT->apIter[ii];
if( p->base.bEof==0
&& (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowid<iFrom))
){
fts5MultiIterNext(p->pIndex, p, bFrom, iFrom);
while( bFrom && p->base.bEof==0
&& p->base.iRowid<iFrom
&& p->pIndex->rc==SQLITE_OK
){
fts5MultiIterNext(p->pIndex, p, 0, 0);
}
}
}
fts5IterSetOutputsTokendata(pIter);
}
/*
** If the segment-iterator passed as the first argument is at EOF, then
** set pIter->term to a copy of buffer pTerm.
*/
static void fts5TokendataSetTermIfEof(Fts5Iter *pIter, Fts5Buffer *pTerm){
if( pIter && pIter->aSeg[0].pLeaf==0 ){
fts5BufferSet(&pIter->pIndex->rc, &pIter->aSeg[0].term, pTerm->n, pTerm->p);
}
}
/*
** This function sets up an iterator to use for a non-prefix query on a
** tokendata=1 table.
*/
static Fts5Iter *fts5SetupTokendataIter(
Fts5Index *p, /* FTS index to query */
const u8 *pToken, /* Buffer containing query term */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset /* Colset to filter on */
){
Fts5Iter *pRet = 0;
Fts5TokenDataIter *pSet = 0;
Fts5Structure *pStruct = 0;
const int flags = FTS5INDEX_QUERY_SCANONETERM | FTS5INDEX_QUERY_SCAN;
Fts5Buffer bSeek = {0, 0, 0};
Fts5Buffer *pSmall = 0;
fts5IndexFlush(p);
pStruct = fts5StructureRead(p);
while( p->rc==SQLITE_OK ){
Fts5Iter *pPrev = pSet ? pSet->apIter[pSet->nIter-1] : 0;
Fts5Iter *pNew = 0;
Fts5SegIter *pNewIter = 0;
Fts5SegIter *pPrevIter = 0;
int iLvl, iSeg, ii;
pNew = fts5MultiIterAlloc(p, pStruct->nSegment);
if( pSmall ){
fts5BufferSet(&p->rc, &bSeek, pSmall->n, pSmall->p);
fts5BufferAppendBlob(&p->rc, &bSeek, 1, (const u8*)"\0");
}else{
fts5BufferSet(&p->rc, &bSeek, nToken, pToken);
}
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
break;
}
pNewIter = &pNew->aSeg[0];
pPrevIter = (pPrev ? &pPrev->aSeg[0] : 0);
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){
Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
int bDone = 0;
if( pPrevIter ){
if( fts5BufferCompare(pSmall, &pPrevIter->term) ){
memcpy(pNewIter, pPrevIter, sizeof(Fts5SegIter));
memset(pPrevIter, 0, sizeof(Fts5SegIter));
bDone = 1;
}else if( pPrevIter->iEndofDoclist>pPrevIter->pLeaf->szLeaf ){
fts5SegIterNextInit(p,(const char*)bSeek.p,bSeek.n-1,pSeg,pNewIter);
bDone = 1;
}
}
if( bDone==0 ){
fts5SegIterSeekInit(p, bSeek.p, bSeek.n, flags, pSeg, pNewIter);
}
if( pPrevIter ){
if( pPrevIter->pTombArray ){
pNewIter->pTombArray = pPrevIter->pTombArray;
pNewIter->pTombArray->nRef++;
}
}else{
fts5SegIterAllocTombstone(p, pNewIter);
}
pNewIter++;
if( pPrevIter ) pPrevIter++;
if( p->rc ) break;
}
}
fts5TokendataSetTermIfEof(pPrev, pSmall);
pNew->bSkipEmpty = 1;
pNew->pColset = pColset;
fts5IterSetOutputCb(&p->rc, pNew);
/* Loop through all segments in the new iterator. Find the smallest
** term that any segment-iterator points to. Iterator pNew will be
** used for this term. Also, set any iterator that points to a term that
** does not match pToken/nToken to point to EOF */
pSmall = 0;
for(ii=0; ii<pNew->nSeg; ii++){
Fts5SegIter *pII = &pNew->aSeg[ii];
if( 0==fts5IsTokendataPrefix(&pII->term, pToken, nToken) ){
fts5SegIterSetEOF(pII);
}
if( pII->pLeaf && (!pSmall || fts5BufferCompare(pSmall, &pII->term)>0) ){
pSmall = &pII->term;
}
}
/* If pSmall is still NULL at this point, then the new iterator does
** not point to any terms that match the query. So delete it and break
** out of the loop - all required iterators have been collected. */
if( pSmall==0 ){
sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
break;
}
/* Append this iterator to the set and continue. */
pSet = fts5AppendTokendataIter(p, pSet, pNew);
}
if( p->rc==SQLITE_OK && pSet ){
int ii;
for(ii=0; ii<pSet->nIter; ii++){
Fts5Iter *pIter = pSet->apIter[ii];
int iSeg;
for(iSeg=0; iSeg<pIter->nSeg; iSeg++){
pIter->aSeg[iSeg].flags |= FTS5_SEGITER_ONETERM;
}
fts5MultiIterFinishSetup(p, pIter);
}
}
if( p->rc==SQLITE_OK ){
pRet = fts5MultiIterAlloc(p, 0);
}
if( pRet ){
pRet->pTokenDataIter = pSet;
if( pSet ){
fts5IterSetOutputsTokendata(pRet);
}else{
pRet->base.bEof = 1;
}
}else{
fts5TokendataIterDelete(pSet);
}
fts5StructureRelease(pStruct);
fts5BufferFree(&bSeek);
return pRet;
}
/*
** Open a new iterator to iterate though all rowid that match the
** specified token or token prefix.
*/
static int sqlite3Fts5IndexQuery(
Fts5Index *p, /* FTS index to query */
|
| ︙ | ︙ | |||
242816 242817 242818 242819 242820 242821 242822 242823 242824 242825 242826 242827 242828 242829 242830 |
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
int iPrefixIdx = 0; /* +1 prefix index */
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
** is a prefix query for which there is no prefix index, set iIdx to
** greater than pConfig->nPrefix to indicate that the query will be
** satisfied by scanning multiple terms in the main index.
**
** If the QUERY_TEST_NOIDX flag was specified, then this must be a
| > > > > > | 245256 245257 245258 245259 245260 245261 245262 245263 245264 245265 245266 245267 245268 245269 245270 245271 245272 245273 245274 245275 |
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
int iPrefixIdx = 0; /* +1 prefix index */
int bTokendata = pConfig->bTokendata;
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
bTokendata = 0;
}
/* Figure out which index to search and set iIdx accordingly. If this
** is a prefix query for which there is no prefix index, set iIdx to
** greater than pConfig->nPrefix to indicate that the query will be
** satisfied by scanning multiple terms in the main index.
**
** If the QUERY_TEST_NOIDX flag was specified, then this must be a
|
| ︙ | ︙ | |||
242843 242844 242845 242846 242847 242848 242849 |
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
int nIdxChar = pConfig->aPrefix[iIdx-1];
if( nIdxChar==nChar ) break;
if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
| > > > | | 245288 245289 245290 245291 245292 245293 245294 245295 245296 245297 245298 245299 245300 245301 245302 245303 245304 245305 |
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
int nIdxChar = pConfig->aPrefix[iIdx-1];
if( nIdxChar==nChar ) break;
if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
if( bTokendata && iIdx==0 ){
buf.p[0] = '0';
pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
}else if( iIdx<=pConfig->nPrefix ){
/* Straight index lookup */
Fts5Structure *pStruct = fts5StructureRead(p);
buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
if( pStruct ){
fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY,
pColset, buf.p, nToken+1, -1, 0, &pRet
);
|
| ︙ | ︙ | |||
242890 242891 242892 242893 242894 242895 242896 |
*/
/*
** Move to the next matching rowid.
*/
static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
assert( pIter->pIndex->rc==SQLITE_OK );
| > > > | > | 245338 245339 245340 245341 245342 245343 245344 245345 245346 245347 245348 245349 245350 245351 245352 245353 245354 245355 245356 |
*/
/*
** Move to the next matching rowid.
*/
static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
assert( pIter->pIndex->rc==SQLITE_OK );
if( pIter->pTokenDataIter ){
fts5TokendataIterNext(pIter, 0, 0);
}else{
fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
}
return fts5IndexReturn(pIter->pIndex);
}
/*
** Move to the next matching term/rowid. Used by the fts5vocab module.
*/
static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){
|
| ︙ | ︙ | |||
242923 242924 242925 242926 242927 242928 242929 |
/*
** Move to the next matching rowid that occurs at or after iMatch. The
** definition of "at or after" depends on whether this iterator iterates
** in ascending or descending rowid order.
*/
static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
| > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 245375 245376 245377 245378 245379 245380 245381 245382 245383 245384 245385 245386 245387 245388 245389 245390 245391 245392 245393 245394 245395 245396 245397 245398 245399 245400 245401 245402 245403 245404 245405 245406 245407 245408 245409 245410 245411 245412 245413 245414 245415 245416 245417 245418 245419 245420 245421 245422 245423 245424 245425 245426 245427 245428 245429 245430 245431 245432 245433 245434 245435 245436 245437 245438 245439 245440 245441 245442 245443 245444 245445 245446 245447 245448 245449 245450 245451 245452 245453 245454 245455 245456 245457 245458 245459 245460 245461 245462 245463 245464 245465 245466 245467 245468 245469 245470 245471 245472 245473 245474 245475 245476 245477 245478 245479 245480 245481 245482 245483 245484 245485 245486 245487 245488 245489 245490 245491 245492 245493 245494 245495 245496 245497 245498 245499 245500 245501 245502 245503 245504 245505 245506 245507 245508 |
/*
** Move to the next matching rowid that occurs at or after iMatch. The
** definition of "at or after" depends on whether this iterator iterates
** in ascending or descending rowid order.
*/
static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
if( pIter->pTokenDataIter ){
fts5TokendataIterNext(pIter, 1, iMatch);
}else{
fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
}
return fts5IndexReturn(pIter->pIndex);
}
/*
** Return the current term.
*/
static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
int n;
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
assert_nc( z || n<=1 );
*pn = n-1;
return (z ? &z[1] : 0);
}
/*
** This is used by xInstToken() to access the token at offset iOff, column
** iCol of row iRowid. The token is returned via output variables *ppOut
** and *pnOut. The iterator passed as the first argument must be a tokendata=1
** iterator (pIter->pTokenDataIter!=0).
*/
static int sqlite3Fts5IterToken(
Fts5IndexIter *pIndexIter,
i64 iRowid,
int iCol,
int iOff,
const char **ppOut, int *pnOut
){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
Fts5TokenDataMap *aMap = pT->aMap;
i64 iPos = (((i64)iCol)<<32) + iOff;
int i1 = 0;
int i2 = pT->nMap;
int iTest = 0;
while( i2>i1 ){
iTest = (i1 + i2) / 2;
if( aMap[iTest].iRowid<iRowid ){
i1 = iTest+1;
}else if( aMap[iTest].iRowid>iRowid ){
i2 = iTest;
}else{
if( aMap[iTest].iPos<iPos ){
if( aMap[iTest].iPos<0 ){
break;
}
i1 = iTest+1;
}else if( aMap[iTest].iPos>iPos ){
i2 = iTest;
}else{
break;
}
}
}
if( i2>i1 ){
Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
*ppOut = (const char*)pMap->aSeg[0].term.p+1;
*pnOut = pMap->aSeg[0].term.n-1;
}
return SQLITE_OK;
}
/*
** Clear any existing entries from the token-map associated with the
** iterator passed as the only argument.
*/
static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
if( pIter && pIter->pTokenDataIter ){
pIter->pTokenDataIter->nMap = 0;
}
}
/*
** Set a token-mapping for the iterator passed as the first argument. This
** is used in detail=column or detail=none mode when a token is requested
** using the xInstToken() API. In this case the caller tokenizers the
** current row and configures the token-mapping via multiple calls to this
** function.
*/
static int sqlite3Fts5IndexIterWriteTokendata(
Fts5IndexIter *pIndexIter,
const char *pToken, int nToken,
i64 iRowid, int iCol, int iOff
){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
Fts5Index *p = pIter->pIndex;
int ii;
assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
assert( pIter->pTokenDataIter );
for(ii=0; ii<pT->nIter; ii++){
Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
}
if( ii<pT->nIter ){
fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff);
}
return fts5IndexReturn(p);
}
/*
** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
*/
static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
if( pIndexIter ){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5Index *pIndex = pIter->pIndex;
fts5TokendataIterDelete(pIter->pTokenDataIter);
fts5MultiIterFree(pIter);
sqlite3Fts5IndexCloseReader(pIndex);
}
}
/*
** Read and decode the "averages" record from the database.
|
| ︙ | ︙ | |||
243452 243453 243454 243455 243456 243457 243458 |
int n, /* Size of index key in bytes */
int flags, /* Flags for Fts5IndexQuery */
u64 *pCksum /* IN/OUT: Checksum value */
){
int eDetail = p->pConfig->eDetail;
u64 cksum = *pCksum;
Fts5IndexIter *pIter = 0;
| | > > | 246002 246003 246004 246005 246006 246007 246008 246009 246010 246011 246012 246013 246014 246015 246016 246017 246018 |
int n, /* Size of index key in bytes */
int flags, /* Flags for Fts5IndexQuery */
u64 *pCksum /* IN/OUT: Checksum value */
){
int eDetail = p->pConfig->eDetail;
u64 cksum = *pCksum;
Fts5IndexIter *pIter = 0;
int rc = sqlite3Fts5IndexQuery(
p, z, n, (flags | FTS5INDEX_QUERY_NOTOKENDATA), 0, &pIter
);
while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){
i64 rowid = pIter->iRowid;
if( eDetail==FTS5_DETAIL_NONE ){
cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
}else{
|
| ︙ | ︙ | |||
244149 244150 244151 244152 244153 244154 244155 244156 244157 244158 244159 244160 244161 244162 |
}
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
sqlite3_context *pCtx, /* Function call context */
| > > > > > > > > > > > > > > > > > > | 246701 246702 246703 246704 246705 246706 246707 246708 246709 246710 246711 246712 246713 246714 246715 246716 246717 246718 246719 246720 246721 246722 246723 246724 246725 246726 246727 246728 246729 246730 246731 246732 |
}
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
static void fts5BufferAppendTerm(int *pRc, Fts5Buffer *pBuf, Fts5Buffer *pTerm){
int ii;
fts5BufferGrow(pRc, pBuf, pTerm->n*2 + 1);
if( *pRc==SQLITE_OK ){
for(ii=0; ii<pTerm->n; ii++){
if( pTerm->p[ii]==0x00 ){
pBuf->p[pBuf->n++] = '\\';
pBuf->p[pBuf->n++] = '0';
}else{
pBuf->p[pBuf->n++] = pTerm->p[ii];
}
}
pBuf->p[pBuf->n] = 0x00;
}
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
sqlite3_context *pCtx, /* Function call context */
|
| ︙ | ︙ | |||
244257 244258 244259 244260 244261 244262 244263 |
while( iOff<szLeaf && rc==SQLITE_OK ){
int nAppend;
/* Read the term data for the next term*/
iOff += fts5GetVarint32(&a[iOff], nAppend);
term.n = nKeep;
fts5BufferAppendBlob(&rc, &term, nAppend, &a[iOff]);
| | | < | 246827 246828 246829 246830 246831 246832 246833 246834 246835 246836 246837 246838 246839 246840 246841 246842 |
while( iOff<szLeaf && rc==SQLITE_OK ){
int nAppend;
/* Read the term data for the next term*/
iOff += fts5GetVarint32(&a[iOff], nAppend);
term.n = nKeep;
fts5BufferAppendBlob(&rc, &term, nAppend, &a[iOff]);
sqlite3Fts5BufferAppendPrintf(&rc, &s, " term=");
fts5BufferAppendTerm(&rc, &s, &term);
iOff += nAppend;
/* Figure out where the doclist for this term ends */
if( iPgidxOff<n ){
int nIncr;
iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nIncr);
iTermOff += nIncr;
|
| ︙ | ︙ | |||
244367 244368 244369 244370 244371 244372 244373 |
if( iOff+nByte>n ){
rc = FTS5_CORRUPT;
break;
}
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
| | | < | 246936 246937 246938 246939 246940 246941 246942 246943 246944 246945 246946 246947 246948 246949 246950 246951 |
if( iOff+nByte>n ){
rc = FTS5_CORRUPT;
break;
}
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
sqlite3Fts5BufferAppendPrintf(&rc, &s, " term=");
fts5BufferAppendTerm(&rc, &s, &term);
iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff);
}
fts5BufferFree(&term);
}
decode_out:
|
| ︙ | ︙ | |||
244844 244845 244846 244847 244848 244849 244850 |
struct Fts5FullTable {
Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
int iSavepoint; /* Successful xSavepoint()+1 */
| | | 247412 247413 247414 247415 247416 247417 247418 247419 247420 247421 247422 247423 247424 247425 247426 |
struct Fts5FullTable {
Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
int iSavepoint; /* Successful xSavepoint()+1 */
#ifdef SQLITE_DEBUG
struct Fts5TransactionState ts;
#endif
};
struct Fts5MatchPhrase {
Fts5Buffer *pPoslist; /* Pointer to current poslist */
|
| ︙ | ︙ | |||
245382 245383 245384 245385 245386 245387 245388 |
bSeenGt = 1;
}
}
}
}
idxStr[iIdxStr] = '\0';
| | > > > | | 247950 247951 247952 247953 247954 247955 247956 247957 247958 247959 247960 247961 247962 247963 247964 247965 247966 247967 247968 247969 247970 247971 247972 |
bSeenGt = 1;
}
}
}
}
idxStr[iIdxStr] = '\0';
/* Set idxFlags flags for the ORDER BY clause
**
** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
*/
if( pInfo->nOrderBy==1 ){
int iSort = pInfo->aOrderBy[0].iColumn;
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
idxFlags |= FTS5_BI_ORDER_RANK;
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
idxFlags |= FTS5_BI_ORDER_ROWID;
}
if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
pInfo->orderByConsumed = 1;
if( pInfo->aOrderBy[0].desc ){
idxFlags |= FTS5_BI_ORDER_DESC;
}
|
| ︙ | ︙ | |||
245638 245639 245640 245641 245642 245643 245644 245645 245646 245647 245648 245649 245650 245651 |
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc;
assert( (pCsr->ePlan<3)==
(pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
);
assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
if( pCsr->ePlan<3 ){
int bSkip = 0;
if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
fts5CsrNewrow(pCsr);
| > > > > > > > > > > | 248209 248210 248211 248212 248213 248214 248215 248216 248217 248218 248219 248220 248221 248222 248223 248224 248225 248226 248227 248228 248229 248230 248231 248232 |
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc;
assert( (pCsr->ePlan<3)==
(pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
);
assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
/* If this cursor uses FTS5_PLAN_MATCH and this is a tokendata=1 table,
** clear any token mappings accumulated at the fts5_index.c level. In
** other cases, specifically FTS5_PLAN_SOURCE and FTS5_PLAN_SORTED_MATCH,
** we need to retain the mappings for the entire query. */
if( pCsr->ePlan==FTS5_PLAN_MATCH
&& ((Fts5Table*)pCursor->pVtab)->pConfig->bTokendata
){
sqlite3Fts5ExprClearTokens(pCsr->pExpr);
}
if( pCsr->ePlan<3 ){
int bSkip = 0;
if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
fts5CsrNewrow(pCsr);
|
| ︙ | ︙ | |||
246789 246790 246791 246792 246793 246794 246795 |
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
|| SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
){
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
rc = SQLITE_RANGE;
| < < < < < < | 249370 249371 249372 249373 249374 249375 249376 249377 249378 249379 249380 249381 249382 249383 |
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
|| SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
){
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
rc = SQLITE_RANGE;
}else{
*piPhrase = pCsr->aInst[iIdx*3];
*piCol = pCsr->aInst[iIdx*3 + 1];
*piOff = pCsr->aInst[iIdx*3 + 2];
}
}
return rc;
|
| ︙ | ︙ | |||
247049 247050 247051 247052 247053 247054 247055 247056 247057 247058 247059 247060 247061 |
}
}
}
return rc;
}
static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
);
static const Fts5ExtensionApi sFts5Api = {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | 249624 249625 249626 249627 249628 249629 249630 249631 249632 249633 249634 249635 249636 249637 249638 249639 249640 249641 249642 249643 249644 249645 249646 249647 249648 249649 249650 249651 249652 249653 249654 249655 249656 249657 249658 249659 249660 249661 249662 249663 249664 249665 249666 249667 249668 249669 249670 249671 249672 249673 249674 249675 249676 249677 249678 249679 249680 249681 249682 249683 249684 249685 249686 249687 249688 249689 249690 249691 249692 249693 249694 249695 249696 249697 249698 249699 249700 249701 249702 249703 249704 249705 249706 249707 249708 |
}
}
}
return rc;
}
/*
** xQueryToken() API implemenetation.
*/
static int fts5ApiQueryToken(
Fts5Context* pCtx,
int iPhrase,
int iToken,
const char **ppOut,
int *pnOut
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
return sqlite3Fts5ExprQueryToken(pCsr->pExpr, iPhrase, iToken, ppOut, pnOut);
}
/*
** xInstToken() API implemenetation.
*/
static int fts5ApiInstToken(
Fts5Context *pCtx,
int iIdx,
int iToken,
const char **ppOut, int *pnOut
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
|| SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
){
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
rc = SQLITE_RANGE;
}else{
int iPhrase = pCsr->aInst[iIdx*3];
int iCol = pCsr->aInst[iIdx*3 + 1];
int iOff = pCsr->aInst[iIdx*3 + 2];
i64 iRowid = fts5CursorRowid(pCsr);
rc = sqlite3Fts5ExprInstToken(
pCsr->pExpr, iRowid, iPhrase, iCol, iOff, iToken, ppOut, pnOut
);
}
}
return rc;
}
static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
);
static const Fts5ExtensionApi sFts5Api = {
3, /* iVersion */
fts5ApiUserData,
fts5ApiColumnCount,
fts5ApiRowCount,
fts5ApiColumnTotalSize,
fts5ApiTokenize,
fts5ApiPhraseCount,
fts5ApiPhraseSize,
fts5ApiInstCount,
fts5ApiInst,
fts5ApiRowid,
fts5ApiColumnText,
fts5ApiColumnSize,
fts5ApiQueryPhrase,
fts5ApiSetAuxdata,
fts5ApiGetAuxdata,
fts5ApiPhraseFirst,
fts5ApiPhraseNext,
fts5ApiPhraseFirstColumn,
fts5ApiPhraseNextColumn,
fts5ApiQueryToken,
fts5ApiInstToken
};
/*
** Implementation of API function xQueryPhrase().
*/
static int fts5ApiQueryPhrase(
Fts5Context *pCtx,
|
| ︙ | ︙ | |||
247341 247342 247343 247344 247345 247346 247347 |
*/
static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
int rc;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
| < < | | < < < < < < < < < < < < | | | < < | 249961 249962 249963 249964 249965 249966 249967 249968 249969 249970 249971 249972 249973 249974 249975 249976 249977 249978 249979 249980 249981 249982 249983 249984 249985 249986 249987 249988 249989 249990 249991 249992 249993 249994 249995 249996 249997 |
*/
static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
int rc;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);
return rc;
}
static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
fts5TripCursors((Fts5FullTable*)pTab);
return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
}
/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
int rc = SQLITE_OK;
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
if( rc==SQLITE_OK ){
pTab->iSavepoint = iSavepoint+1;
}
return rc;
}
/*
** The xRelease() method.
**
** This is a no-op.
|
| ︙ | ︙ | |||
247617 247618 247619 247620 247621 247622 247623 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
| | | 250221 250222 250223 250224 250225 250226 250227 250228 250229 250230 250231 250232 250233 250234 250235 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2023-12-14 16:34:47 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9", -1, SQLITE_TRANSIENT);
}
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
|
| ︙ | ︙ | |||
247640 247641 247642 247643 247644 247645 247646 | } /* ** Run an integrity check on the FTS5 data structures. Return a string ** if anything is found amiss. Return a NULL pointer if everything is ** OK. */ | | | 250244 250245 250246 250247 250248 250249 250250 250251 250252 250253 250254 250255 250256 250257 250258 |
}
/*
** Run an integrity check on the FTS5 data structures. Return a string
** if anything is found amiss. Return a NULL pointer if everything is
** OK.
*/
static int fts5IntegrityMethod(
sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */
const char *zSchema, /* Name of schema in which this table lives */
const char *zTabname, /* Name of the table itself */
int isQuick, /* True if this is a quick-check */
char **pzErr /* Write error message here */
){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
| ︙ | ︙ | |||
247698 247699 247700 247701 247702 247703 247704 |
/* xRollback */ fts5RollbackMethod,
/* xFindFunction */ fts5FindFunctionMethod,
/* xRename */ fts5RenameMethod,
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
/* xShadowName */ fts5ShadowName,
| | | 250302 250303 250304 250305 250306 250307 250308 250309 250310 250311 250312 250313 250314 250315 250316 |
/* xRollback */ fts5RollbackMethod,
/* xFindFunction */ fts5FindFunctionMethod,
/* xRename */ fts5RenameMethod,
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
/* xShadowName */ fts5ShadowName,
/* xIntegrity */ fts5IntegrityMethod
};
int rc;
Fts5Global *pGlobal = 0;
pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
if( pGlobal==0 ){
|
| ︙ | ︙ | |||
248464 248465 248466 248467 248468 248469 248470 |
ctx.pStorage = p;
rc = sqlite3Fts5StorageDeleteAll(p);
if( rc==SQLITE_OK ){
rc = fts5StorageLoadTotals(p, 1);
}
if( rc==SQLITE_OK ){
| | | 251068 251069 251070 251071 251072 251073 251074 251075 251076 251077 251078 251079 251080 251081 251082 |
ctx.pStorage = p;
rc = sqlite3Fts5StorageDeleteAll(p);
if( rc==SQLITE_OK ){
rc = fts5StorageLoadTotals(p, 1);
}
if( rc==SQLITE_OK ){
rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg);
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
i64 iRowid = sqlite3_column_int64(pScan, 0);
sqlite3Fts5BufferZero(&buf);
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
|
| ︙ | ︙ | |||
249250 249251 249252 249253 249254 249255 249256 249257 249258 249259 249260 249261 249262 249263 |
*zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \
*zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
*zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
} \
}
#endif /* ifndef SQLITE_AMALGAMATION */
typedef struct Unicode61Tokenizer Unicode61Tokenizer;
struct Unicode61Tokenizer {
unsigned char aTokenChar[128]; /* ASCII range token characters */
char *aFold; /* Buffer to fold text into */
int nFold; /* Size of aFold[] in bytes */
int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
| > > > > > > | 251854 251855 251856 251857 251858 251859 251860 251861 251862 251863 251864 251865 251866 251867 251868 251869 251870 251871 251872 251873 |
*zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \
*zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \
*zOut++ = 0x80 + (unsigned char)(c & 0x3F); \
} \
}
#endif /* ifndef SQLITE_AMALGAMATION */
#define FTS5_SKIP_UTF8(zIn) { \
if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \
while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \
} \
}
typedef struct Unicode61Tokenizer Unicode61Tokenizer;
struct Unicode61Tokenizer {
unsigned char aTokenChar[128]; /* ASCII range token characters */
char *aFold; /* Buffer to fold text into */
int nFold; /* Size of aFold[] in bytes */
int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
|
| ︙ | ︙ | |||
250286 250287 250288 250289 250290 250291 250292 250293 250294 250295 250296 250297 250298 250299 |
/**************************************************************************
** Start of trigram implementation.
*/
typedef struct TrigramTokenizer TrigramTokenizer;
struct TrigramTokenizer {
int bFold; /* True to fold to lower-case */
};
/*
** Free a trigram tokenizer.
*/
static void fts5TriDelete(Fts5Tokenizer *p){
sqlite3_free(p);
| > | 252896 252897 252898 252899 252900 252901 252902 252903 252904 252905 252906 252907 252908 252909 252910 |
/**************************************************************************
** Start of trigram implementation.
*/
typedef struct TrigramTokenizer TrigramTokenizer;
struct TrigramTokenizer {
int bFold; /* True to fold to lower-case */
int iFoldParam; /* Parameter to pass to Fts5UnicodeFold() */
};
/*
** Free a trigram tokenizer.
*/
static void fts5TriDelete(Fts5Tokenizer *p){
sqlite3_free(p);
|
| ︙ | ︙ | |||
250312 250313 250314 250315 250316 250317 250318 250319 250320 250321 250322 250323 250324 250325 250326 250327 250328 250329 250330 250331 250332 250333 250334 250335 250336 250337 |
TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
UNUSED_PARAM(pUnused);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
int i;
pNew->bFold = 1;
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
rc = SQLITE_ERROR;
}else{
pNew->bFold = (zArg[0]=='0');
}
}else{
rc = SQLITE_ERROR;
}
}
if( rc!=SQLITE_OK ){
fts5TriDelete((Fts5Tokenizer*)pNew);
pNew = 0;
}
}
*ppOut = (Fts5Tokenizer*)pNew;
return rc;
| > > > > > > > > > > > > | 252923 252924 252925 252926 252927 252928 252929 252930 252931 252932 252933 252934 252935 252936 252937 252938 252939 252940 252941 252942 252943 252944 252945 252946 252947 252948 252949 252950 252951 252952 252953 252954 252955 252956 252957 252958 252959 252960 |
TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
UNUSED_PARAM(pUnused);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
int i;
pNew->bFold = 1;
pNew->iFoldParam = 0;
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
rc = SQLITE_ERROR;
}else{
pNew->bFold = (zArg[0]=='0');
}
}else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
rc = SQLITE_ERROR;
}else{
pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
}
}else{
rc = SQLITE_ERROR;
}
}
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
rc = SQLITE_ERROR;
}
if( rc!=SQLITE_OK ){
fts5TriDelete((Fts5Tokenizer*)pNew);
pNew = 0;
}
}
*ppOut = (Fts5Tokenizer*)pNew;
return rc;
|
| ︙ | ︙ | |||
250346 250347 250348 250349 250350 250351 250352 250353 250354 250355 250356 250357 250358 |
int unusedFlags,
const char *pText, int nText,
int (*xToken)(void*, int, const char*, int, int, int)
){
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
int rc = SQLITE_OK;
char aBuf[32];
const unsigned char *zIn = (const unsigned char*)pText;
const unsigned char *zEof = &zIn[nText];
u32 iCode;
UNUSED_PARAM(unusedFlags);
while( 1 ){
| > > > > > > > > > > > > > > > > > > > > > > > > | | < | > > | | < < | | | > > | < < | | | > | | < | | < < | > | < > | | 252969 252970 252971 252972 252973 252974 252975 252976 252977 252978 252979 252980 252981 252982 252983 252984 252985 252986 252987 252988 252989 252990 252991 252992 252993 252994 252995 252996 252997 252998 252999 253000 253001 253002 253003 253004 253005 253006 253007 253008 253009 253010 253011 253012 253013 253014 253015 253016 253017 253018 253019 253020 253021 253022 253023 253024 253025 253026 253027 253028 253029 253030 253031 253032 253033 253034 253035 253036 253037 253038 |
int unusedFlags,
const char *pText, int nText,
int (*xToken)(void*, int, const char*, int, int, int)
){
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
int rc = SQLITE_OK;
char aBuf[32];
char *zOut = aBuf;
int ii;
const unsigned char *zIn = (const unsigned char*)pText;
const unsigned char *zEof = &zIn[nText];
u32 iCode;
int aStart[3]; /* Input offset of each character in aBuf[] */
UNUSED_PARAM(unusedFlags);
/* Populate aBuf[] with the characters for the first trigram. */
for(ii=0; ii<3; ii++){
do {
aStart[ii] = zIn - (const unsigned char*)pText;
READ_UTF8(zIn, zEof, iCode);
if( iCode==0 ) return SQLITE_OK;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
WRITE_UTF8(zOut, iCode);
}
/* At the start of each iteration of this loop:
**
** aBuf: Contains 3 characters. The 3 characters of the next trigram.
** zOut: Points to the byte following the last character in aBuf.
** aStart[3]: Contains the byte offset in the input text corresponding
** to the start of each of the three characters in the buffer.
*/
assert( zIn<=zEof );
while( 1 ){
int iNext; /* Start of character following current tri */
const char *z1;
/* Read characters from the input up until the first non-diacritic */
do {
iNext = zIn - (const unsigned char*)pText;
READ_UTF8(zIn, zEof, iCode);
if( iCode==0 ) break;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
/* Pass the current trigram back to fts5 */
rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext);
if( iCode==0 || rc!=SQLITE_OK ) break;
/* Remove the first character from buffer aBuf[]. Append the character
** with codepoint iCode. */
z1 = aBuf;
FTS5_SKIP_UTF8(z1);
memmove(aBuf, z1, zOut - z1);
zOut -= (z1 - aBuf);
WRITE_UTF8(zOut, iCode);
/* Update the aStart[] array */
aStart[0] = aStart[1];
aStart[1] = aStart[2];
aStart[2] = iNext;
}
return rc;
}
/*
** Argument xCreate is a pointer to a constructor function for a tokenizer.
|
| ︙ | ︙ | |||
250402 250403 250404 250405 250406 250407 250408 |
*/
static int sqlite3Fts5TokenizerPattern(
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
Fts5Tokenizer *pTok
){
if( xCreate==fts5TriCreate ){
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
| > | > | 253047 253048 253049 253050 253051 253052 253053 253054 253055 253056 253057 253058 253059 253060 253061 253062 253063 |
*/
static int sqlite3Fts5TokenizerPattern(
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
Fts5Tokenizer *pTok
){
if( xCreate==fts5TriCreate ){
TrigramTokenizer *p = (TrigramTokenizer*)pTok;
if( p->iFoldParam==0 ){
return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
}
}
return FTS5_PATTERN_NONE;
}
/*
** Register all built-in tokenizers with FTS5.
*/
|
| ︙ | ︙ | |||
252191 252192 252193 252194 252195 252196 252197 |
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
nTerm = sqlite3_value_bytes(pEq);
| | | 254838 254839 254840 254841 254842 254843 254844 254845 254846 254847 254848 254849 254850 254851 254852 |
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
nTerm = sqlite3_value_bytes(pEq);
f = FTS5INDEX_QUERY_NOTOKENDATA;
}else{
if( pGe ){
zTerm = (const char *)sqlite3_value_text(pGe);
nTerm = sqlite3_value_bytes(pGe);
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
|
| ︙ | ︙ |
Changes to extsrc/sqlite3.h.
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.45.0" #define SQLITE_VERSION_NUMBER 3045000 #define SQLITE_SOURCE_ID "2023-12-14 16:34:47 27d4a89a5ff96b7b7fc5dc9650e1269f7c7edf91de9b9aafce40be9ecc8b95e9" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
3950 3951 3952 3953 3954 3955 3956 | ** <li> sqlite3_extended_errcode() ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language | | > | | > | 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 | ** <li> sqlite3_extended_errcode() ** <li> sqlite3_errmsg() ** <li> sqlite3_errmsg16() ** <li> sqlite3_error_offset() ** </ul> ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively, ** or NULL if no error message is available. ** (See how SQLite handles [invalid UTF] for exceptions to this rule.) ** ^(Memory to hold the error message string is managed internally. ** The application does not need to worry about freeing the result. ** However, the error string might be overwritten or deallocated by ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text ** that describes the [result code] E, as UTF-8, or NULL if E is not an ** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** ** ^If the most recent error references a specific token in the input ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by ** sqlite3_error_offset() assumes that the input SQL is UTF8. |
| ︙ | ︙ | |||
8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 | #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 | > | 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 | #define SQLITE_TESTCTRL_BITVEC_TEST 8 #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ #define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 |
| ︙ | ︙ | |||
12980 12981 12982 12983 12984 12985 12986 12987 12988 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
| > > > > > > > > > > > > > > > > > > > > > > > > > | | 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 12998 12999 13000 13001 13002 13003 13004 13005 13006 13007 13008 13009 13010 13011 13012 13013 13014 13015 13016 13017 13018 13019 13020 13021 13022 13023 13024 |
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
**
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase iPhrase of the current
** query. Before returning, output parameter *ppToken is set to point
** to a buffer containing the requested token, and *pnToken to the
** size of this buffer in bytes.
**
** The output text is not a copy of the query text that specified the
** token. It is the output of the tokenizer module. For tokendata=1
** tables, this includes any embedded 0x00 and trailing data.
**
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
** This is used to access token iToken of phrase hit iIdx within the
** current row. Output variable (*ppToken) is set to point to a buffer
** containing the matching document token, and (*pnToken) to the size
** of that buffer in bytes. This API is not available if the specified
** token matches a prefix query term. In that case both output variables
** are always set to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 3 */
void *(*xUserData)(Fts5Context*);
int (*xColumnCount)(Fts5Context*);
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
| ︙ | ︙ | |||
13017 13018 13019 13020 13021 13022 13023 13024 13025 13026 13027 13028 13029 13030 | void *(*xGetAuxdata)(Fts5Context*, int bClear); int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); }; /* ** CUSTOM AUXILIARY FUNCTIONS *************************************************************************/ /************************************************************************* | > > > > > > > | 13045 13046 13047 13048 13049 13050 13051 13052 13053 13054 13055 13056 13057 13058 13059 13060 13061 13062 13063 13064 13065 |
void *(*xGetAuxdata)(Fts5Context*, int bClear);
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
/* Below this point are iVersion>=3 only */
int (*xQueryToken)(Fts5Context*,
int iPhrase, int iToken,
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
|
| ︙ | ︙ |