Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Merge from trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | rptview-submenu-paralink |
Files: | files | file ages | folders |
SHA3-256: |
a961a67ba72777d1342ac0901ad92193 |
User & Date: | george 2022-02-10 00:22:32 |
2022-02-10
| ||
00:22 | Merge from trunk ... (Leaf check-in: a961a67b user: george tags: rptview-submenu-paralink) | |
00:05 | Remove unused local variable from cgi_parse_POST_JSON() to fix a compiler warning. ... (check-in: 96bf76a4 user: george tags: trunk) | |
2022-01-21
| ||
20:24 | Merge from trunk ... (check-in: 9094def2 user: george tags: rptview-submenu-paralink) | |
Changes to extsrc/shell.c.
︙ | ︙ | |||
12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 12169 12170 12171 12172 12173 12174 | typedef struct EQPGraph EQPGraph; struct EQPGraph { EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ EQPGraphRow *pLast; /* Last element of the pRow list */ char zPrefix[100]; /* Graph prefix */ }; /* ** State information about the database connection is contained in an ** instance of the following structure. */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ u8 autoEQPtest; /* autoEQP is in test mode */ u8 autoEQPtrace; /* autoEQP is in trace mode */ u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ u8 bSafeMode; /* True to prohibit unsafe operations */ u8 bSafeModePersist; /* The long-term value of bSafeMode */ unsigned statsOn; /* True to display memory stats before each finalize */ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ int lineno; /* Line number of last line read from in */ int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ FILE *in; /* Read commands from this stream */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ | > > > > > > > > > > > | 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 12169 12170 12171 12172 12173 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 | typedef struct EQPGraph EQPGraph; struct EQPGraph { EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ EQPGraphRow *pLast; /* Last element of the pRow list */ char zPrefix[100]; /* Graph prefix */ }; /* Parameters affecting columnar mode result display (defaulting together) */ typedef struct ColModeOpts { int iWrap; /* In columnar modes, wrap lines reaching this limit */ u8 bQuote; /* Quote results for .mode box and table */ u8 bWordWrap; /* In columnar modes, wrap at word boundaries */ } ColModeOpts; #define ColModeOpts_default { 60, 0, 0 } #define ColModeOpts_default_qbox { 60, 1, 0 } /* ** State information about the database connection is contained in an ** instance of the following structure. */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ u8 autoEQPtest; /* autoEQP is in test mode */ u8 autoEQPtrace; /* autoEQP is in trace mode */ u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ u8 bSafeMode; /* True to prohibit unsafe operations */ u8 bSafeModePersist; /* The long-term value of bSafeMode */ ColModeOpts cmOpts; /* Option values affecting columnar mode output */ unsigned statsOn; /* True to display memory stats before each finalize */ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ int inputNesting; /* Track nesting level of .read and other redirects */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ int lineno; /* Line number of last line read from in */ int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ FILE *in; /* Read commands from this stream */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ |
︙ | ︙ | |||
12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 | #define SEP_Tab "\t" #define SEP_Space " " #define SEP_Comma "," #define SEP_CrLf "\r\n" #define SEP_Unit "\x1F" #define SEP_Record "\x1E" /* ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); | > > > > > > | 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 | #define SEP_Tab "\t" #define SEP_Space " " #define SEP_Comma "," #define SEP_CrLf "\r\n" #define SEP_Unit "\x1F" #define SEP_Record "\x1E" /* ** Limit input nesting via .read or any other input redirect. ** It's not too expensive, so a generous allowance can be made. */ #define MAX_INPUT_NESTING 25 /* ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); |
︙ | ︙ | |||
14232 14233 14234 14235 14236 14237 14238 14239 14240 14241 14242 14243 14244 14245 14246 14247 14248 14249 14250 14251 14252 14253 14254 14255 14256 14257 14258 14259 14260 14261 14262 14263 14264 14265 14266 14267 14268 14269 14270 14271 14272 | print_box_line(p->out, p->actualWidth[i]+2); } utf8_printf(p->out, "%s", zSep3); } fputs("\n", p->out); } /* ** Run a prepared statement and output the result in one of the ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table, ** or MODE_Box. ** ** This is different from ordinary exec_prepared_stmt() in that ** it has to run the entire query and gather the results into memory ** first, in order to determine column widths, before providing ** any output. */ static void exec_prepared_stmt_columnar( ShellState *p, /* Pointer to ShellState */ sqlite3_stmt *pStmt /* Statment to run */ ){ sqlite3_int64 nRow = 0; int nColumn = 0; char **azData = 0; sqlite3_int64 nAlloc = 0; const char *z; int rc; sqlite3_int64 i, nData; int j, nTotal, w, n; const char *colSep = 0; const char *rowSep = 0; rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); shell_check_oom(azData); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < | < > | | < < | < < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 14249 14250 14251 14252 14253 14254 14255 14256 14257 14258 14259 14260 14261 14262 14263 14264 14265 14266 14267 14268 14269 14270 14271 14272 14273 14274 14275 14276 14277 14278 14279 14280 14281 14282 14283 14284 14285 14286 14287 14288 14289 14290 14291 14292 14293 14294 14295 14296 14297 14298 14299 14300 14301 14302 14303 14304 14305 14306 14307 14308 14309 14310 14311 14312 14313 14314 14315 14316 14317 14318 14319 14320 14321 14322 14323 14324 14325 14326 14327 14328 14329 14330 14331 14332 14333 14334 14335 14336 14337 14338 14339 14340 14341 14342 14343 14344 14345 14346 14347 14348 14349 14350 14351 14352 14353 14354 14355 14356 14357 14358 14359 14360 14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372 14373 14374 14375 14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 14392 14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406 14407 14408 14409 14410 14411 14412 14413 14414 14415 14416 14417 14418 14419 14420 14421 14422 14423 14424 14425 14426 14427 14428 14429 14430 14431 14432 14433 14434 14435 14436 14437 14438 14439 14440 14441 14442 14443 14444 14445 14446 14447 14448 14449 14450 14451 14452 14453 14454 14455 14456 14457 14458 14459 14460 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472 14473 14474 14475 14476 14477 14478 14479 14480 14481 14482 14483 14484 14485 14486 14487 14488 14489 14490 14491 14492 14493 14494 14495 14496 14497 14498 14499 | print_box_line(p->out, p->actualWidth[i]+2); } utf8_printf(p->out, "%s", zSep3); } fputs("\n", p->out); } /* ** z[] is a line of text that is to be displayed the .mode box or table or ** similar tabular formats. z[] might contain control characters such ** as \n, \t, \f, or \r. ** ** Compute characters to display on the first line of z[]. Stop at the ** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained ** from malloc()) of that first line, which caller should free sometime. ** Write anything to display on the next line into *pzTail. If this is ** the last line, write a NULL into *pzTail. (*pzTail is not allocated.) */ static char *translateForDisplayAndDup( const unsigned char *z, /* Input text to be transformed */ const unsigned char **pzTail, /* OUT: Tail of the input for next line */ int mxWidth, /* Max width. 0 means no limit */ u8 bWordWrap /* If true, avoid breaking mid-word */ ){ int i; /* Input bytes consumed */ int j; /* Output bytes generated */ int k; /* Input bytes to be displayed */ int n; /* Output column number */ unsigned char *zOut; /* Output text */ if( z==0 ){ *pzTail = 0; return 0; } if( mxWidth<0 ) mxWidth = -mxWidth; if( mxWidth==0 ) mxWidth = 1000000; i = j = n = 0; while( n<mxWidth ){ if( z[i]>=' ' ){ n++; do{ i++; j++; }while( (z[i]&0xc0)==0x80 ); continue; } if( z[i]=='\t' ){ do{ n++; j++; }while( (n&7)!=0 && n<mxWidth ); i++; continue; } break; } if( n>=mxWidth && bWordWrap ){ /* Perhaps try to back up to a better place to break the line */ for(k=i; k>i/2; k--){ if( isspace(z[k-1]) ) break; } if( k<=i/2 ){ for(k=i; k>i/2; k--){ if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break; } } if( k<=i/2 ){ k = i; }else{ i = k; while( z[i]==' ' ) i++; } }else{ k = i; } if( n>=mxWidth && z[i]>=' ' ){ *pzTail = &z[i]; }else if( z[i]=='\r' && z[i+1]=='\n' ){ *pzTail = z[i+2] ? &z[i+2] : 0; }else if( z[i]==0 || z[i+1]==0 ){ *pzTail = 0; }else{ *pzTail = &z[i+1]; } zOut = malloc( j+1 ); shell_check_oom(zOut); i = j = n = 0; while( i<k ){ if( z[i]>=' ' ){ n++; do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 ); continue; } if( z[i]=='\t' ){ do{ n++; zOut[j++] = ' '; }while( (n&7)!=0 && n<mxWidth ); i++; continue; } break; } zOut[j] = 0; return (char*)zOut; } /* Extract the value of the i-th current column for pStmt as an SQL literal ** value. Memory is obtained from sqlite3_malloc64() and must be freed by ** the caller. */ static char *quoted_column(sqlite3_stmt *pStmt, int i){ switch( sqlite3_column_type(pStmt, i) ){ case SQLITE_NULL: { return sqlite3_mprintf("NULL"); } case SQLITE_INTEGER: case SQLITE_FLOAT: { return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i)); } case SQLITE_TEXT: { return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i)); } case SQLITE_BLOB: { int j; sqlite3_str *pStr = sqlite3_str_new(0); const unsigned char *a = sqlite3_column_blob(pStmt,i); int n = sqlite3_column_bytes(pStmt,i); sqlite3_str_append(pStr, "x'", 2); for(j=0; j<n; j++){ sqlite3_str_appendf(pStr, "%02x", a[j]); } sqlite3_str_append(pStr, "'", 1); return sqlite3_str_finish(pStr); } } return 0; /* Not reached */ } /* ** Run a prepared statement and output the result in one of the ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table, ** or MODE_Box. ** ** This is different from ordinary exec_prepared_stmt() in that ** it has to run the entire query and gather the results into memory ** first, in order to determine column widths, before providing ** any output. */ static void exec_prepared_stmt_columnar( ShellState *p, /* Pointer to ShellState */ sqlite3_stmt *pStmt /* Statment to run */ ){ sqlite3_int64 nRow = 0; int nColumn = 0; char **azData = 0; sqlite3_int64 nAlloc = 0; char *abRowDiv = 0; const unsigned char *uz; const char *z; char **azQuoted = 0; int rc; sqlite3_int64 i, nData; int j, nTotal, w, n; const char *colSep = 0; const char *rowSep = 0; const unsigned char **azNextLine = 0; int bNextLine = 0; int bMultiLineRowExists = 0; int bw = p->cmOpts.bWordWrap; rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); shell_check_oom(azData); azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) ); shell_check_oom((void*)azNextLine); memset((void*)azNextLine, 0, nColumn*sizeof(char*) ); if( p->cmOpts.bQuote ){ azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) ); shell_check_oom(azQuoted); memset(azQuoted, 0, nColumn*sizeof(char*) ); } abRowDiv = sqlite3_malloc64( nAlloc/nColumn ); shell_check_oom(abRowDiv); if( nColumn>p->nWidth ){ p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int)); shell_check_oom(p->colWidth); for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0; p->nWidth = nColumn; p->actualWidth = &p->colWidth[nColumn]; } memset(p->actualWidth, 0, nColumn*sizeof(int)); for(i=0; i<nColumn; i++){ w = p->colWidth[i]; if( w<0 ) w = -w; p->actualWidth[i] = w; } for(i=0; i<nColumn; i++){ const unsigned char *zNotUsed; int wx = p->colWidth[i]; if( wx==0 ){ wx = p->cmOpts.iWrap; } if( wx<0 ) wx = -wx; uz = (const unsigned char*)sqlite3_column_name(pStmt,i); azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw); } do{ int useNextLine = bNextLine; bNextLine = 0; if( (nRow+2)*nColumn >= nAlloc ){ nAlloc *= 2; azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*)); shell_check_oom(azData); abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn); shell_check_oom(abRowDiv); } abRowDiv[nRow] = 1; nRow++; for(i=0; i<nColumn; i++){ int wx = p->colWidth[i]; if( wx==0 ){ wx = p->cmOpts.iWrap; } if( wx<0 ) wx = -wx; if( useNextLine ){ uz = azNextLine[i]; }else if( p->cmOpts.bQuote ){ sqlite3_free(azQuoted[i]); azQuoted[i] = quoted_column(pStmt,i); uz = (const unsigned char*)azQuoted[i]; }else{ uz = (const unsigned char*)sqlite3_column_text(pStmt,i); } azData[nRow*nColumn + i] = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw); if( azNextLine[i] ){ bNextLine = 1; abRowDiv[nRow-1] = 0; bMultiLineRowExists = 1; } } }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW ); nTotal = nColumn*(nRow+1); for(i=0; i<nTotal; i++){ z = azData[i]; if( z==0 ) z = p->nullValue; n = strlenChar(z); j = i%nColumn; if( n>p->actualWidth[j] ) p->actualWidth[j] = n; |
︙ | ︙ | |||
14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 14392 14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406 14407 | z = azData[i]; if( z==0 ) z = p->nullValue; w = p->actualWidth[j]; if( p->colWidth[j]<0 ) w = -w; utf8_width_print(p->out, w, z); if( j==nColumn-1 ){ utf8_printf(p->out, "%s", rowSep); j = -1; if( seenInterrupt ) goto columnar_end; }else{ utf8_printf(p->out, "%s", colSep); } } if( p->cMode==MODE_Table ){ print_row_separator(p, nColumn, "+"); }else if( p->cMode==MODE_Box ){ print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); } columnar_end: if( seenInterrupt ){ utf8_printf(p->out, "Interrupt\n"); } nData = (nRow+1)*nColumn; for(i=0; i<nData; i++) free(azData[i]); sqlite3_free(azData); } /* ** Run a prepared statement */ static void exec_prepared_stmt( ShellState *pArg, /* Pointer to ShellState */ | > > > > > > > > > > > > > > > | 14568 14569 14570 14571 14572 14573 14574 14575 14576 14577 14578 14579 14580 14581 14582 14583 14584 14585 14586 14587 14588 14589 14590 14591 14592 14593 14594 14595 14596 14597 14598 14599 14600 14601 14602 14603 14604 14605 14606 14607 14608 14609 14610 14611 14612 14613 14614 | z = azData[i]; if( z==0 ) z = p->nullValue; w = p->actualWidth[j]; if( p->colWidth[j]<0 ) w = -w; utf8_width_print(p->out, w, z); if( j==nColumn-1 ){ utf8_printf(p->out, "%s", rowSep); if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){ if( p->cMode==MODE_Table ){ print_row_separator(p, nColumn, "+"); }else if( p->cMode==MODE_Box ){ print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134); }else if( p->cMode==MODE_Column ){ raw_printf(p->out, "\n"); } } j = -1; if( seenInterrupt ) goto columnar_end; }else{ utf8_printf(p->out, "%s", colSep); } } if( p->cMode==MODE_Table ){ print_row_separator(p, nColumn, "+"); }else if( p->cMode==MODE_Box ){ print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14); } columnar_end: if( seenInterrupt ){ utf8_printf(p->out, "Interrupt\n"); } nData = (nRow+1)*nColumn; for(i=0; i<nData; i++) free(azData[i]); sqlite3_free(azData); sqlite3_free((void*)azNextLine); sqlite3_free(abRowDiv); if( azQuoted ){ for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]); sqlite3_free(azQuoted); } } /* ** Run a prepared statement */ static void exec_prepared_stmt( ShellState *pArg, /* Pointer to ShellState */ |
︙ | ︙ | |||
15145 15146 15147 15148 15149 15150 15151 15152 15153 15154 15155 15156 15157 15158 | ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", ".import FILE TABLE Import data from FILE into TABLE", " Options:", " --ascii Use \\037 and \\036 as column and row separators", " --csv Use , and \\n as column and row separators", " --skip N Skip the first N rows of input", " -v \"Verbose\" - increase auxiliary output", " Notes:", " * If TABLE does not exist, it is created. The first row of input", " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", | > | 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 | ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", ".import FILE TABLE Import data from FILE into TABLE", " Options:", " --ascii Use \\037 and \\036 as column and row separators", " --csv Use , and \\n as column and row separators", " --skip N Skip the first N rows of input", " --schema S Target table to be S.TABLE", " -v \"Verbose\" - increase auxiliary output", " Notes:", " * If TABLE does not exist, it is created. The first row of input", " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", |
︙ | ︙ | |||
15170 15171 15172 15173 15174 15175 15176 | ".lint OPTIONS Report potential schema issues.", " Options:", " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION ".load FILE ?ENTRY? Load an extension library", #endif ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", | | | | | | | | | | | | > | | | | > > > > > > > | | 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 | ".lint OPTIONS Report potential schema issues.", " Options:", " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION ".load FILE ?ENTRY? Load an extension library", #endif ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", ".mode MODE ?OPTIONS? Set output mode", " MODE is one of:", " ascii Columns/rows delimited by 0x1F and 0x1E", " box Tables using unicode box-drawing characters", " csv Comma-separated values", " column Output in columns. (See .width)", " html HTML <table> code", " insert SQL insert statements for TABLE", " json Results in a JSON array", " line One value per line", " list Values delimited by \"|\"", " markdown Markdown table format", " qbox Shorthand for \"box --width 60 --quote\"", " quote Escape answers as for SQL", " table ASCII-art table", " tabs Tab-separated values", " tcl TCL list elements", " OPTIONS: (for columnar modes or insert mode):", " --wrap N Wrap output lines to no longer than N characters", " --wordwrap B Wrap or not at word boundaries per B (on/off)", " --ww Shorthand for \"--wordwrap 1\"", " --quote Quote output text as SQL literals", " --noquote Do not quote output text", " TABLE The name of SQL table used for \"insert\" mode", ".nonce STRING Suspend safe mode for one command if nonce matches", ".nullvalue STRING Use STRING in place of NULL values", ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", " If FILE begins with '|' then open as a pipe", " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", |
︙ | ︙ | |||
19457 19458 19459 19460 19461 19462 19463 19464 19465 19466 19467 19468 19469 19470 | }else{ showHelp(p->out, 0); } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ char *zTable = 0; /* Insert data into this table */ char *zFile = 0; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int needCommit; /* True to COMMIT or ROLLBACK at end */ int nSep; /* Number of bytes in p->colSeparator[] */ | > | 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 19687 | }else{ showHelp(p->out, 0); } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ char *zTable = 0; /* Insert data into this table */ char *zSchema = "main"; /* within this schema */ char *zFile = 0; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int needCommit; /* True to COMMIT or ROLLBACK at end */ int nSep; /* Number of bytes in p->colSeparator[] */ |
︙ | ︙ | |||
19499 19500 19501 19502 19503 19504 19505 19506 19507 19508 19509 19510 19511 19512 | utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z); showHelp(p->out, "import"); rc = 1; goto meta_command_exit; } }else if( strcmp(z,"-v")==0 ){ eVerbose++; }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){ nSkip = integerValue(azArg[++i]); }else if( strcmp(z,"-ascii")==0 ){ sCtx.cColSep = SEP_Unit[0]; sCtx.cRowSep = SEP_Record[0]; xRead = ascii_read_one_field; useOutputMode = 0; | > > | 19716 19717 19718 19719 19720 19721 19722 19723 19724 19725 19726 19727 19728 19729 19730 19731 | utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z); showHelp(p->out, "import"); rc = 1; goto meta_command_exit; } }else if( strcmp(z,"-v")==0 ){ eVerbose++; }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){ zSchema = azArg[++i]; }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){ nSkip = integerValue(azArg[++i]); }else if( strcmp(z,"-ascii")==0 ){ sCtx.cColSep = SEP_Unit[0]; sCtx.cRowSep = SEP_Record[0]; xRead = ascii_read_one_field; useOutputMode = 0; |
︙ | ︙ | |||
19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 19602 19603 19604 19605 19606 19607 19608 19609 19610 | } if( sCtx.in==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); rc = 1; import_cleanup(&sCtx); goto meta_command_exit; } if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ char zSep[2]; zSep[1] = 0; zSep[0] = sCtx.cColSep; utf8_printf(p->out, "Column separator "); output_c_string(p->out, zSep); utf8_printf(p->out, ", row separator "); zSep[0] = sCtx.cRowSep; output_c_string(p->out, zSep); utf8_printf(p->out, "\n"); } while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } | > | | > < | | > | > | 19809 19810 19811 19812 19813 19814 19815 19816 19817 19818 19819 19820 19821 19822 19823 19824 19825 19826 19827 19828 19829 19830 19831 19832 19833 19834 19835 19836 19837 19838 19839 19840 19841 19842 19843 19844 19845 19846 19847 19848 19849 19850 19851 19852 19853 19854 19855 19856 19857 19858 19859 19860 19861 19862 19863 19864 19865 19866 19867 19868 19869 19870 19871 19872 19873 19874 19875 19876 19877 19878 19879 19880 19881 19882 19883 19884 19885 19886 19887 19888 19889 19890 19891 19892 19893 19894 19895 | } if( sCtx.in==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); rc = 1; import_cleanup(&sCtx); goto meta_command_exit; } /* Below, resources must be freed before exit. */ if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){ char zSep[2]; zSep[1] = 0; zSep[0] = sCtx.cColSep; utf8_printf(p->out, "Column separator "); output_c_string(p->out, zSep); utf8_printf(p->out, ", row separator "); zSep[0] = sCtx.cRowSep; output_c_string(p->out, zSep); utf8_printf(p->out, "\n"); } while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } zSql = sqlite3_mprintf("SELECT * FROM \"%w\".\"%w\"", zSchema, zTable); if( zSql==0 ){ import_cleanup(&sCtx); shell_out_of_memory(); } nByte = strlen30(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", zSchema, zTable); char cSep = '('; while( xRead(&sCtx) ){ zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); cSep = ','; if( sCtx.cTerm!=sCtx.cColSep ) break; } if( cSep=='(' ){ sqlite3_free(zCreate); import_cleanup(&sCtx); utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); rc = 1; goto meta_command_exit; } zCreate = sqlite3_mprintf("%z\n)", zCreate); if( eVerbose>=1 ){ utf8_printf(p->out, "%s\n", zCreate); } rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); if( rc ){ utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); sqlite3_free(zCreate); import_cleanup(&sCtx); rc = 1; goto meta_command_exit; } sqlite3_free(zCreate); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } sqlite3_free(zSql); if( rc ){ if (pStmt) sqlite3_finalize(pStmt); utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); import_cleanup(&sCtx); rc = 1; goto meta_command_exit; } nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ import_cleanup(&sCtx); shell_out_of_memory(); } sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", zSchema, zTable); j = strlen30(zSql); for(i=1; i<nCol; i++){ zSql[j++] = ','; zSql[j++] = '?'; } zSql[j++] = ')'; zSql[j] = 0; |
︙ | ︙ | |||
19960 19961 19962 19963 19964 19965 19966 | const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile, 0); } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | | > | | | | | | | | | | > | > | > | | | < < | | 20182 20183 20184 20185 20186 20187 20188 20189 20190 20191 20192 20193 20194 20195 20196 20197 20198 20199 20200 20201 20202 20203 20204 20205 20206 20207 20208 20209 20210 20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 20224 20225 20226 20227 20228 20229 20230 20231 20232 20233 20234 20235 20236 20237 20238 20239 20240 20241 20242 20243 20244 20245 20246 20247 20248 20249 20250 20251 20252 20253 20254 20255 20256 20257 20258 20259 20260 20261 20262 20263 20264 20265 20266 20267 20268 20269 20270 20271 20272 20273 20274 20275 20276 20277 20278 20279 20280 20281 20282 20283 20284 20285 20286 20287 20288 20289 20290 20291 20292 20293 20294 20295 20296 20297 20298 20299 20300 20301 20302 20303 20304 20305 20306 20307 20308 20309 20310 20311 20312 | const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile, 0); } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ const char *zMode = 0; const char *zTabname = 0; int i, n2; ColModeOpts cmOpts = ColModeOpts_default; for(i=1; i<nArg; i++){ const char *z = azArg[i]; if( optionMatch(z,"wrap") && i+1<nArg ){ cmOpts.iWrap = integerValue(azArg[++i]); }else if( optionMatch(z,"ww") ){ cmOpts.bWordWrap = 1; }else if( optionMatch(z,"wordwrap") && i+1<nArg ){ cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]); }else if( optionMatch(z,"quote") ){ cmOpts.bQuote = 1; }else if( optionMatch(z,"noquote") ){ cmOpts.bQuote = 0; }else if( zMode==0 ){ zMode = z; /* Apply defaults for qbox pseudo-mods. If that * overwrites already-set values, user was informed of this. */ if( strcmp(z, "qbox")==0 ){ ColModeOpts cmo = ColModeOpts_default_qbox; zMode = "box"; cmOpts = cmo; } }else if( zTabname==0 ){ zTabname = z; }else if( z[0]=='-' ){ utf8_printf(stderr, "unknown option: %s\n", z); utf8_printf(stderr, "options:\n" " --noquote\n" " --quote\n" " --wordwrap on/off\n" " --wrap N\n" " --ww\n"); rc = 1; goto meta_command_exit; }else{ utf8_printf(stderr, "extra argument: \"%s\"\n", z); rc = 1; goto meta_command_exit; } } if( zMode==0 ){ if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ raw_printf (p->out, "current output mode: %s --wrap %d --wordwrap %s --%squote\n", modeDescr[p->mode], p->cmOpts.iWrap, p->cmOpts.bWordWrap ? "on" : "off", p->cmOpts.bQuote ? "" : "no"); }else{ raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); } zMode = modeDescr[p->mode]; } n2 = strlen30(zMode); if( strncmp(zMode,"lines",n2)==0 ){ p->mode = MODE_Line; sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( strncmp(zMode,"columns",n2)==0 ){ p->mode = MODE_Column; if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){ p->showHeader = 1; } sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); p->cmOpts = cmOpts; }else if( strncmp(zMode,"list",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( strncmp(zMode,"html",n2)==0 ){ p->mode = MODE_Html; }else if( strncmp(zMode,"tcl",n2)==0 ){ p->mode = MODE_Tcl; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( strncmp(zMode,"csv",n2)==0 ){ p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); }else if( strncmp(zMode,"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); }else if( strncmp(zMode,"insert",n2)==0 ){ p->mode = MODE_Insert; set_table_name(p, zTabname ? zTabname : "table"); }else if( strncmp(zMode,"quote",n2)==0 ){ p->mode = MODE_Quote; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row); }else if( strncmp(zMode,"ascii",n2)==0 ){ p->mode = MODE_Ascii; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); }else if( strncmp(zMode,"markdown",n2)==0 ){ p->mode = MODE_Markdown; p->cmOpts = cmOpts; }else if( strncmp(zMode,"table",n2)==0 ){ p->mode = MODE_Table; p->cmOpts = cmOpts; }else if( strncmp(zMode,"box",n2)==0 ){ p->mode = MODE_Box; p->cmOpts = cmOpts; }else if( strncmp(zMode,"count",n2)==0 ){ p->mode = MODE_Count; }else if( strncmp(zMode,"off",n2)==0 ){ p->mode = MODE_Off; }else if( strncmp(zMode,"json",n2)==0 ){ p->mode = MODE_Json; }else{ raw_printf(stderr, "Error: mode should be one of: " "ascii box column csv html insert json line list markdown " "qbox quote table tabs tcl\n"); rc = 1; } p->cMode = p->mode; }else if( c=='n' && strcmp(azArg[0], "nonce")==0 ){ if( nArg!=2 ){ |
︙ | ︙ | |||
21165 21166 21167 21168 21169 21170 21171 | } utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[ShellHasFlag(p, SHFLG_Echo)]); utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); utf8_printf(p->out, "%12.12s: %s\n","explain", p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); | > > > > > > > > > | > | 21446 21447 21448 21449 21450 21451 21452 21453 21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 21465 21466 21467 21468 21469 21470 | } utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[ShellHasFlag(p, SHFLG_Echo)]); utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]); utf8_printf(p->out, "%12.12s: %s\n","explain", p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]); if( p->mode==MODE_Column || (p->mode>=MODE_Markdown && p->mode<=MODE_Box) ){ utf8_printf (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode", modeDescr[p->mode], p->cmOpts.iWrap, p->cmOpts.bWordWrap ? "on" : "off", p->cmOpts.bQuote ? "" : "no"); }else{ utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); } utf8_printf(p->out, "%12.12s: ", "nullvalue"); output_c_string(p->out, p->nullValue); raw_printf(p->out, "\n"); utf8_printf(p->out,"%12.12s: %s\n","output", strlen30(p->outfile) ? p->outfile : "stdout"); utf8_printf(p->out,"%12.12s: ", "colseparator"); output_c_string(p->out, p->colSeparator); |
︙ | ︙ | |||
22008 22009 22010 22011 22012 22013 22014 22015 22016 22017 22018 22019 22020 22021 | int nSql = 0; /* Bytes of zSql[] used */ int nAlloc = 0; /* Allocated zSql[] space */ int rc; /* Error code */ int errCnt = 0; /* Number of errors seen */ int startline = 0; /* Line number for start of current input */ QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ p->lineno = 0; while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(p->in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ if( p->in==0 && stdin_is_interactive ) printf("\n"); | > > > > > > > | 22299 22300 22301 22302 22303 22304 22305 22306 22307 22308 22309 22310 22311 22312 22313 22314 22315 22316 22317 22318 22319 | int nSql = 0; /* Bytes of zSql[] used */ int nAlloc = 0; /* Allocated zSql[] space */ int rc; /* Error code */ int errCnt = 0; /* Number of errors seen */ int startline = 0; /* Line number for start of current input */ QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ if( p->inputNesting==MAX_INPUT_NESTING ){ /* This will be more informative in a later version. */ utf8_printf(stderr,"Input nesting limit (%d) reached at line %d." " Check recursion.\n", MAX_INPUT_NESTING, p->lineno); return 1; } ++p->inputNesting; p->lineno = 0; while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){ fflush(p->out); zLine = one_input_line(p->in, zLine, nSql>0); if( zLine==0 ){ /* End of input */ if( p->in==0 && stdin_is_interactive ) printf("\n"); |
︙ | ︙ | |||
22090 22091 22092 22093 22094 22095 22096 22097 22098 22099 22100 22101 22102 22103 | } } if( nSql && QSS_PLAINDARK(qss) ){ errCnt += runOneSqlLine(p, zSql, p->in, startline); } free(zSql); free(zLine); return errCnt>0; } /* ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ | > | 22388 22389 22390 22391 22392 22393 22394 22395 22396 22397 22398 22399 22400 22401 22402 | } } if( nSql && QSS_PLAINDARK(qss) ){ errCnt += runOneSqlLine(p, zSql, p->in, startline); } free(zSql); free(zLine); --p->inputNesting; return errCnt>0; } /* ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ |
︙ | ︙ |
Changes to extsrc/sqlite3.c.
︙ | ︙ | |||
450 451 452 453 454 455 456 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 | | | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 #define SQLITE_SOURCE_ID "2022-02-05 01:01:07 1ec747d1c34ced9877709dd306e674376e79145de08b9c316d12bc5e06efc03e" /* ** 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 |
︙ | ︙ | |||
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 | ** sqlite3_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite3_value objects even when not strictly required. ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments ** to [sqlite3_result_value()], [sqlite3_bind_value()], and ** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. | > > | 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 | ** sqlite3_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite3_value objects even when not strictly required. ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] ** are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments ** to [sqlite3_result_value()], [sqlite3_bind_value()], and ** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. |
︙ | ︙ | |||
7433 7434 7435 7436 7437 7438 7439 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | > > | 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents ** an operator that is part of a constraint term in the WHERE clause of ** a query that uses a [virtual table]. ** ** ^The left-hand operand of the operator is given by the corresponding ** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand ** operand is the rowid. ** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET ** operators have no left-hand operand, and so for those operators the ** corresponding aConstraint[].iColumn is meaningless and should not be ** used. ** ** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through ** value 255 are reserved to represent functions that are overloaded ** by the [xFindFunction|xFindFunction method] of the virtual table ** implementation. ** ** The right-hand operands for each constraint might be accessible using ** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand ** operand is only available if it appears as a single constant literal ** in the input SQL. If the right-hand operand is another column or an ** expression (even a constant expression) or a parameter, then the ** sqlite3_vtab_rhs_value() probably will not be able to extract it. ** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and ** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand ** and hence calls to sqlite3_vtab_rhs_value() for those operators will ** always return SQLITE_NOTFOUND. ** ** The collating sequence to be used for comparison can be found using ** the [sqlite3_vtab_collation()] interface. For most real-world virtual ** tables, the collating sequence of constraints does not matter (for example ** because the constraints are numeric) and so the sqlite3_vtab_collation() ** interface is no commonly needed. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT 16 #define SQLITE_INDEX_CONSTRAINT_GE 32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 #define SQLITE_INDEX_CONSTRAINT_LIKE 65 #define SQLITE_INDEX_CONSTRAINT_GLOB 66 #define SQLITE_INDEX_CONSTRAINT_REGEXP 67 #define SQLITE_INDEX_CONSTRAINT_NE 68 #define SQLITE_INDEX_CONSTRAINT_ISNOT 69 #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 #define SQLITE_INDEX_CONSTRAINT_IS 72 #define SQLITE_INDEX_CONSTRAINT_LIMIT 73 #define SQLITE_INDEX_CONSTRAINT_OFFSET 74 #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation ** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before |
︙ | ︙ | |||
9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 | ** current implementation, the sqlite3_vtab_nochange() interface does always ** returns false for the enhanced [UPDATE FROM] statement. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** ** This function may only be called from within a call to the [xBestIndex] ** method of a [virtual table]. This function returns a pointer to a string ** that is the name of the appropriate collation sequence to use for text ** comparisons on the constraint identified by its arguments. ** | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 | ** current implementation, the sqlite3_vtab_nochange() interface does always ** returns false for the enhanced [UPDATE FROM] statement. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** METHOD: sqlite3_index_info ** ** This function may only be called from within a call to the [xBestIndex] ** method of a [virtual table]. This function returns a pointer to a string ** that is the name of the appropriate collation sequence to use for text ** comparisons on the constraint identified by its arguments. ** ** The first argument must be the pointer to the [sqlite3_index_info] object ** that is the first parameter to the xBestIndex() method. The second argument ** must be an index into the aConstraint[] array belonging to the ** sqlite3_index_info structure passed to xBestIndex. ** ** Important: ** The first parameter must be the same pointer that is passed into the ** xBestMethod() method. The first parameter may not be a pointer to a ** different [sqlite3_index_info] object, even an exact copy. ** ** The return value is computed as follows: ** ** <ol> ** <li><p> If the constraint comes from a WHERE clause expression that contains ** a [COLLATE operator], then the name of the collation specified by ** that COLLATE operator is returned. ** <li><p> If there is no COLLATE operator, but the column that is the subject ** of the constraint specifies an alternative collating sequence via ** a [COLLATE clause] on the column definition within the CREATE TABLE ** statement that was passed into [sqlite3_declare_vtab()], then the ** name of that alternative collating sequence is returned. ** <li><p> Otherwise, "BINARY" is returned. ** </ol> */ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); /* ** CAPI3REF: Determine if a virtual table query is DISTINCT ** METHOD: sqlite3_index_info ** ** This API may only be used from within an [xBestIndex|xBestIndex method] ** of a [virtual table] implementation. The result of calling this ** interface from outside of xBestIndex() is undefined and probably harmful. ** ** ^The sqlite3_vtab_distinct() interface returns an integer that is ** either 0, 1, or 2. The integer returned by sqlite3_vtab_distinct() ** gives the virtual table additional information about how the query ** planner wants the output to be ordered. As long as the virtual table ** can meet the ordering requirements of the query planner, it may set ** the "orderByConsumed" flag. ** ** <ol><li value="0"><p> ** ^If the sqlite3_vtab_distinct() interface returns 0, that means ** that the query planner needs the virtual table to return all rows in the ** sort order defined by the "nOrderBy" and "aOrderBy" fields of the ** [sqlite3_index_info] object. This is the default expectation. If the ** virtual table outputs all rows in sorted order, then it is always safe for ** the xBestIndex method to set the "orderByConsumed" flag, regardless of ** the return value from sqlite3_vtab_distinct(). ** <li value="1"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 1, that means ** that the query planner does not need the rows to be returned in sorted order ** as long as all rows with the same values in all columns identified by the ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner ** is doing a GROUP BY. ** <li value="2"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular ** order, as long as rows with the same values in all "aOrderBy" columns ** are adjacent.)^ ^(Furthermore, only a single row for each particular ** combination of values in the columns identified by the "aOrderBy" field ** needs to be returned.)^ ^It is always ok for two or more rows with the same ** values in all "aOrderBy" columns to be returned, as long as all such rows ** are adjacent. ^The virtual table may, if it chooses, omit extra rows ** that have the same value for all columns identified by "aOrderBy". ** ^However omitting the extra rows is optional. ** This mode is used for a DISTINCT query. ** </ol> ** ** ^For the purposes of comparing virtual table output values to see if the ** values are same value for sorting purposes, two NULL values are considered ** to be the same. In other words, the comparison operator is "IS" ** (or "IS NOT DISTINCT FROM") and not "==". ** ** If a virtual table implementation is unable to meet the requirements ** specified above, then it must not set the "orderByConsumed" flag in the ** [sqlite3_index_info] object or an incorrect answer may result. ** ** ^A virtual table implementation is always free to return rows in any order ** it wants, as long as the "orderByConsumed" flag is not set. ^When the ** the "orderByConsumed" flag is unset, the query planner will add extra ** [bytecode] to ensure that the final results returned by the SQL query are ** ordered correctly. The use of the "orderByConsumed" flag and the ** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful ** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" ** flag might help queries against a virtual table to run faster. Being ** overly aggressive and setting the "orderByConsumed" flag when it is not ** valid to do so, on the other hand, might cause SQLite to return incorrect ** results. */ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); /* ** CAPI3REF: Identify and handle IN constraints in xBestIndex ** ** This interface may only be used from within an ** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. ** The result of invoking this interface from any other context is ** undefined and probably harmful. ** ** ^(A constraint on a virtual table of the form ** "[IN operator|column IN (...)]" is ** communicated to the xBestIndex method as a ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use ** this constraint, it must set the corresponding ** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under ** the usual mode of handling IN operators, SQLite generates [bytecode] ** that invokes the [xFilter|xFilter() method] once for each value ** on the right-hand side of the IN operator.)^ Thus the virtual table ** only sees a single value from the right-hand side of the IN operator ** at a time. ** ** In some cases, however, it would be advantageous for the virtual ** table to see all values on the right-hand of the IN operator all at ** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: ** ** <ol> ** <li><p> ** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) ** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint ** is an [IN operator] that can be processed all at once. ^In other words, ** sqlite3_vtab_in() with -1 in the third argument is a mechanism ** by which the virtual table can ask SQLite if all-at-once processing ** of the IN operator is even possible. ** ** <li><p> ** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates ** to SQLite that the virtual table does or does not want to process ** the IN operator all-at-once, respectively. ^Thus when the third ** parameter (F) is non-negative, this interface is the mechanism by ** which the virtual table tells SQLite how it wants to process the ** IN operator. ** </ol> ** ** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times ** within the same xBestIndex method call. ^For any given P,N pair, ** the return value from sqlite3_vtab_in(P,N,F) will always be the same ** within the same xBestIndex call. ^If the interface returns true ** (non-zero), that means that the constraint is an IN operator ** that can be processed all-at-once. ^If the constraint is not an IN ** operator or cannot be processed all-at-once, then the interface returns ** false. ** ** ^(All-at-once processing of the IN operator is selected if both of the ** following conditions are met: ** ** <ol> ** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive ** integer. This is how the virtual table tells SQLite that it wants to ** use the N-th constraint. ** ** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was ** non-negative had F>=1. ** </ol>)^ ** ** ^If either or both of the conditions above are false, then SQLite uses ** the traditional one-at-a-time processing strategy for the IN constraint. ** ^If both conditions are true, then the argvIndex-th parameter to the ** xFilter method will be an [sqlite3_value] that appears to be NULL, ** but which can be passed to [sqlite3_vtab_in_first()] and ** [sqlite3_vtab_in_next()] to find all values on the right-hand side ** of the IN constraint. */ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); /* ** CAPI3REF: Find all elements on the right-hand side of an IN constraint. ** ** These interfaces are only useful from within the ** [xFilter|xFilter() method] of a [virtual table] implementation. ** The result of invoking these interfaces from any other context ** is undefined and probably harmful. ** ** The X parameter in a call to sqlite3_vtab_in_first(X,P) or ** sqlite3_vtab_in_next(X,P) must be one of the parameters to the ** xFilter method which invokes these routines, and specifically ** a parameter that was previously selected for all-at-once IN constraint ** processing use the [sqlite3_vtab_in()] interface in the ** [xBestIndex|xBestIndex method]. ^(If the X parameter is not ** an xFilter argument that was selected for all-at-once IN constraint ** processing, then these routines return [SQLITE_MISUSE])^ or perhaps ** exhibit some other undefined or harmful behavior. ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: ** ** <blockquote><pre> ** for(rc=sqlite3_vtab_in_first(pList, &pVal); ** rc==SQLITE_OK && pVal ** rc=sqlite3_vtab_in_next(pList, &pVal) ** ){ ** // do something with pVal ** } ** if( rc!=SQLITE_OK ){ ** // an error has occurred ** } ** </pre></blockquote>)^ ** ** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) ** routines return SQLITE_OK and set *P to point to the first or next value ** on the RHS of the IN constraint. ^If there are no more values on the ** right hand side of the IN constraint, then *P is set to NULL and these ** routines return [SQLITE_DONE]. ^The return value might be ** some other value, such as SQLITE_NOMEM, in the event of a malfunction. ** ** The *ppOut values returned by these routines are only valid until the ** next call to either of these routines or until the end of the xFilter ** method from which these routines were called. If the virtual table ** implementation needs to retain the *ppOut values for longer, it must make ** copies. The *ppOut values are [protected sqlite3_value|protected]. */ SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); /* ** CAPI3REF: Constraint values in xBestIndex() ** METHOD: sqlite3_index_info ** ** This API may only be used from within the [xBestIndex|xBestIndex method] ** of a [virtual table] implementation. The result of calling this interface ** from outside of an xBestIndex method are undefined and probably harmful. ** ** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within ** the [xBestIndex] method of a [virtual table] implementation, with P being ** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and ** J being a 0-based index into P->aConstraint[], then this routine ** attempts to set *V to the value of the right-hand operand of ** that constraint if the right-hand operand is known. ^If the ** right-hand operand is not known, then *V is set to a NULL pointer. ** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if ** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) ** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th ** constraint is not available. ^The sqlite3_vtab_rhs_value() interface ** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if ** something goes wrong. ** ** The sqlite3_vtab_rhs_value() interface is usually only successful if ** the right-hand operand of a constraint is a literal value in the original ** SQL statement. If the right-hand operand is an expression or a reference ** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() ** will probably return [SQLITE_NOTFOUND]. ** ** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and ** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such ** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ ** ** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value ** and remains valid for the duration of the xBestIndex method call. ** ^When xBestIndex returns, the sqlite3_value object returned by ** sqlite3_vtab_rhs_value() is automatically deallocated. ** ** The "_rhs_" in the name of this routine is an appreviation for ** "Right-Hand Side". */ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to ** inform a [virtual table] implementation what the [ON CONFLICT] mode ** is for the SQL statement being evaluated. |
︙ | ︙ | |||
14372 14373 14374 14375 14376 14377 14378 | ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS ((int)(sizeof(Bitmask)*8)) /* ** A bit in a Bitmask */ | | | | > | | 14637 14638 14639 14640 14641 14642 14643 14644 14645 14646 14647 14648 14649 14650 14651 14652 14653 14654 14655 | ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS ((int)(sizeof(Bitmask)*8)) /* ** A bit in a Bitmask */ #define MASKBIT(n) (((Bitmask)1)<<(n)) #define MASKBIT64(n) (((u64)1)<<(n)) #define MASKBIT32(n) (((unsigned int)1)<<(n)) #define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0) #define ALLBITS ((Bitmask)-1) /* A VList object records a mapping between parameters/variables/wildcards ** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer ** variable number associated with that parameter. See the format description ** on the sqlite3VListAdd() routine for more information. A VList is really ** just an array of integers. */ |
︙ | ︙ | |||
15401 15402 15403 15404 15405 15406 15407 | #define OP_CursorLock 166 #define OP_CursorUnlock 167 #define OP_TableLock 168 /* synopsis: iDb=P1 root=P2 write=P3 */ #define OP_VBegin 169 #define OP_VCreate 170 #define OP_VDestroy 171 #define OP_VOpen 172 | > | | | | | | | | | | | | 15667 15668 15669 15670 15671 15672 15673 15674 15675 15676 15677 15678 15679 15680 15681 15682 15683 15684 15685 15686 15687 15688 15689 15690 15691 15692 | #define OP_CursorLock 166 #define OP_CursorUnlock 167 #define OP_TableLock 168 /* synopsis: iDb=P1 root=P2 write=P3 */ #define OP_VBegin 169 #define OP_VCreate 170 #define OP_VDestroy 171 #define OP_VOpen 172 #define OP_VInitIn 173 /* synopsis: r[P2]=ValueList(P1,P3) */ #define OP_VColumn 174 /* synopsis: r[P3]=vcolumn(P2) */ #define OP_VRename 175 #define OP_Pagecount 176 #define OP_MaxPgcnt 177 #define OP_FilterAdd 178 /* synopsis: filter(P1) += key(P3@P4) */ #define OP_Trace 179 #define OP_CursorHint 180 #define OP_ReleaseReg 181 /* synopsis: release r[P1@P2] mask P3 */ #define OP_Noop 182 #define OP_Explain 183 #define OP_Abortable 184 /* 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 */ |
︙ | ︙ | |||
15445 15446 15447 15448 15449 15450 15451 | /* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\ /* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\ /* 136 */ 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00, 0x10,\ /* 144 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a,\ /* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ | | | < > | 15712 15713 15714 15715 15716 15717 15718 15719 15720 15721 15722 15723 15724 15725 15726 15727 15728 | /* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\ /* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\ /* 136 */ 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00, 0x10,\ /* 144 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 152 */ 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a,\ /* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\ /* 176 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 184 */ 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. */ |
︙ | ︙ | |||
18574 18575 18576 18577 18578 18579 18580 18581 18582 18583 18584 18585 18586 18587 | ** Fields above must be initialized to zero. The fields that follow, ** down to the beginning of the recursive section, do not need to be ** initialized as they will be set before being used. The boundary is ** determined by offsetof(Parse,aTempReg). **************************************************************************/ int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined ** using offsetof(Parse,sLastToken) so the sLastToken field must be the ** first field in the recursive region. | > | 18841 18842 18843 18844 18845 18846 18847 18848 18849 18850 18851 18852 18853 18854 18855 | ** Fields above must be initialized to zero. The fields that follow, ** down to the beginning of the recursive section, do not need to be ** initialized as they will be set before being used. The boundary is ** determined by offsetof(Parse,aTempReg). **************************************************************************/ int aTempReg[8]; /* Holding area for temporary registers */ Parse *pOuterParse; /* Outer Parse object when nested */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined ** using offsetof(Parse,sLastToken) so the sLastToken field must be the ** first field in the recursive region. |
︙ | ︙ | |||
18624 18625 18626 18627 18628 18629 18630 | #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME 2 #define PARSE_MODE_UNMAP 3 /* ** Sizes and pointers of various parts of the Parse object. */ | > | | 18892 18893 18894 18895 18896 18897 18898 18899 18900 18901 18902 18903 18904 18905 18906 18907 | #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME 2 #define PARSE_MODE_UNMAP 3 /* ** Sizes and pointers of various parts of the Parse object. */ #define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg)) #define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ |
︙ | ︙ | |||
19564 19565 19566 19567 19568 19569 19570 | #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*); SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, Upsert*); | | > | 19833 19834 19835 19836 19837 19838 19839 19840 19841 19842 19843 19844 19845 19846 19847 19848 | #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*); SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, Upsert*); SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*, ExprList*,Select*,u16,int); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); |
︙ | ︙ | |||
19964 19965 19966 19967 19968 19969 19970 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), void (*)(sqlite3_context*), void (*)(sqlite3_context*,int,sqlite3_value **), FuncDestructor *pDestructor ); SQLITE_PRIVATE void sqlite3NoopDestructor(void*); | | | 20234 20235 20236 20237 20238 20239 20240 20241 20242 20243 20244 20245 20246 20247 20248 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), void (*)(sqlite3_context*), void (*)(sqlite3_context*,int,sqlite3_value **), FuncDestructor *pDestructor ); SQLITE_PRIVATE void sqlite3NoopDestructor(void*); SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*); SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, int); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); |
︙ | ︙ | |||
20085 20086 20087 20088 20089 20090 20091 | SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); | > | | 20355 20356 20357 20358 20359 20360 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 | SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*); SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*); SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); #ifdef SQLITE_ENABLE_NORMALIZE SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*); #endif SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*); |
︙ | ︙ | |||
20518 20519 20520 20521 20522 20523 20524 20525 20526 20527 20528 20529 20530 20531 | #define OpenCounter(X) #endif /* defined(SQLITE_TEST) */ #endif /* !defined(_OS_COMMON_H_) */ /************** End of os_common.h *******************************************/ /************** Begin file ctime.c *******************************************/ /* ** 2010 February 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. | > > > > > > > > | 20789 20790 20791 20792 20793 20794 20795 20796 20797 20798 20799 20800 20801 20802 20803 20804 20805 20806 20807 20808 20809 20810 | #define OpenCounter(X) #endif /* defined(SQLITE_TEST) */ #endif /* !defined(_OS_COMMON_H_) */ /************** End of os_common.h *******************************************/ /************** Begin file ctime.c *******************************************/ /* DO NOT EDIT! ** This file is automatically generated by the script in the canonical ** SQLite source tree at tool/mkctimec.tcl. ** ** To modify this header, edit any of the various lists in that script ** which specify categories of generated conditionals in this file. */ /* ** 2010 February 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. |
︙ | ︙ | |||
20566 20567 20568 20569 20570 20571 20572 | ** ** This array looks large, but in a typical installation actually uses ** only a handful of compile-time options, so most times this array is usually ** rather short and uses little memory space. */ static const char * const sqlite3azCompileOpt[] = { | < < < | 20845 20846 20847 20848 20849 20850 20851 20852 20853 20854 20855 20856 20857 20858 | ** ** This array looks large, but in a typical installation actually uses ** only a handful of compile-time options, so most times this array is usually ** rather short and uses little memory space. */ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_32BIT_ROWID "32BIT_ROWID", #endif #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif #ifdef SQLITE_64BIT_STATS |
︙ | ︙ | |||
20699 20700 20701 20702 20703 20704 20705 | #endif #ifdef SQLITE_DISABLE_FTS4_DEFERRED "DISABLE_FTS4_DEFERRED", #endif #ifdef SQLITE_DISABLE_INTRINSIC "DISABLE_INTRINSIC", #endif | < < < | 20975 20976 20977 20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 | #endif #ifdef SQLITE_DISABLE_FTS4_DEFERRED "DISABLE_FTS4_DEFERRED", #endif #ifdef SQLITE_DISABLE_INTRINSIC "DISABLE_INTRINSIC", #endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif #ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS "DISABLE_PAGECACHE_OVERFLOW_STATS", #endif #ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT |
︙ | ︙ | |||
21102 21103 21104 21105 21106 21107 21108 21109 21110 21111 21112 21113 21114 21115 | "OMIT_INCRBLOB", #endif #ifdef SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif | > > > | 21375 21376 21377 21378 21379 21380 21381 21382 21383 21384 21385 21386 21387 21388 21389 21390 21391 | "OMIT_INCRBLOB", #endif #ifdef SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif #ifdef SQLITE_OMIT_JSON "OMIT_JSON", #endif #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif |
︙ | ︙ | |||
21291 21292 21293 21294 21295 21296 21297 | #endif #ifdef SQLITE_WIN32_MALLOC "WIN32_MALLOC", #endif #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC", #endif | | < < | | 21567 21568 21569 21570 21571 21572 21573 21574 21575 21576 21577 21578 21579 21580 21581 21582 | #endif #ifdef SQLITE_WIN32_MALLOC "WIN32_MALLOC", #endif #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC", #endif } ; SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); return (const char**)sqlite3azCompileOpt; } #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
︙ | ︙ | |||
22212 22213 22214 22215 22216 22217 22218 22219 22220 22221 22222 22223 22224 22225 | int iBlobWrite; /* Value returned by preupdate_blobwrite() */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); | > > > > > > > > > > > > > > > > > > | 22486 22487 22488 22489 22490 22491 22492 22493 22494 22495 22496 22497 22498 22499 22500 22501 22502 22503 22504 22505 22506 22507 22508 22509 22510 22511 22512 22513 22514 22515 22516 22517 | int iBlobWrite; /* Value returned by preupdate_blobwrite() */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; /* ** An instance of this object is used to pass an vector of values into ** OP_VFilter, the xFilter method of a virtual table. The vector is the ** set of values on the right-hand side of an IN constraint. ** ** The value as passed into xFilter is an sqlite3_value with a "pointer" ** type, such as is generated by sqlite3_result_pointer() and read by ** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null ** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces ** know how to use this object to step through all the values in the ** right operand of the IN constraint. */ typedef struct ValueList ValueList; struct ValueList { BtCursor *pCsr; /* An ephemeral table holding all values */ sqlite3_value *pOut; /* Register to hold each decoded output value */ }; /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); |
︙ | ︙ | |||
23404 23405 23406 23407 23408 23409 23410 | ** to context pCtx. If the error is an unrecognized modifier, no error is ** written to pCtx. */ static int parseModifier( sqlite3_context *pCtx, /* Function context */ const char *z, /* The text of the modifier */ int n, /* Length of zMod in bytes */ | | > > | 23696 23697 23698 23699 23700 23701 23702 23703 23704 23705 23706 23707 23708 23709 23710 23711 23712 23713 23714 23715 23716 23717 23718 23719 23720 23721 23722 23723 23724 | ** to context pCtx. If the error is an unrecognized modifier, no error is ** written to pCtx. */ static int parseModifier( sqlite3_context *pCtx, /* Function context */ const char *z, /* The text of the modifier */ int n, /* Length of zMod in bytes */ DateTime *p, /* The date/time value to be modified */ int idx /* Parameter index of the modifier */ ){ int rc = 1; double r; switch(sqlite3UpperToLower[(u8)z[0]] ){ case 'a': { /* ** auto ** ** If rawS is available, then interpret as a julian day number, or ** a unix timestamp, depending on its magnitude. */ if( sqlite3_stricmp(z, "auto")==0 ){ if( idx>1 ) return 1; /* IMP: R-33611-57934 */ if( !p->rawS || p->validJD ){ rc = 0; p->rawS = 0; }else if( p->s>=-210866760000 && p->s<=253402300799 ){ r = p->s*1000.0 + 210866760000000.0; clearYMD_HMS_TZ(p); p->iJD = (sqlite3_int64)(r + 0.5); |
︙ | ︙ | |||
23441 23442 23443 23444 23445 23446 23447 23448 23449 23450 23451 23452 23453 23454 | ** ** Always interpret the prior number as a julian-day value. If this ** is not the first modifier, or if the prior argument is not a numeric ** value in the allowed range of julian day numbers understood by ** SQLite (0..5373484.5) then the result will be NULL. */ if( sqlite3_stricmp(z, "julianday")==0 ){ if( p->validJD && p->rawS ){ rc = 0; p->rawS = 0; } } break; } | > | 23735 23736 23737 23738 23739 23740 23741 23742 23743 23744 23745 23746 23747 23748 23749 | ** ** Always interpret the prior number as a julian-day value. If this ** is not the first modifier, or if the prior argument is not a numeric ** value in the allowed range of julian day numbers understood by ** SQLite (0..5373484.5) then the result will be NULL. */ if( sqlite3_stricmp(z, "julianday")==0 ){ if( idx>1 ) return 1; /* IMP: R-31176-64601 */ if( p->validJD && p->rawS ){ rc = 0; p->rawS = 0; } } break; } |
︙ | ︙ | |||
23471 23472 23473 23474 23475 23476 23477 23478 23479 23480 23481 23482 23483 23484 | /* ** unixepoch ** ** Treat the current value of p->s as the number of ** seconds since 1970. Convert to a real julian day number. */ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ r = p->s*1000.0 + 210866760000000.0; if( r>=0.0 && r<464269060800000.0 ){ clearYMD_HMS_TZ(p); p->iJD = (sqlite3_int64)(r + 0.5); p->validJD = 1; p->rawS = 0; rc = 0; | > | 23766 23767 23768 23769 23770 23771 23772 23773 23774 23775 23776 23777 23778 23779 23780 | /* ** unixepoch ** ** Treat the current value of p->s as the number of ** seconds since 1970. Convert to a real julian day number. */ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ if( idx>1 ) return 1; /* IMP: R-49255-55373 */ r = p->s*1000.0 + 210866760000000.0; if( r>=0.0 && r<464269060800000.0 ){ clearYMD_HMS_TZ(p); p->iJD = (sqlite3_int64)(r + 0.5); p->validJD = 1; p->rawS = 0; rc = 0; |
︙ | ︙ | |||
23684 23685 23686 23687 23688 23689 23690 | if( !z || parseDateOrTime(context, (char*)z, p) ){ return 1; } } for(i=1; i<argc; i++){ z = sqlite3_value_text(argv[i]); n = sqlite3_value_bytes(argv[i]); | | | 23980 23981 23982 23983 23984 23985 23986 23987 23988 23989 23990 23991 23992 23993 23994 | if( !z || parseDateOrTime(context, (char*)z, p) ){ return 1; } } 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; } |
︙ | ︙ | |||
28954 28955 28956 28957 28958 28959 28960 28961 | } /* ** Call this routine to record the fact that an OOM (out-of-memory) error ** has happened. This routine will set db->mallocFailed, and also ** temporarily disable the lookaside memory allocator and interrupt ** any running VDBEs. */ | > > > > > > > | > > | 29250 29251 29252 29253 29254 29255 29256 29257 29258 29259 29260 29261 29262 29263 29264 29265 29266 29267 29268 29269 29270 29271 29272 29273 29274 29275 29276 29277 29278 29279 29280 29281 29282 29283 29284 | } /* ** Call this routine to record the fact that an OOM (out-of-memory) error ** has happened. This routine will set db->mallocFailed, and also ** temporarily disable the lookaside memory allocator and interrupt ** any running VDBEs. ** ** Always return a NULL pointer so that this routine can be invoked using ** ** return sqlite3OomFault(db); ** ** and thereby avoid unnecessary stack frame allocations for the overwhelmingly ** common case where no OOM occurs. */ SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ db->mallocFailed = 1; if( db->nVdbeExec>0 ){ AtomicStore(&db->u1.isInterrupted, 1); } DisableLookaside; if( db->pParse ){ sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; } } return 0; } /* ** This routine reactivates the memory allocator and clears the ** db->mallocFailed flag as necessary. ** ** The memory allocator is not restarted if there are running |
︙ | ︙ | |||
32354 32355 32356 32357 32358 32359 32360 32361 32362 32363 32364 32365 32366 32367 32368 32369 32370 32371 32372 32373 32374 | ** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used ** during statement execution (sqlite3_step() etc.). */ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; va_list ap; sqlite3 *db = pParse->db; db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( db->errByteOffset<-1 ) db->errByteOffset = -1; if( db->suppressErr ){ sqlite3DbFree(db, zMsg); }else{ pParse->nErr++; sqlite3DbFree(db, pParse->zErrMsg); pParse->zErrMsg = zMsg; pParse->rc = SQLITE_ERROR; pParse->pWith = 0; } | > > > > > > | 32659 32660 32661 32662 32663 32664 32665 32666 32667 32668 32669 32670 32671 32672 32673 32674 32675 32676 32677 32678 32679 32680 32681 32682 32683 32684 32685 | ** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used ** during statement execution (sqlite3_step() etc.). */ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; va_list ap; sqlite3 *db = pParse->db; assert( db!=0 ); assert( db->pParse==pParse ); db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( db->errByteOffset<-1 ) db->errByteOffset = -1; if( db->suppressErr ){ sqlite3DbFree(db, zMsg); if( db->mallocFailed ){ pParse->nErr++; pParse->rc = SQLITE_NOMEM; } }else{ pParse->nErr++; sqlite3DbFree(db, pParse->zErrMsg); pParse->zErrMsg = zMsg; pParse->rc = SQLITE_ERROR; pParse->pWith = 0; } |
︙ | ︙ | |||
34332 34333 34334 34335 34336 34337 34338 | /* 166 */ "CursorLock" OpHelp(""), /* 167 */ "CursorUnlock" OpHelp(""), /* 168 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), /* 169 */ "VBegin" OpHelp(""), /* 170 */ "VCreate" OpHelp(""), /* 171 */ "VDestroy" OpHelp(""), /* 172 */ "VOpen" OpHelp(""), | > | | | | | | | | | | | | 34643 34644 34645 34646 34647 34648 34649 34650 34651 34652 34653 34654 34655 34656 34657 34658 34659 34660 34661 34662 34663 34664 34665 34666 34667 34668 | /* 166 */ "CursorLock" OpHelp(""), /* 167 */ "CursorUnlock" OpHelp(""), /* 168 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), /* 169 */ "VBegin" OpHelp(""), /* 170 */ "VCreate" OpHelp(""), /* 171 */ "VDestroy" OpHelp(""), /* 172 */ "VOpen" OpHelp(""), /* 173 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), /* 174 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), /* 175 */ "VRename" OpHelp(""), /* 176 */ "Pagecount" OpHelp(""), /* 177 */ "MaxPgcnt" OpHelp(""), /* 178 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), /* 179 */ "Trace" OpHelp(""), /* 180 */ "CursorHint" OpHelp(""), /* 181 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), /* 182 */ "Noop" OpHelp(""), /* 183 */ "Explain" OpHelp(""), /* 184 */ "Abortable" OpHelp(""), }; return azName[i]; } #endif /************** End of opcodes.c *********************************************/ /************** Begin file os_unix.c *****************************************/ |
︙ | ︙ | |||
56720 56721 56722 56723 56724 56725 56726 | ** ** This function is only called right before committing a transaction. ** Once this function has been called, the transaction must either be ** rolled back or committed. It is not safe to call this function and ** then continue writing to the database. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ | | < | 57032 57033 57034 57035 57036 57037 57038 57039 57040 57041 57042 57043 57044 57045 57046 | ** ** This function is only called right before committing a transaction. ** Once this function has been called, the transaction must either be ** rolled back or committed. It is not safe to call this function and ** then continue writing to the database. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ assert( pPager->dbSize>=nPage ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; /* At one point the code here called assertTruncateConstraint() to ** ensure that all pages being truncated away by this operation are, ** if one or more savepoints are open, present in the savepoint ** journal so that they can be restored if the savepoint is rolled |
︙ | ︙ | |||
63100 63101 63102 63103 63104 63105 63106 | ** Return WAL_RETRY which will cause the in-memory WAL-index to be ** rebuilt. */ rc = WAL_RETRY; goto begin_unreliable_shm_out; } /* Allocate a buffer to read frames into */ | > > | | | 63411 63412 63413 63414 63415 63416 63417 63418 63419 63420 63421 63422 63423 63424 63425 63426 63427 63428 63429 63430 63431 63432 63433 63434 63435 63436 63437 63438 63439 63440 63441 | ** Return WAL_RETRY which will cause the in-memory WAL-index to be ** rebuilt. */ rc = WAL_RETRY; goto begin_unreliable_shm_out; } /* Allocate a buffer to read frames into */ assert( (pWal->szPage & (pWal->szPage-1))==0 ); assert( pWal->szPage>=512 && pWal->szPage<=65536 ); szFrame = pWal->szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame); if( aFrame==0 ){ rc = SQLITE_NOMEM_BKPT; goto begin_unreliable_shm_out; } aData = &aFrame[WAL_FRAME_HDRSIZE]; /* Check to see if a complete transaction has been appended to the ** wal file since the heap-memory wal-index was created. If so, the ** heap-memory wal-index is discarded and WAL_RETRY returned to ** the caller. */ aSaveCksum[0] = pWal->hdr.aFrameCksum[0]; aSaveCksum[1] = pWal->hdr.aFrameCksum[1]; for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage); iOffset+szFrame<=szWal; iOffset+=szFrame ){ u32 pgno; /* Database page number for frame */ u32 nTruncate; /* dbsize field from frame header */ /* Read and decode the next log frame. */ |
︙ | ︙ | |||
68932 68933 68934 68935 68936 68937 68938 | pBt->usableSize = usableSize; pBt->pageSize = pageSize; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); return rc; } | > | | | > > > | 69245 69246 69247 69248 69249 69250 69251 69252 69253 69254 69255 69256 69257 69258 69259 69260 69261 69262 69263 69264 69265 | pBt->usableSize = usableSize; pBt->pageSize = pageSize; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); return rc; } if( nPage>nPageFile ){ if( sqlite3WritableSchema(pBt->db)==0 ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; }else{ nPage = nPageFile; } } /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to ** be less than 480. In other words, if the page size is 512, then the ** reserved space size cannot exceed 32. */ if( usableSize<480 ){ goto page1_init_failed; } |
︙ | ︙ | |||
76689 76690 76691 76692 76693 76694 76695 | */ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ Parse sParse; int rc = 0; | | < | | 77006 77007 77008 77009 77010 77011 77012 77013 77014 77015 77016 77017 77018 77019 77020 77021 77022 77023 77024 77025 77026 | */ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int i = sqlite3FindDbName(pDb, zDb); if( i==1 ){ Parse sParse; int rc = 0; sqlite3ParseObjectInit(&sParse,pDb); if( sqlite3OpenTempDatabase(&sParse) ){ sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, sParse.zErrMsg); sqlite3ParseObjectReset(&sParse); if( rc ){ return 0; } } if( i<0 ){ sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); |
︙ | ︙ | |||
78908 78909 78910 78911 78912 78913 78914 | sqlite3_value *pVal = 0; int negInt = 1; const char *zNeg = ""; int rc = SQLITE_OK; assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; | < < < < | 79224 79225 79226 79227 79228 79229 79230 79231 79232 79233 79234 79235 79236 79237 79238 | sqlite3_value *pVal = 0; int negInt = 1; const char *zNeg = ""; int rc = SQLITE_OK; assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; if( op==TK_REGISTER ) op = pExpr->op2; /* Compressed expressions only appear when parsing the DEFAULT clause ** on a table column definition, and hence only when pCtx==0. This ** check ensures that an EP_TokenOnly expression is never passed down ** into valueFromFunction(). */ assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); |
︙ | ︙ | |||
80705 80706 80707 80708 80709 80710 80711 | ** Change the comment on the most recently coded instruction. Or ** insert a No-op and add the comment to that new instruction. This ** makes the code easier to read during debugging. None of this happens ** in a production build. */ static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ assert( p->nOp>0 || p->aOp==0 ); | | < | 81017 81018 81019 81020 81021 81022 81023 81024 81025 81026 81027 81028 81029 81030 81031 | ** Change the comment on the most recently coded instruction. Or ** insert a No-op and add the comment to that new instruction. This ** makes the code easier to read during debugging. None of this happens ** in a production build. */ static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 ); if( p->nOp ){ assert( p->aOp ); sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); } } SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ |
︙ | ︙ | |||
85434 85435 85436 85437 85438 85439 85440 85441 85442 85443 85444 85445 85446 85447 | ** performance by substituting a NULL result, or some other light-weight ** value, as a signal to the xUpdate routine that the column is unchanged. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ assert( p ); return sqlite3_value_nochange(p->pOut); } /* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared ** statement, the exact same time is returned for each invocation regardless ** of the amount of time that elapses between invocations. In other words, ** the time returned is always the time of the first call. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 85745 85746 85747 85748 85749 85750 85751 85752 85753 85754 85755 85756 85757 85758 85759 85760 85761 85762 85763 85764 85765 85766 85767 85768 85769 85770 85771 85772 85773 85774 85775 85776 85777 85778 85779 85780 85781 85782 85783 85784 85785 85786 85787 85788 85789 85790 85791 85792 85793 85794 85795 85796 85797 85798 85799 85800 85801 85802 85803 85804 85805 85806 85807 85808 85809 85810 85811 85812 85813 85814 85815 85816 85817 85818 85819 85820 85821 85822 | ** performance by substituting a NULL result, or some other light-weight ** value, as a signal to the xUpdate routine that the column is unchanged. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ assert( p ); return sqlite3_value_nochange(p->pOut); } /* ** Implementation of sqlite3_vtab_in_first() (if bNext==0) and ** sqlite3_vtab_in_next() (if bNext!=0). */ static int valueFromValueList( sqlite3_value *pVal, /* Pointer to the ValueList object */ sqlite3_value **ppOut, /* Store the next value from the list here */ int bNext /* 1 for _next(). 0 for _first() */ ){ int rc; ValueList *pRhs; *ppOut = 0; if( pVal==0 ) return SQLITE_MISUSE; pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList"); if( pRhs==0 ) return SQLITE_MISUSE; if( bNext ){ rc = sqlite3BtreeNext(pRhs->pCsr, 0); }else{ int dummy = 0; rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy); assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) ); if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE; } if( rc==SQLITE_OK ){ u32 sz; /* Size of current row in bytes */ Mem sMem; /* Raw content of current row */ memset(&sMem, 0, sizeof(sMem)); sz = sqlite3BtreePayloadSize(pRhs->pCsr); rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); if( rc==SQLITE_OK ){ u8 *zBuf = (u8*)sMem.z; u32 iSerial; sqlite3_value *pOut = pRhs->pOut; int iOff = 1 + getVarint32(&zBuf[1], iSerial); sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut); pOut->enc = ENC(pOut->db); if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){ rc = SQLITE_NOMEM; }else{ *ppOut = pOut; } } sqlite3VdbeMemRelease(&sMem); } return rc; } /* ** Set the iterator value pVal to point to the first value in the set. ** Set (*ppOut) to point to this value before returning. */ SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){ return valueFromValueList(pVal, ppOut, 0); } /* ** Set the iterator value pVal to point to the next value in the set. ** Set (*ppOut) to point to this value before returning. */ SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){ return valueFromValueList(pVal, ppOut, 1); } /* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared ** statement, the exact same time is returned for each invocation regardless ** of the amount of time that elapses between invocations. In other words, ** the time returned is always the time of the first call. |
︙ | ︙ | |||
87535 87536 87537 87538 87539 87540 87541 | ** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning ** with pOp->p3. Return the hash. */ static u64 filterHash(const Mem *aMem, const Op *pOp){ int i, mx; u64 h = 0; | < | 87910 87911 87912 87913 87914 87915 87916 87917 87918 87919 87920 87921 87922 87923 | ** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning ** with pOp->p3. Return the hash. */ static u64 filterHash(const Mem *aMem, const Op *pOp){ int i, mx; u64 h = 0; assert( pOp->p4type==P4_INT32 ); for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){ const Mem *p = &aMem[i]; if( p->flags & (MEM_Int|MEM_IntReal) ){ h += p->u.i; }else if( p->flags & MEM_Real ){ h += sqlite3VdbeIntValue(p); |
︙ | ︙ | |||
89018 89019 89020 89021 89022 89023 89024 | if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); | | | 89392 89393 89394 89395 89396 89397 89398 89399 89400 89401 89402 89403 89404 89405 89406 | if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str; } if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); testcase( pIn3->flags & MEM_IntReal ); sqlite3VdbeMemStringify(pIn3, encoding, 1); testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); |
︙ | ︙ | |||
89844 89845 89846 89847 89848 89849 89850 89851 89852 89853 89854 89855 89856 89857 89858 89859 89860 89861 89862 89863 89864 89865 89866 89867 | break; } case COLTYPE_TEXT: { if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error; break; } case COLTYPE_REAL: { if( pIn1->flags & MEM_Int ){ /* When applying REAL affinity, if the result is still an MEM_Int ** that will fit in 6 bytes, then change the type to MEM_IntReal ** so that we keep the high-resolution integer value but know that ** the type really wants to be REAL. */ testcase( pIn1->u.i==140737488355328LL ); testcase( pIn1->u.i==140737488355327LL ); testcase( pIn1->u.i==-140737488355328LL ); testcase( pIn1->u.i==-140737488355329LL ); if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){ pIn1->flags |= MEM_IntReal; pIn1->flags &= ~MEM_Int; }else{ pIn1->u.r = (double)pIn1->u.i; pIn1->flags |= MEM_Real; pIn1->flags &= ~MEM_Int; } | > > | | 90218 90219 90220 90221 90222 90223 90224 90225 90226 90227 90228 90229 90230 90231 90232 90233 90234 90235 90236 90237 90238 90239 90240 90241 90242 90243 90244 90245 90246 90247 90248 90249 90250 90251 | break; } case COLTYPE_TEXT: { if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error; break; } case COLTYPE_REAL: { testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real ); testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal ); if( pIn1->flags & MEM_Int ){ /* When applying REAL affinity, if the result is still an MEM_Int ** that will fit in 6 bytes, then change the type to MEM_IntReal ** so that we keep the high-resolution integer value but know that ** the type really wants to be REAL. */ testcase( pIn1->u.i==140737488355328LL ); testcase( pIn1->u.i==140737488355327LL ); testcase( pIn1->u.i==-140737488355328LL ); testcase( pIn1->u.i==-140737488355329LL ); if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){ pIn1->flags |= MEM_IntReal; pIn1->flags &= ~MEM_Int; }else{ pIn1->u.r = (double)pIn1->u.i; pIn1->flags |= MEM_Real; pIn1->flags &= ~MEM_Int; } }else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){ goto vdbe_type_error; } break; } default: { /* COLTYPE_ANY. Accept anything. */ break; |
︙ | ︙ | |||
94590 94591 94592 94593 94594 94595 94596 94597 94598 94599 94600 94601 94602 94603 | assert( db->mallocFailed ); pModule->xClose(pVCur); goto no_mem; } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VFilter P1 P2 P3 P4 * ** Synopsis: iplan=r[P3] zplan='P4' ** ** P1 is a cursor opened using VOpen. P2 is an address to jump to if ** the filtered result set is empty. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 94966 94967 94968 94969 94970 94971 94972 94973 94974 94975 94976 94977 94978 94979 94980 94981 94982 94983 94984 94985 94986 94987 94988 94989 94990 94991 94992 94993 94994 94995 94996 94997 94998 94999 95000 95001 95002 95003 95004 95005 95006 95007 | assert( db->mallocFailed ); pModule->xClose(pVCur); goto no_mem; } break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VInitIn P1 P2 P3 * * ** Synopsis: r[P2]=ValueList(P1,P3) ** ** Set register P2 to be a pointer to a ValueList object for cursor P1 ** with cache register P3 and output register P3+1. This ValueList object ** can be used as the first argument to sqlite3_vtab_in_first() and ** sqlite3_vtab_in_next() to extract all of the values stored in the P1 ** cursor. Register P3 is used to hold the values returned by ** sqlite3_vtab_in_first() and sqlite3_vtab_in_next(). */ case OP_VInitIn: { /* out2 */ VdbeCursor *pC; /* The cursor containing the RHS values */ ValueList *pRhs; /* New ValueList object to put in reg[P2] */ pC = p->apCsr[pOp->p1]; pRhs = sqlite3_malloc64( sizeof(*pRhs) ); if( pRhs==0 ) goto no_mem; pRhs->pCsr = pC->uc.pCursor; pRhs->pOut = &aMem[pOp->p3]; pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Null; sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VFilter P1 P2 P3 P4 * ** Synopsis: iplan=r[P3] zplan='P4' ** ** P1 is a cursor opened using VOpen. P2 is an address to jump to if ** the filtered result set is empty. |
︙ | ︙ | |||
95577 95578 95579 95580 95581 95582 95583 | } #endif wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); | < > | < | 95981 95982 95983 95984 95985 95986 95987 95988 95989 95990 95991 95992 95993 95994 95995 95996 95997 | } #endif wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); while(1){ sqlite3ParseObjectInit(&sParse,db); if( !pBlob ) goto blob_open_out; sqlite3DbFree(db, zErr); zErr = 0; sqlite3BtreeEnterAll(db); pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); if( pTab && IsVirtual(pTab) ){ pTab = 0; |
︙ | ︙ | |||
95757 95758 95759 95760 95761 95762 95763 | pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); | | > > | | 96160 96161 96162 96163 96164 96165 96166 96167 96168 96169 96170 96171 96172 96173 96174 96175 96176 96177 96178 96179 96180 96181 96182 96183 96184 96185 96186 96187 | pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break; sqlite3ParseObjectReset(&sParse); } blob_open_out: if( rc==SQLITE_OK && db->mallocFailed==0 ){ *ppBlob = (sqlite3_blob *)pBlob; }else{ if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3ParseObjectReset(&sParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Close a blob handle that was previously created using |
︙ | ︙ | |||
100833 100834 100835 100836 100837 100838 100839 | if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 ){ /* Internal-use-only functions are disallowed unless the ** SQL is being compiled using sqlite3NestedParse() or ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be | | | 101238 101239 101240 101241 101242 101243 101244 101245 101246 101247 101248 101249 101250 101251 101252 | if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 ){ /* Internal-use-only functions are disallowed unless the ** SQL is being compiled using sqlite3NestedParse() or ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be ** used to activate internal functions for testing purposes */ no_such_func = 1; pDef = 0; }else if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 && !IN_RENAME_OBJECT ){ sqlite3ExprFunctionUsable(pParse, pExpr, pDef); |
︙ | ︙ | |||
101052 101053 101054 101055 101056 101057 101058 | testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); } break; } } | > | | 101457 101458 101459 101460 101461 101462 101463 101464 101465 101466 101467 101468 101469 101470 101471 101472 | testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); } break; } } assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); return pParse->nErr ? WRC_Abort : WRC_Continue; } /* ** pEList is a list of expressions which are really the result set of the ** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause. ** This routine checks to see if pE is a simple identifier which corresponds ** to the AS-name of one of the terms of the expression list. If it is, |
︙ | ︙ | |||
101466 101467 101468 101469 101470 101471 101472 | ** prior call to sqlite3SelectExpand(). When that happens, let ** sqlite3SelectPrep() do all of the processing for this SELECT. ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and ** this routine in the correct order. */ if( (p->selFlags & SF_Expanded)==0 ){ sqlite3SelectPrep(pParse, p, pOuterNC); | | | 101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 101883 101884 101885 101886 | ** prior call to sqlite3SelectExpand(). When that happens, let ** sqlite3SelectPrep() do all of the processing for this SELECT. ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and ** this routine in the correct order. */ if( (p->selFlags & SF_Expanded)==0 ){ sqlite3SelectPrep(pParse, p, pOuterNC); return pParse->nErr ? WRC_Abort : WRC_Prune; } isCompound = p->pPrior!=0; nCompound = 0; pLeftmost = p; while( p ){ assert( (p->selFlags & SF_Expanded)!=0 ); |
︙ | ︙ | |||
101514 101515 101516 101517 101518 101519 101520 | 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; sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); pParse->zAuthContext = zSavedContext; | | > | 101920 101921 101922 101923 101924 101925 101926 101927 101928 101929 101930 101931 101932 101933 101934 101935 | 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; sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); pParse->zAuthContext = zSavedContext; if( pParse->nErr ) return WRC_Abort; assert( db->mallocFailed==0 ); /* If the number of references to the outer context changed when ** expressions in the sub-select were resolved, the sub-select ** is correlated. It is not required to check the refcount on any ** but the innermost outer context object, as lookupName() increments ** the refcount on all contexts between the current one and the ** context containing the column when it resolves a name. */ |
︙ | ︙ | |||
104694 104695 104696 104697 104698 104699 104700 | colUsed = 0; /* Columns of index used so far */ for(i=0; i<nExpr; i++){ Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; | | < | 105101 105102 105103 105104 105105 105106 105107 105108 105109 105110 105111 105112 105113 105114 105115 | colUsed = 0; /* Columns of index used so far */ for(i=0; i<nExpr; i++){ Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); for(j=0; j<nExpr; j++){ if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue; assert( pIdx->azColl[j] ); if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ continue; } break; |
︙ | ︙ | |||
105171 105172 105173 105174 105175 105176 105177 | }else{ /* If there is no pre-existing limit add a limit of 1 */ pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); } pSel->iLimit = 0; if( sqlite3Select(pParse, pSel, &dest) ){ | < | | < | 105577 105578 105579 105580 105581 105582 105583 105584 105585 105586 105587 105588 105589 105590 105591 105592 | }else{ /* If there is no pre-existing limit add a limit of 1 */ pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); } pSel->iLimit = 0; if( sqlite3Select(pParse, pSel, &dest) ){ pExpr->op2 = pExpr->op; pExpr->op = TK_ERROR; return 0; } pExpr->iTable = rReg = dest.iSDParm; ExprSetVVAProperty(pExpr, EP_NoReduce); if( addrOnce ){ sqlite3VdbeJumpHere(v, addrOnce); } |
︙ | ︙ | |||
105391 105392 105393 105394 105395 105396 105397 | ** We will then skip the binary search of the RHS. */ if( destIfNull==destIfFalse ){ destStep2 = destIfFalse; }else{ destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse); } | < | | 105795 105796 105797 105798 105799 105800 105801 105802 105803 105804 105805 105806 105807 105808 105809 105810 105811 | ** We will then skip the binary search of the RHS. */ if( destIfNull==destIfFalse ){ destStep2 = destIfFalse; }else{ destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse); } for(i=0; i<nVector; i++){ Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i); if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error; if( sqlite3ExprCanBeNull(p) ){ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); VdbeCoverage(v); } } /* Step 3. The LHS is now known to be non-NULL. Do the binary search |
︙ | ︙ | |||
108569 108570 108571 108572 108573 108574 108575 | Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ Vdbe *v; /* The prepared statement under construction */ int r1; /* Temporary registers */ db = pParse->db; | > | > | 108972 108973 108974 108975 108976 108977 108978 108979 108980 108981 108982 108983 108984 108985 108986 108987 108988 | Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ Vdbe *v; /* The prepared statement under construction */ int r1; /* Temporary registers */ db = pParse->db; assert( db->pParse==pParse ); if( pParse->nErr ) return; assert( db->mallocFailed==0 ); pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ |
︙ | ︙ | |||
108695 108696 108697 108698 108699 108700 108701 | || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) ){ sqlite3NestedParse(pParse, "SELECT CASE WHEN quick_check GLOB 'CHECK*'" " THEN raise(ABORT,'CHECK constraint failed')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" | | | 109100 109101 109102 109103 109104 109105 109106 109107 109108 109109 109110 109111 109112 109113 109114 | || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) ){ sqlite3NestedParse(pParse, "SELECT CASE WHEN quick_check GLOB 'CHECK*'" " THEN raise(ABORT,'CHECK constraint failed')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" " FROM pragma_quick_check(%Q,%Q)" " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'", zTab, zDb ); } } } |
︙ | ︙ | |||
108980 108981 108982 108983 108984 108985 108986 | ** sqlite3_free(x); ** if( x==y ) ... ** ** Technically, as x no longer points into a valid object or to the byte ** following a valid object, it may not be used in comparison operations. */ static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ | > > | | 109385 109386 109387 109388 109389 109390 109391 109392 109393 109394 109395 109396 109397 109398 109399 109400 109401 | ** sqlite3_free(x); ** if( x==y ) ... ** ** Technically, as x no longer points into a valid object or to the byte ** following a valid object, it may not be used in comparison operations. */ static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ assert( pParse==pParse->db->pParse ); assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); if( pParse->nErr==0 ){ const RenameToken *p; u8 i = 0; for(p=pParse->pRename; p; p=p->pNext){ if( p->p ){ assert( p->p!=pPtr ); i += *(u8*)(p->p); } |
︙ | ︙ | |||
109377 109378 109379 109380 109381 109382 109383 | int rc; db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); /* Parse the SQL statement passed as the first argument. If no error ** occurs and the parse does not result in a new table, index or ** trigger object, the database must be corrupt. */ | | | 109784 109785 109786 109787 109788 109789 109790 109791 109792 109793 109794 109795 109796 109797 109798 | int rc; db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); /* Parse the SQL statement passed as the first argument. If no error ** occurs and the parse does not result in a new table, index or ** trigger object, the database must be corrupt. */ sqlite3ParseObjectInit(p, db); p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; rc = zSql ? sqlite3RunParser(p, zSql) : SQLITE_NOMEM; if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 |
︙ | ︙ | |||
109662 109663 109664 109665 109666 109667 109668 | while( (pIdx = pParse->pNewIndex)!=0 ){ pParse->pNewIndex = pIdx->pNext; sqlite3FreeIndex(db, pIdx); } sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->zErrMsg); renameTokenFree(db, pParse->pRename); | | | 110069 110070 110071 110072 110073 110074 110075 110076 110077 110078 110079 110080 110081 110082 110083 | while( (pIdx = pParse->pNewIndex)!=0 ){ pParse->pNewIndex = pIdx->pNext; sqlite3FreeIndex(db, pIdx); } sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->zErrMsg); renameTokenFree(db, pParse->pRename); sqlite3ParseObjectReset(pParse); } /* ** SQL function: ** ** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) ** |
︙ | ︙ | |||
110376 110377 110378 110379 110380 110381 110382 110383 110384 110385 110386 110387 110388 110389 | goto exit_drop_column; } /* Edit the sqlite_schema table */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); zDb = db->aDb[iDb].zDbSName; renameTestSchema(pParse, zDb, iDb==1, "", 0); renameFixQuotes(pParse, zDb, iDb==1); sqlite3NestedParse(pParse, "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " "sql = sqlite_drop_column(%d, sql, %d) " "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)" , zDb, iDb, iCol, pTab->zName | > > > > > > | 110783 110784 110785 110786 110787 110788 110789 110790 110791 110792 110793 110794 110795 110796 110797 110798 110799 110800 110801 110802 | goto exit_drop_column; } /* Edit the sqlite_schema table */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); zDb = db->aDb[iDb].zDbSName; #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ goto exit_drop_column; } #endif renameTestSchema(pParse, zDb, iDb==1, "", 0); renameFixQuotes(pParse, zDb, iDb==1); sqlite3NestedParse(pParse, "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " "sql = sqlite_drop_column(%d, sql, %d) " "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)" , zDb, iDb, iCol, pTab->zName |
︙ | ︙ | |||
112763 112764 112765 112766 112767 112768 112769 | SQLITE_OK!=resolveAttachExpr(&sName, pDbname) || SQLITE_OK!=resolveAttachExpr(&sName, pKey) ){ goto attach_end; } #ifndef SQLITE_OMIT_AUTHORIZATION | | | 113176 113177 113178 113179 113180 113181 113182 113183 113184 113185 113186 113187 113188 113189 113190 | SQLITE_OK!=resolveAttachExpr(&sName, pDbname) || SQLITE_OK!=resolveAttachExpr(&sName, pKey) ){ goto attach_end; } #ifndef SQLITE_OMIT_AUTHORIZATION if( ALWAYS(pAuthArg) ){ char *zAuthArg; if( pAuthArg->op==TK_STRING ){ assert( !ExprHasProperty(pAuthArg, EP_IntValue) ); zAuthArg = pAuthArg->u.zToken; }else{ zAuthArg = 0; } |
︙ | ︙ | |||
113424 113425 113426 113427 113428 113429 113430 113431 | */ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; assert( pParse->pToplevel==0 ); db = pParse->db; if( pParse->nested ) return; | > | | > | 113837 113838 113839 113840 113841 113842 113843 113844 113845 113846 113847 113848 113849 113850 113851 113852 113853 113854 113855 113856 113857 | */ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; assert( pParse->pToplevel==0 ); db = pParse->db; assert( db->pParse==pParse ); if( pParse->nested ) return; if( pParse->nErr ){ if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM; return; } assert( db->mallocFailed==0 ); /* Begin by generating some termination code at the end of the ** vdbe program */ v = pParse->pVdbe; if( v==0 ){ if( db->init.busy ){ |
︙ | ︙ | |||
113561 113562 113563 113564 113565 113566 113567 | /* Finally, jump back to the beginning of the executable code. */ sqlite3VdbeGoto(v, 1); } } /* Get the VDBE program ready for execution */ | > > | | 113976 113977 113978 113979 113980 113981 113982 113983 113984 113985 113986 113987 113988 113989 113990 113991 113992 | /* Finally, jump back to the beginning of the executable code. */ sqlite3VdbeGoto(v, 1); } } /* Get the VDBE program ready for execution */ assert( v!=0 || pParse->nErr ); assert( db->mallocFailed==0 || pParse->nErr ); if( pParse->nErr==0 ){ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ assert( pParse->pAinc==0 || pParse->nTab>0 ); sqlite3VdbeMakeReady(v, pParse); pParse->rc = SQLITE_DONE; }else{ pParse->rc = SQLITE_ERROR; |
︙ | ︙ | |||
115665 115666 115667 115668 115669 115670 115671 | sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); } pList->a[0].sortFlags = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pTab->iPKey = -1; sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, SQLITE_IDXTYPE_PRIMARYKEY); | | > | 116082 116083 116084 116085 116086 116087 116088 116089 116090 116091 116092 116093 116094 116095 116096 116097 116098 116099 116100 | sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); } pList->a[0].sortFlags = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pTab->iPKey = -1; sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, SQLITE_IDXTYPE_PRIMARYKEY); if( pParse->nErr ){ pTab->tabFlags &= ~TF_WithoutRowid; return; } assert( db->mallocFailed==0 ); pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk->nKeyCol==1 ); }else{ pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); /* |
︙ | ︙ | |||
116409 116410 116411 116412 116413 116414 116415 | ** The names of the columns in the table are taken from ** arglist which is stored in pTable->pCheck. The pCheck field ** normally holds CHECK constraints on an ordinary table, but for ** a VIEW it holds the list of column names. */ sqlite3ColumnsFromExprList(pParse, pTable->pCheck, &pTable->nCol, &pTable->aCol); | < | > | 116827 116828 116829 116830 116831 116832 116833 116834 116835 116836 116837 116838 116839 116840 116841 116842 116843 116844 | ** The names of the columns in the table are taken from ** arglist which is stored in pTable->pCheck. The pCheck field ** normally holds CHECK constraints on an ordinary table, but for ** a VIEW it holds the list of column names. */ sqlite3ColumnsFromExprList(pParse, pTable->pCheck, &pTable->nCol, &pTable->aCol); if( pParse->nErr==0 && pTable->nCol==pSel->pEList->nExpr ){ assert( db->mallocFailed==0 ); sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel, SQLITE_AFF_NONE); } }else{ /* CREATE VIEW name AS... without an argument list. Construct ** the column names from the SELECT statement that defines the view. */ |
︙ | ︙ | |||
117031 117032 117033 117034 117035 117036 117037 | if( v==0 ) return; if( memRootPage>=0 ){ tnum = (Pgno)memRootPage; }else{ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); | | | 117449 117450 117451 117452 117453 117454 117455 117456 117457 117458 117459 117460 117461 117462 117463 | if( v==0 ) return; if( memRootPage>=0 ){ tnum = (Pgno)memRootPage; }else{ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); assert( pKey!=0 || pParse->nErr ); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*) sqlite3KeyInfoRef(pKey), P4_KEYINFO); /* Open the table. Loop through all rows of the table, inserting index |
︙ | ︙ | |||
117195 117196 117197 117198 117199 117200 117201 | Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ int nExtra = 0; /* Space allocated for zExtra[] */ int nExtraCol; /* Number of extra columns needed */ char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ | > | > | 117613 117614 117615 117616 117617 117618 117619 117620 117621 117622 117623 117624 117625 117626 117627 117628 117629 117630 117631 | Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ int nExtra = 0; /* Space allocated for zExtra[] */ int nExtraCol; /* Number of extra columns needed */ char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ assert( db->pParse==pParse ); if( pParse->nErr ){ goto exit_create_index; } assert( db->mallocFailed==0 ); if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } if( sqlite3HasExplicitNulls(pParse, pList) ){ |
︙ | ︙ | |||
117261 117262 117263 117264 117265 117266 117267 | pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); | < | 117681 117682 117683 117684 117685 117686 117687 117688 117689 117690 117691 117692 117693 117694 | pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 && pTblName!=0 #if SQLITE_USER_AUTHENTICATION && sqlite3UserAuthTable(pTab->zName)==0 #endif ){ |
︙ | ︙ | |||
117825 117826 117827 117828 117829 117830 117831 | */ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; int iDb; | < > | 118244 118245 118246 118247 118248 118249 118250 118251 118252 118253 118254 118255 118256 118257 118258 118259 118260 118261 | */ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; int iDb; if( db->mallocFailed ){ goto exit_drop_index; } assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */ assert( pName->nSrc==1 ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_drop_index; } pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ if( !ifExists ){ |
︙ | ︙ | |||
119744 119745 119746 119747 119748 119749 119750 | #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif memset(&sContext, 0, sizeof(sContext)); db = pParse->db; | > | > | 120163 120164 120165 120166 120167 120168 120169 120170 120171 120172 120173 120174 120175 120176 120177 120178 120179 120180 120181 | #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif memset(&sContext, 0, sizeof(sContext)); db = pParse->db; assert( db->pParse==pParse ); if( pParse->nErr ){ goto delete_from_cleanup; } assert( db->mallocFailed==0 ); assert( pTabList->nSrc==1 ); /* Locate the table which we want to delete. This table has to be ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect ** an SrcList* parameter instead of just a Table* parameter. |
︙ | ︙ | |||
119927 119928 119929 119930 119931 119932 119933 | ** to be deleted, based on the WHERE clause. Set variable eOnePass ** to indicate the strategy used to implement this delete: ** ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ | | | 120348 120349 120350 120351 120352 120353 120354 120355 120356 120357 120358 120359 120360 120361 120362 | ** to be deleted, based on the WHERE clause. Set variable eOnePass ** to indicate the strategy used to implement this delete: ** ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); if( sqlite3WhereUsesDeferredSeek(pWInfo) ){ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur); |
︙ | ︙ | |||
120540 120541 120542 120543 120544 120545 120546 120547 120548 120549 120550 120551 120552 120553 | ** Return the subtype of X */ static void subtypeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ sqlite3_result_int(context, sqlite3_value_subtype(argv[0])); } /* ** Implementation of the length() function */ static void lengthFunc( | > | 120961 120962 120963 120964 120965 120966 120967 120968 120969 120970 120971 120972 120973 120974 120975 | ** Return the subtype of X */ static void subtypeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ UNUSED_PARAMETER(argc); sqlite3_result_int(context, sqlite3_value_subtype(argv[0])); } /* ** Implementation of the length() function */ static void lengthFunc( |
︙ | ︙ | |||
123470 123471 123472 123473 123474 123475 123476 | sNameContext.pParse = pParse; sqlite3ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment either the deferred or immediate ** foreign key constraint counter. */ if( pParse->nErr==0 ){ | | | 123892 123893 123894 123895 123896 123897 123898 123899 123900 123901 123902 123903 123904 123905 123906 | sNameContext.pParse = pParse; sqlite3ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment either the deferred or immediate ** foreign key constraint counter. */ if( pParse->nErr==0 ){ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0); sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); if( pWInfo ){ sqlite3WhereEnd(pWInfo); } } /* Clean up the WHERE clause constructed above. */ |
︙ | ︙ | |||
125012 125013 125014 125015 125016 125017 125018 | #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of trigger times */ #endif db = pParse->db; | > | > | 125434 125435 125436 125437 125438 125439 125440 125441 125442 125443 125444 125445 125446 125447 125448 125449 125450 125451 125452 | #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of trigger times */ #endif db = pParse->db; assert( db->pParse==pParse ); if( pParse->nErr ){ goto insert_cleanup; } assert( db->mallocFailed==0 ); dest.iSDParm = 0; /* Suppress a harmless compiler warning */ /* If the Select object is really just a simple VALUES() list with a ** single row (the common case) then keep that one row of values ** and discard the other (unused) parts of the pSelect object */ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ |
︙ | ︙ | |||
125190 125191 125192 125193 125194 125195 125196 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); dest.iSdst = bIdListInOrder ? regData : 0; dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; | > | > | 125614 125615 125616 125617 125618 125619 125620 125621 125622 125623 125624 125625 125626 125627 125628 125629 125630 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); dest.iSdst = bIdListInOrder ? regData : 0; dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; assert( db->pParse==pParse ); if( rc || pParse->nErr ) goto insert_cleanup; assert( db->mallocFailed==0 ); sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to |
︙ | ︙ | |||
127935 127936 127937 127938 127939 127940 127941 127942 127943 127944 127945 127946 127947 127948 | sqlite3_int64 (*total_changes64)(sqlite3*); /* Version 3.37.0 and later */ int (*autovacuum_pages)(sqlite3*, unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), void*, void(*)(void*)); /* Version 3.38.0 and later */ int (*error_offset)(sqlite3*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( | > > > > > | 128361 128362 128363 128364 128365 128366 128367 128368 128369 128370 128371 128372 128373 128374 128375 128376 128377 128378 128379 | sqlite3_int64 (*total_changes64)(sqlite3*); /* Version 3.37.0 and later */ int (*autovacuum_pages)(sqlite3*, unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), void*, void(*)(void*)); /* Version 3.38.0 and later */ int (*error_offset)(sqlite3*); int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**); int (*vtab_distinct)(sqlite3_index_info*); int (*vtab_in)(sqlite3_index_info*,int,int); int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); int (*vtab_in_next)(sqlite3_value*,sqlite3_value**); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( |
︙ | ︙ | |||
128248 128249 128250 128251 128252 128253 128254 128255 128256 128257 128258 128259 128260 128261 | /* Version 3.36.1 and later */ #define sqlite3_changes64 sqlite3_api->changes64 #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages /* Version 3.38.0 and later */ #define sqlite3_error_offset sqlite3_api->error_offset #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > > > > | 128679 128680 128681 128682 128683 128684 128685 128686 128687 128688 128689 128690 128691 128692 128693 128694 128695 128696 128697 | /* Version 3.36.1 and later */ #define sqlite3_changes64 sqlite3_api->changes64 #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages /* Version 3.38.0 and later */ #define sqlite3_error_offset sqlite3_api->error_offset #define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value #define sqlite3_vtab_distinct sqlite3_api->vtab_distinct #define sqlite3_vtab_in sqlite3_api->vtab_in #define sqlite3_vtab_in_first sqlite3_api->vtab_in_first #define sqlite3_vtab_in_next sqlite3_api->vtab_in_next #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
︙ | ︙ | |||
128739 128740 128741 128742 128743 128744 128745 128746 128747 128748 128749 128750 128751 128752 | /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, /* Version 3.38.0 and later */ sqlite3_error_offset, }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else | > > > > > | 129175 129176 129177 129178 129179 129180 129181 129182 129183 129184 129185 129186 129187 129188 129189 129190 129191 129192 129193 | /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, /* Version 3.38.0 and later */ sqlite3_error_offset, sqlite3_vtab_rhs_value, sqlite3_vtab_distinct, sqlite3_vtab_in, sqlite3_vtab_in_first, sqlite3_vtab_in_next }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
︙ | ︙ | |||
131040 131041 131042 131043 131044 131045 131046 131047 131048 131049 131050 131051 131052 131053 | char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName); if( zSql ){ sqlite3_stmt *pDummy = 0; (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0); (void)sqlite3_finalize(pDummy); sqlite3DbFree(db, zSql); } pHash = &db->aDb[ii].pSchema->tblHash; break; } } } for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){ | > > > > | 131481 131482 131483 131484 131485 131486 131487 131488 131489 131490 131491 131492 131493 131494 131495 131496 131497 131498 | char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName); if( zSql ){ sqlite3_stmt *pDummy = 0; (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0); (void)sqlite3_finalize(pDummy); sqlite3DbFree(db, zSql); } if( db->mallocFailed ){ sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; } pHash = &db->aDb[ii].pSchema->tblHash; break; } } } for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){ |
︙ | ︙ | |||
133076 133077 133078 133079 133080 133081 133082 | } return i; } /* ** Free all memory allocations in the pParse object */ | | > > < | | | < > > > | | 133521 133522 133523 133524 133525 133526 133527 133528 133529 133530 133531 133532 133533 133534 133535 133536 133537 133538 133539 133540 133541 133542 133543 133544 133545 133546 133547 133548 133549 133550 133551 133552 133553 133554 133555 133556 133557 133558 133559 133560 133561 133562 133563 133564 133565 133566 133567 133568 133569 133570 133571 | } return i; } /* ** Free all memory allocations in the pParse object */ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ sqlite3 *db = pParse->db; assert( db!=0 ); assert( db->pParse==pParse ); assert( pParse->nested==0 ); #ifndef SQLITE_OMIT_SHARED_CACHE sqlite3DbFree(db, pParse->aTableLock); #endif while( pParse->pCleanup ){ ParseCleanup *pCleanup = pParse->pCleanup; pParse->pCleanup = pCleanup->pNext; pCleanup->xCleanup(db, pCleanup->pPtr); sqlite3DbFreeNN(db, pCleanup); } sqlite3DbFree(db, pParse->aLabel); if( pParse->pConstExpr ){ sqlite3ExprListDelete(db, pParse->pConstExpr); } assert( db->lookaside.bDisable >= pParse->disableLookaside ); db->lookaside.bDisable -= pParse->disableLookaside; db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; assert( pParse->db->pParse==pParse ); db->pParse = pParse->pOuterParse; pParse->db = 0; pParse->disableLookaside = 0; } /* ** Add a new cleanup operation to a Parser. The cleanup should happen when ** the parser object is destroyed. But, beware: the cleanup might happen ** immediately. ** ** Use this mechanism for uncommon cleanups. There is a higher setup ** cost for this mechansim (an extra malloc), so it should not be used ** for common cleanups that happen on most calls. But for less ** common cleanups, we save a single NULL-pointer comparison in ** sqlite3ParseObjectReset(), which reduces the total CPU cycle count. ** ** If a memory allocation error occurs, then the cleanup happens immediately. ** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the ** pParse->earlyCleanup flag is set in that case. Calling code show verify ** that test cases exist for which this happens, to guard against possible ** use-after-free errors following an OOM. The preferred way to do this is ** to immediately follow the call to this routine with: |
︙ | ︙ | |||
133148 133149 133150 133151 133152 133153 133154 133155 133156 133157 133158 133159 133160 133161 133162 133163 133164 133165 133166 133167 133168 133169 133170 133171 | pPtr = 0; #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) pParse->earlyCleanup = 1; #endif } return pPtr; } /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ Vdbe *pReprepare, /* VM being reprepared */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ Parse sParse; /* Parsing context */ | > > > > > > > > > > > > > > > > > > > > | > > > | | 133596 133597 133598 133599 133600 133601 133602 133603 133604 133605 133606 133607 133608 133609 133610 133611 133612 133613 133614 133615 133616 133617 133618 133619 133620 133621 133622 133623 133624 133625 133626 133627 133628 133629 133630 133631 133632 133633 133634 133635 133636 133637 133638 133639 133640 133641 133642 133643 133644 133645 133646 133647 133648 133649 133650 133651 133652 133653 133654 | pPtr = 0; #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) pParse->earlyCleanup = 1; #endif } return pPtr; } /* ** Turn bulk memory into a valid Parse object and link that Parse object ** into database connection db. ** ** Call sqlite3ParseObjectReset() to undo this operation. ** ** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which ** is generated by Lemon. */ SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){ memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); assert( db->pParse!=pParse ); pParse->pOuterParse = db->pParse; db->pParse = pParse; pParse->db = db; if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory"); } /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ Vdbe *pReprepare, /* VM being reprepared */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ Parse sParse; /* Parsing context */ /* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */ memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ); memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); sParse.pOuterParse = db->pParse; db->pParse = &sParse; sParse.db = db; sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory"); assert( sqlite3_mutex_held(db->mutex) ); /* For a long-term use prepared statement avoid the use of ** lookaside memory. */ if( prepFlags & SQLITE_PREPARE_PERSISTENT ){ sParse.disableLookaside++; |
︙ | ︙ | |||
133222 133223 133224 133225 133226 133227 133228 | } } } } sqlite3VtabUnlockList(db); | < | 133693 133694 133695 133696 133697 133698 133699 133700 133701 133702 133703 133704 133705 133706 | } } } } sqlite3VtabUnlockList(db); if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; testcase( nBytes==mxLen ); testcase( nBytes==mxLen+1 ); if( nBytes>mxLen ){ sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); |
︙ | ︙ | |||
133289 133290 133291 133292 133293 133294 133295 | TriggerPrg *pT = sParse.pTriggerPrg; sParse.pTriggerPrg = pT->pNext; sqlite3DbFree(db, pT); } end_prepare: | | | 133759 133760 133761 133762 133763 133764 133765 133766 133767 133768 133769 133770 133771 133772 133773 | TriggerPrg *pT = sParse.pTriggerPrg; sParse.pTriggerPrg = pT->pNext; sqlite3DbFree(db, pT); } end_prepare: sqlite3ParseObjectReset(&sParse); return rc; } static int sqlite3LockAndPrepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ |
︙ | ︙ | |||
134944 134945 134946 134947 134948 134949 134950 | p->nKeyField = (u16)N; p->nAllField = (u16)(N+X); p->enc = ENC(db); p->db = db; p->nRef = 1; memset(&p[1], 0, nExtra); }else{ | | | 135414 135415 135416 135417 135418 135419 135420 135421 135422 135423 135424 135425 135426 135427 135428 | p->nKeyField = (u16)N; p->nAllField = (u16)(N+X); p->enc = ENC(db); p->db = db; p->nRef = 1; memset(&p[1], 0, nExtra); }else{ return (KeyInfo*)sqlite3OomFault(db); } return p; } /* ** Deallocate a KeyInfo object */ |
︙ | ︙ | |||
135115 135116 135117 135118 135119 135120 135121 135122 135123 135124 135125 135126 135127 135128 | sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); } #endif iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ regRowid = 0; regRow = pDest->iSdst; }else{ regRowid = sqlite3GetTempReg(pParse); if( eDest==SRT_EphemTab || eDest==SRT_Table ){ regRow = sqlite3GetTempReg(pParse); nColumn = 0; | > > > | 135585 135586 135587 135588 135589 135590 135591 135592 135593 135594 135595 135596 135597 135598 135599 135600 135601 | sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); } #endif iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ if( eDest==SRT_Mem && p->iOffset ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst); } regRowid = 0; regRow = pDest->iSdst; }else{ regRowid = sqlite3GetTempReg(pParse); if( eDest==SRT_EphemTab || eDest==SRT_Table ){ regRow = sqlite3GetTempReg(pParse); nColumn = 0; |
︙ | ︙ | |||
136973 136974 136975 136976 136977 136978 136979 136980 136981 136982 136983 136984 136985 136986 | if( nSelect<=3 ){ pSplit = p; }else{ pSplit = p; for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; } } pPrior = pSplit->pPrior; pSplit->pPrior = 0; pPrior->pNext = 0; assert( p->pOrderBy == pOrderBy ); assert( pOrderBy!=0 || db->mallocFailed ); pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); | > | 137446 137447 137448 137449 137450 137451 137452 137453 137454 137455 137456 137457 137458 137459 137460 | if( nSelect<=3 ){ pSplit = p; }else{ pSplit = p; for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; } } pPrior = pSplit->pPrior; assert( pPrior!=0 ); pSplit->pPrior = 0; pPrior->pNext = 0; assert( p->pOrderBy == pOrderBy ); assert( pOrderBy!=0 || db->mallocFailed ); pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); |
︙ | ︙ | |||
139124 139125 139126 139127 139128 139129 139130 | if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){ return WRC_Abort; } } /* Process NATURAL keywords, and ON and USING clauses of joins. */ | > | | 139598 139599 139600 139601 139602 139603 139604 139605 139606 139607 139608 139609 139610 139611 139612 139613 | if( pFrom->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pFrom) ){ return WRC_Abort; } } /* Process NATURAL keywords, and ON and USING clauses of joins. */ assert( db->mallocFailed==0 || pParse->nErr!=0 ); if( pParse->nErr || sqliteProcessJoin(pParse, p) ){ return WRC_Abort; } /* For every "*" that occurs in the column list, insert the names of ** all columns in all tables. And for every TABLE.* insert the names ** of all columns in TABLE. The parser inserted a special expression ** with the TK_ASTERISK operator for each "*" that it found in the column |
︙ | ︙ | |||
139421 139422 139423 139424 139425 139426 139427 139428 139429 139430 | */ SQLITE_PRIVATE void sqlite3SelectPrep( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ assert( p!=0 || pParse->db->mallocFailed ); if( pParse->db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); | > | | > > | | 139896 139897 139898 139899 139900 139901 139902 139903 139904 139905 139906 139907 139908 139909 139910 139911 139912 139913 139914 139915 139916 139917 139918 139919 139920 139921 139922 139923 139924 139925 139926 139927 139928 139929 139930 139931 139932 139933 139934 139935 139936 | */ SQLITE_PRIVATE void sqlite3SelectPrep( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ assert( p!=0 || pParse->db->mallocFailed ); assert( pParse->db->pParse==pParse ); if( pParse->db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); if( pParse->nErr ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if( pParse->nErr ) return; sqlite3SelectAddTypeInfo(pParse, p); } /* ** Reset the aggregate accumulator. ** ** The aggregate accumulator is a set of memory cells that hold ** intermediate results while calculating an aggregate. This ** routine generates code that stores NULLs in all of those memory ** cells. */ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; int nReg = pAggInfo->nFunc + pAggInfo->nColumn; assert( pParse->db->pParse==pParse ); assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); if( nReg==0 ) return; if( pParse->nErr ) return; #ifdef SQLITE_DEBUG /* Verify that all AggInfo registers are within the range specified by ** AggInfo.mnReg..AggInfo.mxReg */ assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); for(i=0; i<pAggInfo->nColumn; i++){ assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg ); |
︙ | ︙ | |||
139867 139868 139869 139870 139871 139872 139873 139874 | SortCtx sSort; /* Info on how to code the ORDER BY clause */ int iEnd; /* Address of the end of the query */ sqlite3 *db; /* The database connection */ ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ u8 minMaxFlag; /* Flag for min/max queries */ db = pParse->db; v = sqlite3GetVdbe(pParse); | > | > | 140345 140346 140347 140348 140349 140350 140351 140352 140353 140354 140355 140356 140357 140358 140359 140360 140361 140362 140363 140364 | SortCtx sSort; /* Info on how to code the ORDER BY clause */ int iEnd; /* Address of the end of the query */ sqlite3 *db; /* The database connection */ ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ u8 minMaxFlag; /* Flag for min/max queries */ db = pParse->db; assert( pParse==db->pParse ); v = sqlite3GetVdbe(pParse); if( p==0 || pParse->nErr ){ return 1; } assert( db->mallocFailed==0 ); if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; #if SELECTTRACE_ENABLED SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); if( sqlite3SelectTrace & 0x100 ){ sqlite3TreeViewSelect(0, p, 0); } #endif |
︙ | ︙ | |||
139905 139906 139907 139908 139909 139910 139911 | testcase( pParse->earlyCleanup ); p->pOrderBy = 0; } p->selFlags &= ~SF_Distinct; p->selFlags |= SF_NoopOrderBy; } sqlite3SelectPrep(pParse, p, 0); | | > | 140385 140386 140387 140388 140389 140390 140391 140392 140393 140394 140395 140396 140397 140398 140399 140400 140401 140402 | testcase( pParse->earlyCleanup ); p->pOrderBy = 0; } p->selFlags &= ~SF_Distinct; p->selFlags |= SF_NoopOrderBy; } sqlite3SelectPrep(pParse, p, 0); if( pParse->nErr ){ goto select_end; } assert( db->mallocFailed==0 ); assert( p->pEList!=0 ); #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif |
︙ | ︙ | |||
139951 139952 139953 139954 139955 139956 139957 | if( pDest->eDest==SRT_Output ){ sqlite3GenerateColumnNames(pParse, p); } #ifndef SQLITE_OMIT_WINDOWFUNC if( sqlite3WindowRewrite(pParse, p) ){ | | | 140432 140433 140434 140435 140436 140437 140438 140439 140440 140441 140442 140443 140444 140445 140446 | if( pDest->eDest==SRT_Output ){ sqlite3GenerateColumnNames(pParse, p); } #ifndef SQLITE_OMIT_WINDOWFUNC if( sqlite3WindowRewrite(pParse, p) ){ assert( pParse->nErr ); goto select_end; } #if SELECTTRACE_ENABLED if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n")); sqlite3TreeViewSelect(0, p, 0); } |
︙ | ︙ | |||
140427 140428 140429 140430 140431 140432 140433 | #endif assert( WHERE_USE_LIMIT==SF_FixedLimit ); /* Begin the database scan. */ SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, | | | 140908 140909 140910 140911 140912 140913 140914 140915 140916 140917 140918 140919 140920 140921 140922 | #endif assert( WHERE_USE_LIMIT==SF_FixedLimit ); /* Begin the database scan. */ SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, p->pEList, p, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); } if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){ sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo); } |
︙ | ︙ | |||
140691 140692 140693 140694 140695 140696 140697 | ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct, | | | 141172 141173 141174 141175 141176 141177 141178 141179 141180 141181 141182 141183 141184 141185 141186 | ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct, 0, (WHERE_GROUPBY|(orderByGrp ? WHERE_SORTBYGROUP : 0)|distFlag), 0 ); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDistinct); goto select_end; } eDist = sqlite3WhereIsDistinct(pWInfo); SELECTTRACE(1,pParse,p,("WhereBegin returns\n")); |
︙ | ︙ | |||
140989 140990 140991 140992 140993 140994 140995 | ** be an appropriate ORDER BY expression for the optimization. */ assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, | | | 141470 141471 141472 141473 141474 141475 141476 141477 141478 141479 141480 141481 141482 141483 141484 | ** be an appropriate ORDER BY expression for the optimization. */ assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, pDistinct, 0, minMaxFlag|distFlag, 0); if( pWInfo==0 ){ goto select_end; } SELECTTRACE(1,pParse,p,("WhereBegin returns\n")); eDist = sqlite3WhereIsDistinct(pWInfo); updateAccumulator(pParse, regAcc, pAggInfo, eDist); if( eDist!=WHERE_DISTINCT_NOOP ){ |
︙ | ︙ | |||
141046 141047 141048 141049 141050 141051 141052 | rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: assert( db->mallocFailed==0 || db->mallocFailed==1 ); | | | 141527 141528 141529 141530 141531 141532 141533 141534 141535 141536 141537 141538 141539 141540 141541 | rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: assert( db->mallocFailed==0 || db->mallocFailed==1 ); assert( db->mallocFailed==0 || pParse->nErr!=0 ); sqlite3ExprListDelete(db, pMinMaxOrderBy); #ifdef SQLITE_DEBUG if( pAggInfo && !db->mallocFailed ){ for(i=0; i<pAggInfo->nColumn; i++){ Expr *pExpr = pAggInfo->aCol[i].pCExpr; assert( pExpr!=0 ); assert( pExpr->pAggInfo==pAggInfo ); |
︙ | ︙ | |||
142198 142199 142200 142201 142202 142203 142204 142205 142206 142207 142208 142209 142210 142211 142212 142213 142214 | ExprList *pNew; Returning *pReturning; Select sSelect; SrcList sFrom; assert( v!=0 ); assert( pParse->bReturning ); pReturning = pParse->u1.pReturning; assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); | > > | | | 142679 142680 142681 142682 142683 142684 142685 142686 142687 142688 142689 142690 142691 142692 142693 142694 142695 142696 142697 142698 142699 142700 142701 142702 142703 142704 142705 142706 142707 142708 142709 142710 142711 142712 142713 142714 142715 142716 142717 142718 142719 142720 142721 142722 142723 | ExprList *pNew; Returning *pReturning; Select sSelect; SrcList sFrom; assert( v!=0 ); assert( pParse->bReturning ); assert( db->pParse==pParse ); pReturning = pParse->u1.pReturning; assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); if( !db->mallocFailed ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); if( pReturning->nRetCol==0 ){ pReturning->nRetCol = pNew->nExpr; pReturning->iRetCur = pParse->nTab++; } sNC.pParse = pParse; sNC.uNC.iBaseReg = regIn; sNC.ncFlags = NC_UBaseReg; pParse->eTriggerOp = pTrigger->op; pParse->pTriggerTab = pTab; if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK && ALWAYS(!db->mallocFailed) ){ int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; pParse->nMem += nCol+2; pReturning->iRetReg = reg; for(i=0; i<nCol; i++){ |
︙ | ︙ | |||
142390 142391 142392 142393 142394 142395 142396 | Parse *pTop = sqlite3ParseToplevel(pParse); sqlite3 *db = pParse->db; /* Database handle */ TriggerPrg *pPrg; /* Value to return */ Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ Vdbe *v; /* Temporary VM */ NameContext sNC; /* Name context for sub-vdbe */ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ | < > | 142873 142874 142875 142876 142877 142878 142879 142880 142881 142882 142883 142884 142885 142886 142887 142888 | Parse *pTop = sqlite3ParseToplevel(pParse); sqlite3 *db = pParse->db; /* Database handle */ TriggerPrg *pPrg; /* Value to return */ Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ Vdbe *v; /* Temporary VM */ NameContext sNC; /* Name context for sub-vdbe */ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ Parse sSubParse; /* Parse context for sub-vdbe */ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); assert( pTop->pVdbe ); /* Allocate the TriggerPrg and SubProgram objects. To ensure that they ** are freed if an error occurs, link them into the Parse.pTriggerPrg ** list of the top-level Parse object sooner rather than later. */ |
︙ | ︙ | |||
142413 142414 142415 142416 142417 142418 142419 | pPrg->pTrigger = pTrigger; pPrg->orconf = orconf; pPrg->aColmask[0] = 0xffffffff; pPrg->aColmask[1] = 0xffffffff; /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ | < | | < | | | | | | | | 142896 142897 142898 142899 142900 142901 142902 142903 142904 142905 142906 142907 142908 142909 142910 142911 142912 142913 142914 142915 142916 142917 142918 142919 142920 | pPrg->pTrigger = pTrigger; pPrg->orconf = orconf; pPrg->aColmask[0] = 0xffffffff; pPrg->aColmask[1] = 0xffffffff; /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ sqlite3ParseObjectInit(&sSubParse, db); memset(&sNC, 0, sizeof(sNC)); sNC.pParse = &sSubParse; sSubParse.pTriggerTab = pTab; sSubParse.pToplevel = pTop; sSubParse.zAuthContext = pTrigger->zName; sSubParse.eTriggerOp = pTrigger->op; sSubParse.nQueryLoop = pParse->nQueryLoop; sSubParse.disableVtab = pParse->disableVtab; v = sqlite3GetVdbe(&sSubParse); if( v ){ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", pTrigger->zName, onErrorText(orconf), (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), (pTrigger->op==TK_INSERT ? "INSERT" : ""), (pTrigger->op==TK_DELETE ? "DELETE" : ""), |
︙ | ︙ | |||
142451 142452 142453 142454 142455 142456 142457 | ** (or NULL) the sub-vdbe is immediately halted by jumping to the ** OP_Halt inserted at the end of the program. */ if( pTrigger->pWhen ){ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); if( db->mallocFailed==0 && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) ){ | | | | > | | | | | | > > | | < < | 142932 142933 142934 142935 142936 142937 142938 142939 142940 142941 142942 142943 142944 142945 142946 142947 142948 142949 142950 142951 142952 142953 142954 142955 142956 142957 142958 142959 142960 142961 142962 142963 142964 142965 142966 142967 142968 142969 142970 142971 142972 142973 142974 142975 142976 142977 142978 | ** (or NULL) the sub-vdbe is immediately halted by jumping to the ** OP_Halt inserted at the end of the program. */ if( pTrigger->pWhen ){ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); if( db->mallocFailed==0 && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) ){ iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse); sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); } sqlite3ExprDelete(db, pWhen); } /* Code the trigger program into the sub-vdbe. */ codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf); /* Insert an OP_Halt at the end of the sub-program. */ if( iEndTrigger ){ sqlite3VdbeResolveLabel(v, iEndTrigger); } sqlite3VdbeAddOp0(v, OP_Halt); VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); transferParseError(pParse, &sSubParse); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } pProgram->nMem = sSubParse.nMem; pProgram->nCsr = sSubParse.nTab; pProgram->token = (void *)pTrigger; pPrg->aColmask[0] = sSubParse.oldmask; pPrg->aColmask[1] = sSubParse.newmask; sqlite3VdbeDelete(v); }else{ transferParseError(pParse, &sSubParse); } assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg ); sqlite3ParseObjectReset(&sSubParse); return pPrg; } /* ** Return a pointer to a TriggerPrg object containing the sub-program for ** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such ** TriggerPrg object exists, a new object is allocated and populated before |
︙ | ︙ | |||
142537 142538 142539 142540 142541 142542 142543 | int reg, /* Reg array containing OLD.* and NEW.* values */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, p, pTab, orconf); | | | 143019 143020 143021 143022 143023 143024 143025 143026 143027 143028 143029 143030 143031 143032 143033 | int reg, /* Reg array containing OLD.* and NEW.* values */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, p, pTab, orconf); assert( pPrg || pParse->nErr ); /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program ** is a pointer to the sub-vdbe containing the trigger program. */ if( pPrg ){ int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, |
︙ | ︙ | |||
143055 143056 143057 143058 143059 143060 143061 | int regNew = 0; /* Content of the NEW.* table in triggers */ int regOld = 0; /* Content of OLD.* table in triggers */ int regRowSet = 0; /* Rowset of rows to be updated */ int regKey = 0; /* composite PRIMARY KEY value */ memset(&sContext, 0, sizeof(sContext)); db = pParse->db; | > | > | 143537 143538 143539 143540 143541 143542 143543 143544 143545 143546 143547 143548 143549 143550 143551 143552 143553 143554 143555 | int regNew = 0; /* Content of the NEW.* table in triggers */ int regOld = 0; /* Content of OLD.* table in triggers */ int regRowSet = 0; /* Rowset of rows to be updated */ int regKey = 0; /* composite PRIMARY KEY value */ memset(&sContext, 0, sizeof(sContext)); db = pParse->db; assert( db->pParse==pParse ); if( pParse->nErr ){ goto update_cleanup; } assert( db->mallocFailed==0 ); /* Locate the table which we want to update. */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); |
︙ | ︙ | |||
143429 143430 143431 143432 143433 143434 143435 | ** be deleted as a result of REPLACE conflict handling. Any of these ** things might disturb a cursor being used to scan through the table ** or index, causing a single-pass approach to malfunction. */ flags = WHERE_ONEPASS_DESIRED; if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ flags |= WHERE_ONEPASS_MULTIROW; } | | | 143913 143914 143915 143916 143917 143918 143919 143920 143921 143922 143923 143924 143925 143926 143927 | ** be deleted as a result of REPLACE conflict handling. Any of these ** things might disturb a cursor being used to scan through the table ** or index, causing a single-pass approach to malfunction. */ flags = WHERE_ONEPASS_DESIRED; if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ flags |= WHERE_ONEPASS_MULTIROW; } pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur); if( pWInfo==0 ) goto update_cleanup; /* A one-pass strategy that might update more than one row may not ** be used if any column of the index used for the scan is being ** updated. Otherwise, if there is an index on "b", statements like ** the following could create an infinite loop: ** |
︙ | ︙ | |||
143951 143952 143953 143954 143955 143956 143957 | sqlite3ExprListDelete(db, pList); eOnePass = ONEPASS_OFF; }else{ regRec = ++pParse->nMem; regRowid = ++pParse->nMem; /* Start scanning the virtual table */ | | > > | 144435 144436 144437 144438 144439 144440 144441 144442 144443 144444 144445 144446 144447 144448 144449 144450 144451 | sqlite3ExprListDelete(db, pList); eOnePass = ONEPASS_OFF; }else{ regRec = ++pParse->nMem; regRowid = ++pParse->nMem; /* Start scanning the virtual table */ pWInfo = sqlite3WhereBegin( pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0 ); if( pWInfo==0 ) return; /* Populate the argument registers. */ for(i=0; i<pTab->nCol; i++){ assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ); if( aXRef[i]>=0 ){ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); |
︙ | ︙ | |||
145596 145597 145598 145599 145600 145601 145602 | sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } pTab = pCtx->pTab; assert( IsVirtual(pTab) ); | | < | 146082 146083 146084 146085 146086 146087 146088 146089 146090 146091 146092 146093 146094 146095 146096 146097 | sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } pTab = pCtx->pTab; assert( IsVirtual(pTab) ); sqlite3ParseObjectInit(&sParse, db); sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; /* We should never be able to reach this point while loading the ** schema. Nevertheless, defend against that (turn off db->init.busy) ** in case a bug arises. */ assert( db->init.busy==0 ); initBusy = db->init.busy; db->init.busy = 0; sParse.nQueryLoop = 1; |
︙ | ︙ | |||
145652 145653 145654 145655 145656 145657 145658 | } sParse.eParseMode = PARSE_MODE_NORMAL; if( sParse.pVdbe ){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(db, sParse.pNewTable); | | | 146137 146138 146139 146140 146141 146142 146143 146144 146145 146146 146147 146148 146149 146150 146151 | } sParse.eParseMode = PARSE_MODE_NORMAL; if( sParse.pVdbe ){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(db, sParse.pNewTable); sqlite3ParseObjectReset(&sParse); db->init.busy = initBusy; assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } |
︙ | ︙ | |||
146263 146264 146265 146266 146267 146268 146269 | u16 nBtm; /* Size of BTM vector */ u16 nTop; /* Size of TOP vector */ u16 nDistinctCol; /* Index columns used to sort for DISTINCT */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ | | > > | 146748 146749 146750 146751 146752 146753 146754 146755 146756 146757 146758 146759 146760 146761 146762 146763 146764 146765 146766 146767 | u16 nBtm; /* Size of BTM vector */ u16 nTop; /* Size of TOP vector */ u16 nDistinctCol; /* Index columns used to sort for DISTINCT */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */ u32 bOmitOffset : 1; /* True to let virtual table handle offset */ i8 isOrdered; /* True if satisfies ORDER BY */ u16 omitMask; /* Terms that may be omitted */ char *idxStr; /* Index identifier string */ u32 mHandleIn; /* Terms to handle as IN(...) instead of == */ } vtab; } u; u32 wsFlags; /* WHERE_* flags describing the plan */ u16 nLTerm; /* Number of entries in aLTerm[] */ u16 nSkip; /* Number of NULL aLTerm[] entries */ /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) |
︙ | ︙ | |||
146423 146424 146425 146426 146427 146428 146429 146430 146431 146432 146433 146434 146435 146436 | #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ #define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */ #ifdef SQLITE_ENABLE_STAT4 # define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */ #else # define TERM_HIGHTRUTH 0 /* Only used with STAT4 */ #endif /* ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ | > | 146910 146911 146912 146913 146914 146915 146916 146917 146918 146919 146920 146921 146922 146923 146924 | #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ #define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */ #ifdef SQLITE_ENABLE_STAT4 # define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */ #else # define TERM_HIGHTRUTH 0 /* Only used with STAT4 */ #endif #define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */ /* ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ |
︙ | ︙ | |||
146526 146527 146528 146529 146530 146531 146532 | /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. */ struct WhereLoopBuilder { WhereInfo *pWInfo; /* Information about this WHERE */ WhereClause *pWC; /* WHERE clause terms */ | < | 147014 147015 147016 147017 147018 147019 147020 147021 147022 147023 147024 147025 147026 147027 | /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. */ struct WhereLoopBuilder { WhereInfo *pWInfo; /* Information about this WHERE */ WhereClause *pWC; /* WHERE clause terms */ WhereLoop *pNew; /* Template WhereLoop */ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ #ifdef SQLITE_ENABLE_STAT4 UnpackedRecord *pRec; /* Probe for stat4 (if required) */ int nRecValid; /* Number of valid fields currently in pRec */ #endif unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */ |
︙ | ︙ | |||
146594 146595 146596 146597 146598 146599 146600 146601 146602 146603 146604 146605 146606 146607 | */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set of the query */ Expr *pWhere; /* The complete WHERE clause */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ u8 nLevel; /* Number of nested loop */ | > > > | 147081 147082 147083 147084 147085 147086 147087 147088 147089 147090 147091 147092 147093 147094 147095 147096 147097 | */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set of the query */ Expr *pWhere; /* The complete WHERE clause */ #ifndef SQLITE_OMIT_VIRTUALTABLE Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */ #endif int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ u8 nLevel; /* Number of nested loop */ |
︙ | ︙ | |||
146679 146680 146681 146682 146683 146684 146685 146686 146687 146688 146689 146690 146691 146692 | Bitmask notReady /* Which tables are currently available */ ); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); | > | 147169 147170 147171 147172 147173 147174 147175 147176 147177 147178 147179 147180 147181 147182 147183 | Bitmask notReady /* Which tables are currently available */ ); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); |
︙ | ︙ | |||
146749 146750 146751 146752 146753 146754 146755 146756 146757 146758 146759 146760 146761 146762 | #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ #define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ #endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN | > | 147240 147241 147242 147243 147244 147245 147246 147247 147248 147249 147250 147251 147252 147253 147254 | #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ #define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ #define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */ #endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN |
︙ | ︙ | |||
147559 147560 147561 147562 147563 147564 147565 147566 147567 147568 147569 147570 147571 147572 147573 147574 147575 147576 147577 147578 147579 | if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); regBase = r1; }else{ sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); } } if( pTerm->eOperator & WO_IN ){ if( pTerm->pExpr->flags & EP_xIsSelect ){ /* No affinity ever needs to be (or should be) applied to a value ** from the RHS of an "? IN (SELECT ...)" expression. The ** sqlite3FindInIndex() routine has already ensured that the ** affinity of the comparison has been applied to the value. */ if( zAff ) zAff[j] = SQLITE_AFF_BLOB; } }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ Expr *pRight = pTerm->pExpr->pRight; if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } | > > > > | | 148051 148052 148053 148054 148055 148056 148057 148058 148059 148060 148061 148062 148063 148064 148065 148066 148067 148068 148069 148070 148071 148072 148073 148074 148075 148076 148077 148078 148079 148080 148081 148082 148083 | if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); regBase = r1; }else{ sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); } } } for(j=nSkip; j<nEq; j++){ pTerm = pLoop->aLTerm[j]; if( pTerm->eOperator & WO_IN ){ if( pTerm->pExpr->flags & EP_xIsSelect ){ /* No affinity ever needs to be (or should be) applied to a value ** from the RHS of an "? IN (SELECT ...)" expression. The ** sqlite3FindInIndex() routine has already ensured that the ** affinity of the comparison has been applied to the value. */ if( zAff ) zAff[j] = SQLITE_AFF_BLOB; } }else if( (pTerm->eOperator & WO_ISNULL)==0 ){ Expr *pRight = pTerm->pExpr->pRight; if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } if( pParse->nErr==0 ){ assert( pParse->db->mallocFailed==0 ); if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){ zAff[j] = SQLITE_AFF_BLOB; } if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){ zAff[j] = SQLITE_AFF_BLOB; } } |
︙ | ︙ | |||
148263 148264 148265 148266 148267 148268 148269 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ | > > > > > > | | > > > > > > > > > > | 148759 148760 148761 148762 148763 148764 148765 148766 148767 148768 148769 148770 148771 148772 148773 148774 148775 148776 148777 148778 148779 148780 148781 148782 148783 148784 148785 148786 148787 148788 148789 148790 148791 148792 148793 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ int iTab = pParse->nTab++; int iCache = ++pParse->nMem; sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache); }else{ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; } }else{ Expr *pRight = pTerm->pExpr->pRight; codeExprOrVector(pParse, pRight, iTarget, 1); if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET && pLoop->u.vtab.bOmitOffset ){ assert( pTerm->eOperator==WO_AUX ); assert( pWInfo->pLimit!=0 ); assert( pWInfo->pLimit->iOffset>0 ); sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset); VdbeComment((v,"Zero OFFSET counter")); } } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); |
︙ | ︙ | |||
148290 148291 148292 148293 148294 148295 148296 148297 | assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); if( pLoop->wsFlags & WHERE_IN_ABLE ){ iIn = pLevel->u.in.nIn; }else{ iIn = 0; } for(j=nConstraint-1; j>=0; j--){ pTerm = pLoop->aLTerm[j]; | > | > > > > > > > < | < | 148802 148803 148804 148805 148806 148807 148808 148809 148810 148811 148812 148813 148814 148815 148816 148817 148818 148819 148820 148821 148822 148823 148824 148825 148826 148827 148828 | assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); if( pLoop->wsFlags & WHERE_IN_ABLE ){ iIn = pLevel->u.in.nIn; }else{ iIn = 0; } for(j=nConstraint-1; j>=0; j--){ int bIn; /* True to generate byte code to loop over RHS IN values */ pTerm = pLoop->aLTerm[j]; if( (pTerm->eOperator & WO_IN)!=0 && (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0 ){ bIn = 1; }else{ bIn = 0; } if( bIn ) iIn--; if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ disableTerm(pLevel, pTerm); }else if( bIn && sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1 ){ Expr *pCompare; /* The comparison operator */ Expr *pRight; /* RHS of the comparison */ VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ /* Reload the constraint value into reg[iReg+j+2]. The same value ** was loaded into the same register prior to the OP_VFilter, but ** the xFilter implementation might have changed the datatype or |
︙ | ︙ | |||
149026 149027 149028 149029 149030 149031 149032 | sqlite3VdbeSetP4KeyInfo(pParse, pPk); } regRowid = ++pParse->nMem; } iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y | | > > > > > > > | > > | 149544 149545 149546 149547 149548 149549 149550 149551 149552 149553 149554 149555 149556 149557 149558 149559 149560 149561 149562 149563 149564 149565 149566 149567 149568 149569 149570 149571 149572 149573 149574 149575 149576 149577 149578 149579 149580 149581 149582 149583 149584 149585 149586 149587 | sqlite3VdbeSetP4KeyInfo(pParse, pPk); } regRowid = ++pParse->nMem; } iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y ** Then for every term xN, evaluate as the subexpression: xN AND y ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite3WhereBegin() below. ** ** Actually, each subexpression is converted to "xN AND w" where w is ** the "interesting" terms of z - terms that did not originate in the ** ON or USING clause of a LEFT JOIN, and terms that are usable as ** indices. ** ** This optimization also only applies if the (x1 OR x2 OR ...) term ** is not contained in the ON clause of a LEFT JOIN. ** See ticket http://www.sqlite.org/src/info/f2369304e4 ** ** 2022-02-04: Do not push down slices of a row-value comparison. ** In other words, "w" or "y" may not be a slice of a vector. Otherwise, ** the initialization of the right-hand operand of the vector comparison ** might not occur, or might occur only in an OR branch that is not ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1. */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); testcase( pWC->a[iTerm].wtFlags & TERM_SLICE ); if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){ continue; } if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); } if( pAndExpr ){ /* The extra 0x10000 bit on the opcode is masked off and does not |
︙ | ︙ | |||
149089 149090 149091 149092 149093 149094 149095 | if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1)); WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); | | | | 149616 149617 149618 149619 149620 149621 149622 149623 149624 149625 149626 149627 149628 149629 149630 149631 149632 | if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1)); WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0, WHERE_OR_SUBCLAUSE, iCovCur); assert( pSubWInfo || pParse->nErr ); if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = sqlite3WhereExplainOneScan( pParse, pOrTab, &pSubWInfo->a[0], 0 ); sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); |
︙ | ︙ | |||
149829 149830 149831 149832 149833 149834 149835 | sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); | | | 150356 150357 150358 150359 150360 150361 150362 150363 150364 150365 150366 150367 150368 150369 150370 | sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction!=0 ){ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ *peOp2 = i; *ppRight = pList->a[1].pExpr; *ppLeft = pCol; return 1; |
︙ | ︙ | |||
150786 150787 150788 150789 150790 150791 150792 | /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create ** new terms for each component comparison - "a = ?" and "b = ?". The ** new terms completely replace the original vector comparison, which is ** no longer used. ** ** This is only required if at least one side of the comparison operation | | > > > | | 151313 151314 151315 151316 151317 151318 151319 151320 151321 151322 151323 151324 151325 151326 151327 151328 151329 151330 151331 151332 151333 151334 151335 151336 151337 151338 151339 151340 151341 151342 151343 151344 151345 151346 151347 | /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create ** new terms for each component comparison - "a = ?" and "b = ?". The ** new terms completely replace the original vector comparison, which is ** no longer used. ** ** This is only required if at least one side of the comparison operation ** is not a sub-select. ** ** tag-20220128a */ if( (pExpr->op==TK_EQ || pExpr->op==TK_IS) && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 && sqlite3ExprVectorSize(pExpr->pRight)==nLeft && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 || (pExpr->pRight->flags & EP_xIsSelect)==0) && pWC->op==TK_AND ){ int i; for(i=0; i<nLeft; i++){ int idxNew; Expr *pNew; Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft); Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft); pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); transferJoinMarkings(pNew, pExpr); idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE); exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ pTerm->eOperator = 0; } |
︙ | ︙ | |||
150928 150929 150930 150931 150932 150933 150934 150935 150936 150937 150938 150939 150940 150941 | if( pE2->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ sqlite3WhereSplit(pWC, pE2->pLeft, op); sqlite3WhereSplit(pWC, pE2->pRight, op); } } /* ** Initialize a preallocated WhereClause structure. */ SQLITE_PRIVATE void sqlite3WhereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ WhereInfo *pWInfo /* The WHERE processing context */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151458 151459 151460 151461 151462 151463 151464 151465 151466 151467 151468 151469 151470 151471 151472 151473 151474 151475 151476 151477 151478 151479 151480 151481 151482 151483 151484 151485 151486 151487 151488 151489 151490 151491 151492 151493 151494 151495 151496 151497 151498 151499 151500 151501 151502 151503 151504 151505 151506 151507 151508 151509 151510 151511 151512 151513 151514 151515 151516 151517 151518 151519 151520 151521 151522 151523 151524 151525 151526 151527 151528 151529 151530 151531 151532 151533 151534 151535 151536 151537 151538 151539 151540 151541 151542 151543 151544 151545 151546 151547 151548 151549 151550 151551 151552 151553 151554 151555 151556 151557 151558 151559 151560 151561 151562 151563 151564 151565 151566 151567 151568 151569 151570 151571 151572 151573 151574 151575 151576 151577 151578 | if( pE2->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ sqlite3WhereSplit(pWC, pE2->pLeft, op); sqlite3WhereSplit(pWC, pE2->pRight, op); } } /* ** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or ** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the ** where-clause passed as the first argument. The value for the term ** is found in register iReg. ** ** In the common case where the value is a simple integer ** (example: "LIMIT 5 OFFSET 10") then the expression codes as a ** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value(). ** If not, then it codes as a TK_REGISTER expression. */ void whereAddLimitExpr( WhereClause *pWC, /* Add the constraint to this WHERE clause */ int iReg, /* Register that will hold value of the limit/offset */ Expr *pExpr, /* Expression that defines the limit/offset */ int iCsr, /* Cursor to which the constraint applies */ int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */ ){ Parse *pParse = pWC->pWInfo->pParse; sqlite3 *db = pParse->db; Expr *pNew; int iVal = 0; if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){ Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); if( pVal==0 ) return; ExprSetProperty(pVal, EP_IntValue); pVal->u.iValue = iVal; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); }else{ Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); if( pVal==0 ) return; pVal->iTable = iReg; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); } if( pNew ){ WhereTerm *pTerm; int idx; idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL); pTerm = &pWC->a[idx]; pTerm->leftCursor = iCsr; pTerm->eOperator = WO_AUX; pTerm->eMatchOp = eMatchOp; } } /* ** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the ** SELECT statement passed as the second argument. These terms are only ** added if: ** ** 1. The SELECT statement has a LIMIT clause, and ** 2. The SELECT statement is not an aggregate or DISTINCT query, and ** 3. The SELECT statement has exactly one object in its from clause, and ** that object is a virtual table, and ** 4. There are no terms in the WHERE clause that will not be passed ** to the virtual table xBestIndex method. ** 5. The ORDER BY clause, if any, will be made available to the xBestIndex ** method. ** ** LIMIT and OFFSET terms are ignored by most of the planner code. They ** exist only so that they may be passed to the xBestIndex method of the ** single virtual table in the FROM clause of the SELECT. */ SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause *pWC, Select *p){ assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) ); if( (p && p->pLimit) /* 1 */ && (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */ && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */ ){ ExprList *pOrderBy = p->pOrderBy; int iCsr = p->pSrc->a[0].iCursor; int ii; /* Check condition (4). Return early if it is not met. */ for(ii=0; ii<pWC->nTerm; ii++){ if( pWC->a[ii].wtFlags & TERM_CODED ){ /* This term is a vector operation that has been decomposed into ** other, subsequent terms. It can be ignored. See tag-20220128a */ assert( pWC->a[ii].wtFlags & TERM_VIRTUAL ); assert( pWC->a[ii].eOperator==0 ); continue; } if( pWC->a[ii].leftCursor!=iCsr ) return; } /* Check condition (5). Return early if it is not met. */ if( pOrderBy ){ for(ii=0; ii<pOrderBy->nExpr; ii++){ Expr *pExpr = pOrderBy->a[ii].pExpr; if( pExpr->op!=TK_COLUMN ) return; if( pExpr->iTable!=iCsr ) return; if( pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_BIGNULL ) return; } } /* All conditions are met. Add the terms to the where-clause object. */ assert( p->pLimit->op==TK_LIMIT ); whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); if( p->iOffset>0 ){ whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); } } } /* ** Initialize a preallocated WhereClause structure. */ SQLITE_PRIVATE void sqlite3WhereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ WhereInfo *pWInfo /* The WHERE processing context */ |
︙ | ︙ | |||
150964 150965 150966 150967 150968 150969 150970 150971 150972 150973 150974 150975 150976 150977 | int i; /* Verify that every term past pWC->nBase is virtual */ for(i=pWC->nBase; i<pWC->nTerm; i++){ assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); } #endif while(1){ if( a->wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, a->pExpr); } if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){ if( a->wtFlags & TERM_ORINFO ){ assert( (a->wtFlags & TERM_ANDINFO)==0 ); whereOrInfoDelete(db, a->u.pOrInfo); | > | 151601 151602 151603 151604 151605 151606 151607 151608 151609 151610 151611 151612 151613 151614 151615 | int i; /* Verify that every term past pWC->nBase is virtual */ for(i=pWC->nBase; i<pWC->nTerm; i++){ assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); } #endif while(1){ assert( a->eMatchOp==0 || a->eOperator==WO_AUX ); if( a->wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, a->pExpr); } if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){ if( a->wtFlags & TERM_ORINFO ){ assert( (a->wtFlags & TERM_ANDINFO)==0 ); whereOrInfoDelete(db, a->u.pOrInfo); |
︙ | ︙ | |||
151121 151122 151123 151124 151125 151126 151127 151128 151129 151130 151131 151132 151133 151134 | } pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; assert( ExprUseYTab(pColRef) ); pColRef->y.pTab = pTab; pRhs = sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); if( pItem->fg.jointype & JT_LEFT ){ sqlite3SetJoinExpr(pTerm, pItem->iCursor); } whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); | > | 151759 151760 151761 151762 151763 151764 151765 151766 151767 151768 151769 151770 151771 151772 151773 | } pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; assert( ExprUseYTab(pColRef) ); pColRef->y.pTab = pTab; pItem->colUsed |= sqlite3ExprColUsed(pColRef); pRhs = sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); if( pItem->fg.jointype & JT_LEFT ){ sqlite3SetJoinExpr(pTerm, pItem->iCursor); } whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); |
︙ | ︙ | |||
151165 151166 151167 151168 151169 151170 151171 | ** ** This object is not an API and can be changed from one release to the ** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() ** agree on the structure, all will be well. */ typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { | | | > > > > > > | 151804 151805 151806 151807 151808 151809 151810 151811 151812 151813 151814 151815 151816 151817 151818 151819 151820 151821 151822 151823 151824 151825 | ** ** This object is not an API and can be changed from one release to the ** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() ** agree on the structure, all will be well. */ typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { WhereClause *pWC; /* The Where clause being analyzed */ Parse *pParse; /* The parsing context */ int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ u32 mIn; /* Mask of terms that are <col> IN (...) */ u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */ sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST ** because extra space is allocated to hold up ** to nTerm such values */ }; /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Return the estimated number of output rows from a WHERE clause |
︙ | ︙ | |||
152230 152231 152232 152233 152234 152235 152236 | } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure | | | < > > > | 152875 152876 152877 152878 152879 152880 152881 152882 152883 152884 152885 152886 152887 152888 152889 152890 152891 152892 152893 152894 152895 152896 152897 152898 152899 152900 152901 152902 152903 152904 152905 152906 152907 152908 152909 152910 152911 | } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to freeIndexInfo(). */ static sqlite3_index_info *allocateIndexInfo( WhereInfo *pWInfo, /* The WHERE clause */ WhereClause *pWC, /* The WHERE clause being analyzed */ Bitmask mUnusable, /* Ignore terms with these prereqs */ SrcItem *pSrc, /* The FROM clause term that is the vtab */ u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; int nTerm; Parse *pParse = pWInfo->pParse; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; struct HiddenIndexInfo *pHidden; WhereTerm *pTerm; int nOrderBy; sqlite3_index_info *pIdxInfo; u16 mNoOmit = 0; const Table *pTab; int eDistinct = 0; ExprList *pOrderBy = pWInfo->pOrderBy; assert( pSrc!=0 ); pTab = pSrc->pTab; assert( pTab!=0 ); assert( IsVirtual(pTab) ); /* Find all WHERE clause constraints referring to this virtual table. |
︙ | ︙ | |||
152272 152273 152274 152275 152276 152277 152278 152279 152280 152281 152282 152283 152284 152285 | assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_IS ); testcase( pTerm->eOperator & WO_ALL ); if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); assert( pTerm->u.x.leftColumn>=XN_ROWID ); assert( pTerm->u.x.leftColumn<pTab->nCol ); /* tag-20191211-002: WHERE-clause constraints are not useful to the ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the ** equivalent restriction for ordinary tables. */ | > | 152919 152920 152921 152922 152923 152924 152925 152926 152927 152928 152929 152930 152931 152932 152933 | assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_IS ); testcase( pTerm->eOperator & WO_ALL ); if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); assert( pTerm->u.x.leftColumn>=XN_ROWID ); assert( pTerm->u.x.leftColumn<pTab->nCol ); /* tag-20191211-002: WHERE-clause constraints are not useful to the ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the ** equivalent restriction for ordinary tables. */ |
︙ | ︙ | |||
152333 152334 152335 152336 152337 152338 152339 | if( zColl==0 ) zColl = sqlite3StrBINARY; if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; } /* No matches cause a break out of the loop */ break; } | | > > > | > | > > | > > > | 152981 152982 152983 152984 152985 152986 152987 152988 152989 152990 152991 152992 152993 152994 152995 152996 152997 152998 152999 153000 153001 153002 153003 153004 153005 153006 153007 153008 153009 153010 153011 153012 153013 153014 153015 153016 153017 153018 153019 153020 153021 153022 153023 153024 153025 153026 153027 153028 153029 153030 153031 153032 153033 | if( zColl==0 ) zColl = sqlite3StrBINARY; if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; } /* No matches cause a break out of the loop */ break; } if( i==n ){ nOrderBy = n; if( (pWInfo->wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY)) ){ eDistinct = 1 + ((pWInfo->wctrlFlags & WHERE_DISTINCTBY)!=0); } } } /* Allocate the sqlite3_index_info structure */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) + sizeof(sqlite3_value*)*nTerm ); if( pIdxInfo==0 ){ sqlite3ErrorMsg(pParse, "out of memory"); return 0; } pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; pIdxInfo->aConstraint = pIdxCons; pIdxInfo->aOrderBy = pIdxOrderBy; pIdxInfo->aConstraintUsage = pUsage; pHidden->pWC = pWC; pHidden->pParse = pParse; pHidden->eDistinct = eDistinct; pHidden->mIn = 0; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ u16 op; if( (pTerm->wtFlags & TERM_OK)==0 ) continue; pIdxCons[j].iColumn = pTerm->u.x.leftColumn; pIdxCons[j].iTermOffset = i; op = pTerm->eOperator & WO_ALL; if( op==WO_IN ){ pHidden->mIn |= SMASKBIT32(j); op = WO_EQ; } if( op==WO_AUX ){ pIdxCons[j].op = pTerm->eMatchOp; }else if( op & (WO_ISNULL|WO_IS) ){ if( op==WO_ISNULL ){ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; }else{ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; |
︙ | ︙ | |||
152412 152413 152414 152415 152416 152417 152418 152419 152420 152421 152422 152423 152424 152425 | j++; } pIdxInfo->nOrderBy = j; *pmNoOmit = mNoOmit; return pIdxInfo; } /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** | > > > > > > > > > > > > > > > > > > | 153069 153070 153071 153072 153073 153074 153075 153076 153077 153078 153079 153080 153081 153082 153083 153084 153085 153086 153087 153088 153089 153090 153091 153092 153093 153094 153095 153096 153097 153098 153099 153100 | j++; } pIdxInfo->nOrderBy = j; *pmNoOmit = mNoOmit; return pIdxInfo; } /* ** Free an sqlite3_index_info structure allocated by allocateIndexInfo() ** and possibly modified by xBestIndex methods. */ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden; int i; assert( pIdxInfo!=0 ); pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; assert( pHidden->pParse!=0 ); assert( pHidden->pParse->db==db ); for(i=0; i<pIdxInfo->nConstraint; i++){ sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */ pHidden->aRhs[i] = 0; } sqlite3DbFree(db, pIdxInfo); } /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** |
︙ | ︙ | |||
152434 152435 152436 152437 152438 152439 152440 152441 152442 152443 152444 152445 152446 152447 152448 | ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; whereTraceIndexInfoInputs(p); rc = pVtab->pModule->xBestIndex(pVtab, p); whereTraceIndexInfoOutputs(p); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); | > > | 153109 153110 153111 153112 153113 153114 153115 153116 153117 153118 153119 153120 153121 153122 153123 153124 153125 | ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; whereTraceIndexInfoInputs(p); pParse->db->nSchemaLock++; rc = pVtab->pModule->xBestIndex(pVtab, p); pParse->db->nSchemaLock--; whereTraceIndexInfoOutputs(p); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); |
︙ | ︙ | |||
154564 154565 154566 154567 154568 154569 154570 154571 154572 154573 154574 154575 154576 154577 | pBuilder->pRec = 0; #endif } return rc; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Argument pIdxInfo is already populated with all constraints that may ** be used by the virtual table identified by pBuilder->pNew->iTab. This ** function marks a subset of those constraints usable, invokes the ** xBestIndex method and adds the returned plan to pBuilder. ** | > > > > > > > > > | 155241 155242 155243 155244 155245 155246 155247 155248 155249 155250 155251 155252 155253 155254 155255 155256 155257 155258 155259 155260 155261 155262 155263 | pBuilder->pRec = 0; #endif } return rc; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Return true if pTerm is a virtual table LIMIT or OFFSET term. */ static int isLimitTerm(WhereTerm *pTerm){ assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 ); return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; } /* ** Argument pIdxInfo is already populated with all constraints that may ** be used by the virtual table identified by pBuilder->pNew->iTab. This ** function marks a subset of those constraints usable, invokes the ** xBestIndex method and adds the returned plan to pBuilder. ** |
︙ | ︙ | |||
154592 154593 154594 154595 154596 154597 154598 | static int whereLoopAddVirtualOne( WhereLoopBuilder *pBuilder, Bitmask mPrereq, /* Mask of tables that must be used. */ Bitmask mUsable, /* Mask of usable tables */ u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ u16 mNoOmit, /* Do not omit these constraints */ | | > > | 155278 155279 155280 155281 155282 155283 155284 155285 155286 155287 155288 155289 155290 155291 155292 155293 155294 155295 155296 | static int whereLoopAddVirtualOne( WhereLoopBuilder *pBuilder, Bitmask mPrereq, /* Mask of tables that must be used. */ Bitmask mUsable, /* Mask of usable tables */ u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ u16 mNoOmit, /* Do not omit these constraints */ int *pbIn, /* OUT: True if plan uses an IN(...) op */ int *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */ ){ WhereClause *pWC = pBuilder->pWC; HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; int i; int mxTerm; int rc = SQLITE_OK; WhereLoop *pNew = pBuilder->pNew; Parse *pParse = pBuilder->pWInfo->pParse; |
︙ | ︙ | |||
154617 154618 154619 154620 154621 154622 154623 154624 154625 154626 154627 154628 154629 154630 154631 154632 154633 154634 154635 154636 154637 154638 154639 154640 154641 154642 154643 154644 154645 154646 154647 154648 154649 154650 154651 154652 154653 154654 154655 | ** arguments mUsable and mExclude. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<nConstraint; i++, pIdxCons++){ WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset]; pIdxCons->usable = 0; if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight && (pTerm->eOperator & mExclude)==0 ){ pIdxCons->usable = 1; } } /* Initialize the output fields of the sqlite3_index_info structure */ memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); assert( pIdxInfo->needToFreeIdxStr==0 ); pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); if( rc ){ if( rc==SQLITE_CONSTRAINT ){ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means ** that the particular combination of parameters provided is unusable. ** Make no entries in the loop table. */ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); return SQLITE_OK; } return rc; } mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); | > > | | | 155305 155306 155307 155308 155309 155310 155311 155312 155313 155314 155315 155316 155317 155318 155319 155320 155321 155322 155323 155324 155325 155326 155327 155328 155329 155330 155331 155332 155333 155334 155335 155336 155337 155338 155339 155340 155341 155342 155343 155344 155345 155346 155347 155348 155349 155350 155351 155352 155353 155354 | ** arguments mUsable and mExclude. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<nConstraint; i++, pIdxCons++){ WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset]; pIdxCons->usable = 0; if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight && (pTerm->eOperator & mExclude)==0 && (pbRetryLimit || !isLimitTerm(pTerm)) ){ pIdxCons->usable = 1; } } /* Initialize the output fields of the sqlite3_index_info structure */ memset(pUsage, 0, sizeof(pUsage[0])*nConstraint); assert( pIdxInfo->needToFreeIdxStr==0 ); pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; pHidden->mHandleIn = 0; /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); if( rc ){ if( rc==SQLITE_CONSTRAINT ){ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means ** that the particular combination of parameters provided is unusable. ** Make no entries in the loop table. */ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); return SQLITE_OK; } return rc; } mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint ); memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab)); pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<nConstraint; i++, pIdxCons++){ int iTerm; if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){ WhereTerm *pTerm; int j = pIdxCons->iTermOffset; if( iTerm>=nConstraint |
︙ | ︙ | |||
154684 154685 154686 154687 154688 154689 154690 | if( pUsage[i].omit ){ if( i<16 && ((1<<i)&mNoOmit)==0 ){ testcase( i!=iTerm ); pNew->u.vtab.omitMask |= 1<<iTerm; }else{ testcase( i!=iTerm ); } | > > | > > > | > > > > > > > > > > > > > > > | 155374 155375 155376 155377 155378 155379 155380 155381 155382 155383 155384 155385 155386 155387 155388 155389 155390 155391 155392 155393 155394 155395 155396 155397 155398 155399 155400 155401 155402 155403 155404 155405 155406 155407 155408 155409 155410 155411 155412 155413 155414 155415 155416 155417 155418 | if( pUsage[i].omit ){ if( i<16 && ((1<<i)&mNoOmit)==0 ){ testcase( i!=iTerm ); pNew->u.vtab.omitMask |= 1<<iTerm; }else{ testcase( i!=iTerm ); } if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){ pNew->u.vtab.bOmitOffset = 1; } } if( SMASKBIT32(i) & pHidden->mHandleIn ){ pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm); }else if( (pTerm->eOperator & WO_IN)!=0 ){ /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } if( isLimitTerm(pTerm) && *pbIn ){ /* If there is an IN(...) term handled as an == (separate call to ** xFilter for each value on the RHS of the IN) and a LIMIT or ** OFFSET term handled as well, the plan is unusable. Set output ** variable *pbRetryLimit to true to tell the caller to retry with ** LIMIT and OFFSET disabled. */ if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); pIdxInfo->idxStr = 0; pIdxInfo->needToFreeIdxStr = 0; } *pbRetryLimit = 1; return SQLITE_OK; } } } pNew->nLTerm = mxTerm+1; for(i=0; i<=mxTerm; i++){ if( pNew->aLTerm[i]==0 ){ /* The non-zero argvIdx values must be contiguous. Raise an |
︙ | ︙ | |||
154767 154768 154769 154770 154771 154772 154773 154774 154775 154776 154777 154778 154779 154780 | if( pX->pLeft ){ pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX); } zRet = (pC ? pC->zName : sqlite3StrBINARY); } return zRet; } /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. ** ** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and ** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 155477 155478 155479 155480 155481 155482 155483 155484 155485 155486 155487 155488 155489 155490 155491 155492 155493 155494 155495 155496 155497 155498 155499 155500 155501 155502 155503 155504 155505 155506 155507 155508 155509 155510 155511 155512 155513 155514 155515 155516 155517 155518 155519 155520 155521 155522 155523 155524 155525 155526 155527 155528 155529 155530 155531 155532 155533 155534 155535 155536 155537 155538 155539 155540 155541 155542 155543 155544 155545 155546 155547 155548 155549 155550 155551 155552 155553 155554 155555 155556 155557 | if( pX->pLeft ){ pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX); } zRet = (pC ? pC->zName : sqlite3StrBINARY); } return zRet; } /* ** Return true if constraint iCons is really an IN(...) constraint, or ** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0) ** or clear (if bHandle==0) the flag to handle it using an iterator. */ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info *pIdxInfo, int iCons, int bHandle){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; u32 m = SMASKBIT32(iCons); if( m & pHidden->mIn ){ if( bHandle==0 ){ pHidden->mHandleIn &= ~m; }else if( bHandle>0 ){ pHidden->mHandleIn |= m; } return 1; } return 0; } /* ** This interface is callable from within the xBestIndex callback only. ** ** If possible, set (*ppVal) to point to an object containing the value ** on the right-hand-side of constraint iCons. */ SQLITE_API int sqlite3_vtab_rhs_value( sqlite3_index_info *pIdxInfo, /* Copy of first argument to xBestIndex */ int iCons, /* Constraint for which RHS is wanted */ sqlite3_value **ppVal /* Write value extracted here */ ){ HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1]; sqlite3_value *pVal = 0; int rc = SQLITE_OK; if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ rc = SQLITE_MISUSE; /* EV: R-30545-25046 */ }else{ if( pH->aRhs[iCons]==0 ){ WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset]; rc = sqlite3ValueFromExpr( pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db), SQLITE_AFF_BLOB, &pH->aRhs[iCons] ); testcase( rc!=SQLITE_OK ); } pVal = pH->aRhs[iCons]; } *ppVal = pVal; if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-19933-32160 */ rc = SQLITE_NOTFOUND; /* IMP: R-36424-56542 */ } return rc; } /* ** Return true if ORDER BY clause may be handled as DISTINCT. */ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; assert( pHidden->eDistinct==0 || pHidden->eDistinct==1 || pHidden->eDistinct==2 ); return pHidden->eDistinct; } /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. ** ** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and ** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause |
︙ | ︙ | |||
154809 154810 154811 154812 154813 154814 154815 154816 154817 154818 154819 154820 154821 154822 154823 | SrcItem *pSrc; /* The FROM clause term to search */ sqlite3_index_info *p; /* Object to pass to xBestIndex() */ int nConstraint; /* Number of constraints in p */ int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ u16 mNoOmit; assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; pWC = pBuilder->pWC; pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); | > | < | | > > > > > > > > | | 155586 155587 155588 155589 155590 155591 155592 155593 155594 155595 155596 155597 155598 155599 155600 155601 155602 155603 155604 155605 155606 155607 155608 155609 155610 155611 155612 155613 155614 155615 155616 155617 155618 155619 155620 155621 155622 155623 155624 155625 155626 155627 155628 155629 155630 155631 155632 155633 155634 155635 155636 155637 155638 155639 155640 155641 155642 155643 155644 155645 155646 155647 155648 155649 155650 | SrcItem *pSrc; /* The FROM clause term to search */ sqlite3_index_info *p; /* Object to pass to xBestIndex() */ int nConstraint; /* Number of constraints in p */ int bIn; /* True if plan uses IN(...) operator */ WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ u16 mNoOmit; int bRetry = 0; /* True to retry with LIMIT/OFFSET disabled */ assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; pWC = pBuilder->pWC; pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; pNew->nLTerm = 0; pNew->u.vtab.needFree = 0; nConstraint = p->nConstraint; if( whereLoopResize(pParse->db, pNew, nConstraint) ){ freeIndexInfo(pParse->db, p); return SQLITE_NOMEM_BKPT; } /* First call xBestIndex() with all constraints usable. */ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); WHERETRACE(0x40, (" VirtualOne: all usable\n")); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry ); if( bRetry ){ assert( rc==SQLITE_OK ); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0 ); } /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0) ** and does not use an IN(...) operator, then there is no point in making ** any further calls to xBestIndex() since they will all return the same ** result (if the xBestIndex() implementation is sane). */ if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){ int seenZero = 0; /* True if a plan with no prereqs seen */ int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ Bitmask mPrev = 0; Bitmask mBestNoIn = 0; /* If the plan produced by the earlier call uses an IN(...) term, call ** xBestIndex again, this time with IN(...) terms disabled. */ if( bIn ){ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ seenZero = 1; seenZeroNoIN = 1; } } |
︙ | ︙ | |||
154878 154879 154880 154881 154882 154883 154884 | } mPrev = mNext; if( mNext==ALLBITS ) break; if( mNext==mBest || mNext==mBestNoIn ) continue; WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); rc = whereLoopAddVirtualOne( | | | | | | 155663 155664 155665 155666 155667 155668 155669 155670 155671 155672 155673 155674 155675 155676 155677 155678 155679 155680 155681 155682 155683 155684 155685 155686 155687 155688 155689 155690 155691 155692 155693 155694 155695 155696 155697 155698 155699 155700 155701 155702 155703 155704 155705 | } mPrev = mNext; if( mNext==ALLBITS ) break; if( mNext==mBest || mNext==mBestNoIn ) continue; WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn, 0); if( pNew->prereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; } } /* If the calls to xBestIndex() in the above loop did not find a plan ** that requires no source tables at all (i.e. one guaranteed to be ** usable), make a call here with all source tables disabled */ if( rc==SQLITE_OK && seenZero==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled\n")); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0); if( bIn==0 ) seenZeroNoIN = 1; } /* If the calls to xBestIndex() have so far failed to find a plan ** that requires no source tables at all and does not use an IN(...) ** operator, make a final call to obtain one here. */ if( rc==SQLITE_OK && seenZeroNoIN==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); rc = whereLoopAddVirtualOne( pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0); } } if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); freeIndexInfo(pParse->db, p); WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Add WhereLoop entries to handle OR terms. This works for either |
︙ | ︙ | |||
154950 154951 154952 154953 154954 154955 154956 | WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int once = 1; int i, j; sSubBuild = *pBuilder; | < | 155735 155736 155737 155738 155739 155740 155741 155742 155743 155744 155745 155746 155747 155748 | WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int once = 1; int i, j; sSubBuild = *pBuilder; sSubBuild.pOrSet = &sCur; WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ if( (pOrTerm->eOperator & WO_AND)!=0 ){ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; }else if( pOrTerm->leftCursor==iCur ){ |
︙ | ︙ | |||
156308 156309 156310 156311 156312 156313 156314 156315 156316 156317 156318 156319 156320 156321 | */ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ WhereInfo *pWInfo; /* Will become the return value of this function */ | > | 157092 157093 157094 157095 157096 157097 157098 157099 157100 157101 157102 157103 157104 157105 157106 | */ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ Select *pLimit, /* Use this LIMIT/OFFSET clause, if any */ u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ WhereInfo *pWInfo; /* Will become the return value of this function */ |
︙ | ︙ | |||
156342 156343 156344 156345 156346 156347 156348 | /* Variable initialization */ db = pParse->db; memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; | < | 157127 157128 157129 157130 157131 157132 157133 157134 157135 157136 157137 157138 157139 157140 | /* Variable initialization */ db = pParse->db; memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); if( pTabList->nSrc>BMS ){ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); |
︙ | ︙ | |||
156385 156386 156387 156388 156389 156390 156391 156392 156393 156394 156395 156396 156397 156398 | pWInfo->pResultSet = pResultSet; pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; pWInfo->nLevel = nTabList; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; memset(&pWInfo->nOBSat, 0, offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; pMaskSet->n = 0; pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be | > > > | 157169 157170 157171 157172 157173 157174 157175 157176 157177 157178 157179 157180 157181 157182 157183 157184 157185 | pWInfo->pResultSet = pResultSet; pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; pWInfo->nLevel = nTabList; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; #ifndef SQLITE_OMIT_VIRTUALTABLE pWInfo->pLimit = pLimit; #endif memset(&pWInfo->nOBSat, 0, offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; pMaskSet->n = 0; pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be |
︙ | ︙ | |||
156453 156454 156455 156456 156457 156458 156459 156460 156461 156462 156463 156464 156465 156466 | } } #endif } /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( db->mallocFailed ) goto whereBeginError; /* Special case: WHERE terms that do not refer to any tables in the join ** (constant expressions). Evaluate each such term, and jump over all the ** generated code if the result is not true. ** ** Do not do this if the expression contains non-deterministic functions | > | 157240 157241 157242 157243 157244 157245 157246 157247 157248 157249 157250 157251 157252 157253 157254 | } } #endif } /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); sqlite3WhereAddLimit(&pWInfo->sWC, pLimit); if( db->mallocFailed ) goto whereBeginError; /* Special case: WHERE terms that do not refer to any tables in the join ** (constant expressions). Evaluate each such term, and jump over all the ** generated code if the result is not true. ** ** Do not do this if the expression contains non-deterministic functions |
︙ | ︙ | |||
156552 156553 156554 156555 156556 156557 156558 | wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } } if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ pWInfo->revMask = ALLBITS; } | | > | 157340 157341 157342 157343 157344 157345 157346 157347 157348 157349 157350 157351 157352 157353 157354 157355 157356 157357 | wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } } if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ pWInfo->revMask = ALLBITS; } if( pParse->nErr ){ goto whereBeginError; } assert( db->mallocFailed==0 ); #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace ){ sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); } switch( pWInfo->eDistinct ){ |
︙ | ︙ | |||
156698 156699 156700 156701 156702 156703 156704 156705 156706 156707 156708 156709 156710 156711 | sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0 ){ /* If we know that only a prefix of the record will be used, ** it is advantageous to reduce the "column count" field in ** the P4 operand of the OP_OpenRead/Write opcode. */ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} | > | 157487 157488 157489 157490 157491 157492 157493 157494 157495 157496 157497 157498 157499 157500 157501 | sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0 && (pLoop->wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))==0 ){ /* If we know that only a prefix of the record will be used, ** it is advantageous to reduce the "column count" field in ** the P4 operand of the OP_OpenRead/Write opcode. */ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} |
︙ | ︙ | |||
158262 158263 158264 158265 158266 158267 158268 | /* Defer deleting the temporary table pTab because if an error occurred, ** there could still be references to that table embedded in the ** result-set or ORDER BY clause of the SELECT statement p. */ sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab); } | < | < < < < | 159052 159053 159054 159055 159056 159057 159058 159059 159060 159061 159062 159063 159064 159065 159066 | /* Defer deleting the temporary table pTab because if an error occurred, ** there could still be references to that table embedded in the ** result-set or ORDER BY clause of the SELECT statement p. */ sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab); } assert( rc==SQLITE_OK || pParse->nErr!=0 ); return rc; } /* ** Unlink the Window object from the Select to which it is attached, ** if it is attached. */ |
︙ | ︙ | |||
193953 193954 193955 193956 193957 193958 193959 | pNode = jsonLookup(&x, zPath, &bApnd, ctx); if( x.oom ){ sqlite3_result_error_nomem(ctx); goto jsonSetDone; }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ | | | | 194738 194739 194740 194741 194742 194743 194744 194745 194746 194747 194748 194749 194750 194751 194752 194753 | pNode = jsonLookup(&x, zPath, &bApnd, ctx); if( x.oom ){ sqlite3_result_error_nomem(ctx); goto jsonSetDone; }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ testcase( pNode->eU!=0 && pNode->eU!=1 ); assert( pNode->eU!=3 && pNode->eU!=5 ); VVA( pNode->eU = 4 ); pNode->jnFlags |= (u8)JNODE_REPLACE; pNode->u.iReplace = i + 1; } } if( x.aNode[0].jnFlags & JNODE_REPLACE ){ assert( x.aNode[0].eU==4 ); |
︙ | ︙ | |||
194735 194736 194737 194738 194739 194740 194741 | static const struct { const char *zName; sqlite3_module *pModule; } aMod[] = { { "json_each", &jsonEachModule }, { "json_tree", &jsonTreeModule }, }; | | | 195520 195521 195522 195523 195524 195525 195526 195527 195528 195529 195530 195531 195532 195533 195534 | static const struct { const char *zName; sqlite3_module *pModule; } aMod[] = { { "json_each", &jsonEachModule }, { "json_tree", &jsonTreeModule }, }; unsigned int i; for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); } return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */ |
︙ | ︙ | |||
233332 233333 233334 233335 233336 233337 233338 | 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); | | | 234117 234118 234119 234120 234121 234122 234123 234124 234125 234126 234127 234128 234129 234130 234131 | 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: 2022-01-25 16:28:57 6e4154d414afe2562b488149b10c175d1f15bd1d5060ee479d5ae9386a2e277e", -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){ |
︙ | ︙ |
Changes to extsrc/sqlite3.h.
︙ | ︙ | |||
144 145 146 147 148 149 150 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 #define SQLITE_SOURCE_ID "2022-02-05 01:01:07 1ec747d1c34ced9877709dd306e674376e79145de08b9c316d12bc5e06efc03e" /* ** 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 |
︙ | ︙ | |||
4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 | ** sqlite3_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite3_value objects even when not strictly required. ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments ** to [sqlite3_result_value()], [sqlite3_bind_value()], and ** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. | > > | 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 | ** sqlite3_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite3_value objects even when not strictly required. ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] ** are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments ** to [sqlite3_result_value()], [sqlite3_bind_value()], and ** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. |
︙ | ︙ | |||
7127 7128 7129 7130 7131 7132 7133 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | > > | 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 | #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents ** an operator that is part of a constraint term in the WHERE clause of ** a query that uses a [virtual table]. ** ** ^The left-hand operand of the operator is given by the corresponding ** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand ** operand is the rowid. ** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET ** operators have no left-hand operand, and so for those operators the ** corresponding aConstraint[].iColumn is meaningless and should not be ** used. ** ** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through ** value 255 are reserved to represent functions that are overloaded ** by the [xFindFunction|xFindFunction method] of the virtual table ** implementation. ** ** The right-hand operands for each constraint might be accessible using ** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand ** operand is only available if it appears as a single constant literal ** in the input SQL. If the right-hand operand is another column or an ** expression (even a constant expression) or a parameter, then the ** sqlite3_vtab_rhs_value() probably will not be able to extract it. ** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and ** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand ** and hence calls to sqlite3_vtab_rhs_value() for those operators will ** always return SQLITE_NOTFOUND. ** ** The collating sequence to be used for comparison can be found using ** the [sqlite3_vtab_collation()] interface. For most real-world virtual ** tables, the collating sequence of constraints does not matter (for example ** because the constraints are numeric) and so the sqlite3_vtab_collation() ** interface is no commonly needed. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 #define SQLITE_INDEX_CONSTRAINT_LT 16 #define SQLITE_INDEX_CONSTRAINT_GE 32 #define SQLITE_INDEX_CONSTRAINT_MATCH 64 #define SQLITE_INDEX_CONSTRAINT_LIKE 65 #define SQLITE_INDEX_CONSTRAINT_GLOB 66 #define SQLITE_INDEX_CONSTRAINT_REGEXP 67 #define SQLITE_INDEX_CONSTRAINT_NE 68 #define SQLITE_INDEX_CONSTRAINT_ISNOT 69 #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 #define SQLITE_INDEX_CONSTRAINT_IS 72 #define SQLITE_INDEX_CONSTRAINT_LIMIT 73 #define SQLITE_INDEX_CONSTRAINT_OFFSET 74 #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation ** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before |
︙ | ︙ | |||
9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 | ** current implementation, the sqlite3_vtab_nochange() interface does always ** returns false for the enhanced [UPDATE FROM] statement. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** ** This function may only be called from within a call to the [xBestIndex] ** method of a [virtual table]. This function returns a pointer to a string ** that is the name of the appropriate collation sequence to use for text ** comparisons on the constraint identified by its arguments. ** | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 | ** current implementation, the sqlite3_vtab_nochange() interface does always ** returns false for the enhanced [UPDATE FROM] statement. */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** METHOD: sqlite3_index_info ** ** This function may only be called from within a call to the [xBestIndex] ** method of a [virtual table]. This function returns a pointer to a string ** that is the name of the appropriate collation sequence to use for text ** comparisons on the constraint identified by its arguments. ** ** The first argument must be the pointer to the [sqlite3_index_info] object ** that is the first parameter to the xBestIndex() method. The second argument ** must be an index into the aConstraint[] array belonging to the ** sqlite3_index_info structure passed to xBestIndex. ** ** Important: ** The first parameter must be the same pointer that is passed into the ** xBestMethod() method. The first parameter may not be a pointer to a ** different [sqlite3_index_info] object, even an exact copy. ** ** The return value is computed as follows: ** ** <ol> ** <li><p> If the constraint comes from a WHERE clause expression that contains ** a [COLLATE operator], then the name of the collation specified by ** that COLLATE operator is returned. ** <li><p> If there is no COLLATE operator, but the column that is the subject ** of the constraint specifies an alternative collating sequence via ** a [COLLATE clause] on the column definition within the CREATE TABLE ** statement that was passed into [sqlite3_declare_vtab()], then the ** name of that alternative collating sequence is returned. ** <li><p> Otherwise, "BINARY" is returned. ** </ol> */ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); /* ** CAPI3REF: Determine if a virtual table query is DISTINCT ** METHOD: sqlite3_index_info ** ** This API may only be used from within an [xBestIndex|xBestIndex method] ** of a [virtual table] implementation. The result of calling this ** interface from outside of xBestIndex() is undefined and probably harmful. ** ** ^The sqlite3_vtab_distinct() interface returns an integer that is ** either 0, 1, or 2. The integer returned by sqlite3_vtab_distinct() ** gives the virtual table additional information about how the query ** planner wants the output to be ordered. As long as the virtual table ** can meet the ordering requirements of the query planner, it may set ** the "orderByConsumed" flag. ** ** <ol><li value="0"><p> ** ^If the sqlite3_vtab_distinct() interface returns 0, that means ** that the query planner needs the virtual table to return all rows in the ** sort order defined by the "nOrderBy" and "aOrderBy" fields of the ** [sqlite3_index_info] object. This is the default expectation. If the ** virtual table outputs all rows in sorted order, then it is always safe for ** the xBestIndex method to set the "orderByConsumed" flag, regardless of ** the return value from sqlite3_vtab_distinct(). ** <li value="1"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 1, that means ** that the query planner does not need the rows to be returned in sorted order ** as long as all rows with the same values in all columns identified by the ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner ** is doing a GROUP BY. ** <li value="2"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular ** order, as long as rows with the same values in all "aOrderBy" columns ** are adjacent.)^ ^(Furthermore, only a single row for each particular ** combination of values in the columns identified by the "aOrderBy" field ** needs to be returned.)^ ^It is always ok for two or more rows with the same ** values in all "aOrderBy" columns to be returned, as long as all such rows ** are adjacent. ^The virtual table may, if it chooses, omit extra rows ** that have the same value for all columns identified by "aOrderBy". ** ^However omitting the extra rows is optional. ** This mode is used for a DISTINCT query. ** </ol> ** ** ^For the purposes of comparing virtual table output values to see if the ** values are same value for sorting purposes, two NULL values are considered ** to be the same. In other words, the comparison operator is "IS" ** (or "IS NOT DISTINCT FROM") and not "==". ** ** If a virtual table implementation is unable to meet the requirements ** specified above, then it must not set the "orderByConsumed" flag in the ** [sqlite3_index_info] object or an incorrect answer may result. ** ** ^A virtual table implementation is always free to return rows in any order ** it wants, as long as the "orderByConsumed" flag is not set. ^When the ** the "orderByConsumed" flag is unset, the query planner will add extra ** [bytecode] to ensure that the final results returned by the SQL query are ** ordered correctly. The use of the "orderByConsumed" flag and the ** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful ** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" ** flag might help queries against a virtual table to run faster. Being ** overly aggressive and setting the "orderByConsumed" flag when it is not ** valid to do so, on the other hand, might cause SQLite to return incorrect ** results. */ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); /* ** CAPI3REF: Identify and handle IN constraints in xBestIndex ** ** This interface may only be used from within an ** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. ** The result of invoking this interface from any other context is ** undefined and probably harmful. ** ** ^(A constraint on a virtual table of the form ** "[IN operator|column IN (...)]" is ** communicated to the xBestIndex method as a ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use ** this constraint, it must set the corresponding ** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under ** the usual mode of handling IN operators, SQLite generates [bytecode] ** that invokes the [xFilter|xFilter() method] once for each value ** on the right-hand side of the IN operator.)^ Thus the virtual table ** only sees a single value from the right-hand side of the IN operator ** at a time. ** ** In some cases, however, it would be advantageous for the virtual ** table to see all values on the right-hand of the IN operator all at ** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: ** ** <ol> ** <li><p> ** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) ** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint ** is an [IN operator] that can be processed all at once. ^In other words, ** sqlite3_vtab_in() with -1 in the third argument is a mechanism ** by which the virtual table can ask SQLite if all-at-once processing ** of the IN operator is even possible. ** ** <li><p> ** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates ** to SQLite that the virtual table does or does not want to process ** the IN operator all-at-once, respectively. ^Thus when the third ** parameter (F) is non-negative, this interface is the mechanism by ** which the virtual table tells SQLite how it wants to process the ** IN operator. ** </ol> ** ** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times ** within the same xBestIndex method call. ^For any given P,N pair, ** the return value from sqlite3_vtab_in(P,N,F) will always be the same ** within the same xBestIndex call. ^If the interface returns true ** (non-zero), that means that the constraint is an IN operator ** that can be processed all-at-once. ^If the constraint is not an IN ** operator or cannot be processed all-at-once, then the interface returns ** false. ** ** ^(All-at-once processing of the IN operator is selected if both of the ** following conditions are met: ** ** <ol> ** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive ** integer. This is how the virtual table tells SQLite that it wants to ** use the N-th constraint. ** ** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was ** non-negative had F>=1. ** </ol>)^ ** ** ^If either or both of the conditions above are false, then SQLite uses ** the traditional one-at-a-time processing strategy for the IN constraint. ** ^If both conditions are true, then the argvIndex-th parameter to the ** xFilter method will be an [sqlite3_value] that appears to be NULL, ** but which can be passed to [sqlite3_vtab_in_first()] and ** [sqlite3_vtab_in_next()] to find all values on the right-hand side ** of the IN constraint. */ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); /* ** CAPI3REF: Find all elements on the right-hand side of an IN constraint. ** ** These interfaces are only useful from within the ** [xFilter|xFilter() method] of a [virtual table] implementation. ** The result of invoking these interfaces from any other context ** is undefined and probably harmful. ** ** The X parameter in a call to sqlite3_vtab_in_first(X,P) or ** sqlite3_vtab_in_next(X,P) must be one of the parameters to the ** xFilter method which invokes these routines, and specifically ** a parameter that was previously selected for all-at-once IN constraint ** processing use the [sqlite3_vtab_in()] interface in the ** [xBestIndex|xBestIndex method]. ^(If the X parameter is not ** an xFilter argument that was selected for all-at-once IN constraint ** processing, then these routines return [SQLITE_MISUSE])^ or perhaps ** exhibit some other undefined or harmful behavior. ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: ** ** <blockquote><pre> ** for(rc=sqlite3_vtab_in_first(pList, &pVal); ** rc==SQLITE_OK && pVal ** rc=sqlite3_vtab_in_next(pList, &pVal) ** ){ ** // do something with pVal ** } ** if( rc!=SQLITE_OK ){ ** // an error has occurred ** } ** </pre></blockquote>)^ ** ** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) ** routines return SQLITE_OK and set *P to point to the first or next value ** on the RHS of the IN constraint. ^If there are no more values on the ** right hand side of the IN constraint, then *P is set to NULL and these ** routines return [SQLITE_DONE]. ^The return value might be ** some other value, such as SQLITE_NOMEM, in the event of a malfunction. ** ** The *ppOut values returned by these routines are only valid until the ** next call to either of these routines or until the end of the xFilter ** method from which these routines were called. If the virtual table ** implementation needs to retain the *ppOut values for longer, it must make ** copies. The *ppOut values are [protected sqlite3_value|protected]. */ SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); /* ** CAPI3REF: Constraint values in xBestIndex() ** METHOD: sqlite3_index_info ** ** This API may only be used from within the [xBestIndex|xBestIndex method] ** of a [virtual table] implementation. The result of calling this interface ** from outside of an xBestIndex method are undefined and probably harmful. ** ** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within ** the [xBestIndex] method of a [virtual table] implementation, with P being ** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and ** J being a 0-based index into P->aConstraint[], then this routine ** attempts to set *V to the value of the right-hand operand of ** that constraint if the right-hand operand is known. ^If the ** right-hand operand is not known, then *V is set to a NULL pointer. ** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if ** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) ** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th ** constraint is not available. ^The sqlite3_vtab_rhs_value() interface ** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if ** something goes wrong. ** ** The sqlite3_vtab_rhs_value() interface is usually only successful if ** the right-hand operand of a constraint is a literal value in the original ** SQL statement. If the right-hand operand is an expression or a reference ** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() ** will probably return [SQLITE_NOTFOUND]. ** ** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and ** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such ** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ ** ** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value ** and remains valid for the duration of the xBestIndex method call. ** ^When xBestIndex returns, the sqlite3_value object returned by ** sqlite3_vtab_rhs_value() is automatically deallocated. ** ** The "_rhs_" in the name of this routine is an appreviation for ** "Right-Hand Side". */ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} ** ** These constants are returned by [sqlite3_vtab_on_conflict()] to ** inform a [virtual table] implementation what the [ON CONFLICT] mode ** is for the SQL statement being evaluated. |
︙ | ︙ |
Changes to src/alerts.c.
︙ | ︙ | |||
2323 2324 2325 2326 2327 2328 2329 | @ </thead><tbody> while( db_step(&q)==SQLITE_ROW ){ sqlite3_int64 iMtime = db_column_int64(&q, 6); double rAge = (iNow - iMtime)/86400.0; int uid = db_column_int(&q, 8); const char *zUname = db_column_text(&q, 3); sqlite3_int64 iContact = db_column_int64(&q, 9); | | | 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 | @ </thead><tbody> while( db_step(&q)==SQLITE_ROW ){ sqlite3_int64 iMtime = db_column_int64(&q, 6); double rAge = (iNow - iMtime)/86400.0; int uid = db_column_int(&q, 8); const char *zUname = db_column_text(&q, 3); sqlite3_int64 iContact = db_column_int64(&q, 9); double rContact = (iNow/86400.0) - iContact; @ <tr> @ <td><a href='%R/alerts?sid=%d(db_column_int(&q,0))'>\ @ %h(db_column_text(&q,1))</a></td> @ <td>%h(db_column_text(&q,2))</td> @ <td>%s(db_column_int(&q,5)?"digest":"")</td> if( uid ){ @ <td><a href='%R/setup_uedit?id=%d(uid)'>%h(zUname)</a> |
︙ | ︙ |
Changes to src/blob.c.
︙ | ︙ | |||
162 163 164 165 166 167 168 | if( newSize==0 ){ free(pBlob->aData); pBlob->aData = 0; pBlob->nAlloc = 0; pBlob->nUsed = 0; pBlob->iCursor = 0; pBlob->blobFlags = 0; | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | if( newSize==0 ){ free(pBlob->aData); pBlob->aData = 0; pBlob->nAlloc = 0; pBlob->nUsed = 0; pBlob->iCursor = 0; pBlob->blobFlags = 0; }else if( newSize>pBlob->nAlloc || newSize+4000<pBlob->nAlloc ){ char *pNew = fossil_realloc(pBlob->aData, newSize); pBlob->aData = pNew; pBlob->nAlloc = newSize; if( pBlob->nUsed>pBlob->nAlloc ){ pBlob->nUsed = pBlob->nAlloc; } } |
︙ | ︙ | |||
593 594 595 596 597 598 599 | ** https://fossil-scm.org/forum/forumpost/b7bbd28db4 ** which implies that this is unconditionally failing on mingw 32-bit ** builds. */ void blob_reserve(Blob *pBlob, unsigned int newSize){ if(newSize>=0x7fff0000 ){ blob_panic(); | | | | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | ** https://fossil-scm.org/forum/forumpost/b7bbd28db4 ** which implies that this is unconditionally failing on mingw 32-bit ** builds. */ void blob_reserve(Blob *pBlob, unsigned int newSize){ if(newSize>=0x7fff0000 ){ blob_panic(); }else if(newSize>pBlob->nAlloc){ pBlob->xRealloc(pBlob, newSize+1); pBlob->aData[newSize] = 0; } } /* ** Make sure a blob is nul-terminated and is not a pointer to unmanaged ** space. Return a pointer to the data. |
︙ | ︙ |
Changes to src/cgi.c.
︙ | ︙ | |||
362 363 364 365 366 367 368 | fossil_fatal("SSL not available"); #endif } /* Works like fread(): ** ** Read as many as bytes of content as we can, up to a maximum of nmemb | | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | fossil_fatal("SSL not available"); #endif } /* Works like fread(): ** ** Read as many as bytes of content as we can, up to a maximum of nmemb ** bytes. Return the number of bytes read. Return 0 if there is no ** further input or if an I/O error occurs. */ size_t cgi_fread(void *ptr, size_t nmemb){ if( !g.httpUseSSL ){ return fread(ptr, 1, nmemb, g.httpIn); } #ifdef FOSSIL_ENABLE_SSL return ssl_read_server(g.httpSSLConn, ptr, nmemb, 1); #else fossil_fatal("SSL not available"); #endif } /* Works like feof(): ** |
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 | } } } #ifdef FOSSIL_ENABLE_JSON /* | < < < < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < | < < | | | < < | < < < < < < < | < < | | | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | } } } #ifdef FOSSIL_ENABLE_JSON /* ** Reads a JSON object from the given blob, which is assumed to have ** been populated by the caller from stdin, the SSL API, or a file, as ** appropriate for the particular use case. On success g.json.post is ** updated to hold the content. On error a FSL_JSON_E_INVALID_REQUEST ** response is output and fossil_exit() is called (in HTTP mode exit ** code 0 is used). */ void cgi_parse_POST_JSON( Blob * pIn ){ cson_value * jv = NULL; cson_parse_info pinfo = cson_parse_info_empty; assert(g.json.gc.a && "json_bootstrap_early() was not called!"); jv = cson_parse_Blob(pIn, &pinfo); if( jv==NULL ){ goto invalidRequest; }else{ json_gc_add( "POST.JSON", jv ); g.json.post.v = jv; g.json.post.o = cson_value_get_object( jv ); if( !g.json.post.o ){ /* we don't support non-Object (Array) requests */ goto invalidRequest; } } return; invalidRequest: cgi_set_content_type(json_guess_content_type()); if(0 != pinfo.errorCode){ /* fancy error message */ char * msg = mprintf("JSON parse error at line %u, column %u, " "byte offset %u: %s", pinfo.line, pinfo.col, pinfo.length, cson_rc_string(pinfo.errorCode)); json_err( FSL_JSON_E_INVALID_REQUEST, msg, 1 ); fossil_free(msg); }else if(jv && !g.json.post.o){ json_err( FSL_JSON_E_INVALID_REQUEST, "Request envelope must be a JSON Object (not array).", 1 ); }else{ /* generic error message */ json_err( FSL_JSON_E_INVALID_REQUEST, NULL, 1 ); } fossil_exit( g.isHTTP ? 0 : 1); |
︙ | ︙ | |||
1360 1361 1362 1363 1364 1365 1366 | g.zContentType = fossil_strndup(zType, (int)(zSemi-zType)); zType = g.zContentType; }else{ g.zContentType = zType; } blob_zero(&g.cgiIn); if( len>0 && zType ){ | < | > > | | > | | < | < < < < < < < < < | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 | g.zContentType = fossil_strndup(zType, (int)(zSemi-zType)); zType = g.zContentType; }else{ g.zContentType = zType; } blob_zero(&g.cgiIn); if( len>0 && zType ){ if( blob_read_from_cgi(&g.cgiIn, len)<len ){ char *zMsg = mprintf("CGI content-length mismatch: Wanted %d bytes" " but got only %d\n", len, blob_size(&g.cgiIn)); malformed_request(zMsg); } if( fossil_strcmp(zType, "application/x-fossil")==0 ){ blob_uncompress(&g.cgiIn, &g.cgiIn); } #ifdef FOSSIL_ENABLE_JSON if( noJson==0 && g.json.isJsonMode!=0 && json_can_consume_content_type(zType)!=0 ){ cgi_parse_POST_JSON(&g.cgiIn); cgi_set_content_type(json_guess_content_type()); } #endif /* FOSSIL_ENABLE_JSON */ } } /* ** Decode POST parameter information in the cgiIn content, if any. */ void cgi_decode_post_parameters(void){ |
︙ | ︙ |
Changes to src/chat.c.
︙ | ︙ | |||
481 482 483 484 485 486 487 488 489 490 491 492 493 494 | ** (default=chat-initial-history setting, equivalent to n=0) are ** returned (negative n fetches all older entries). The client then ** needs to take care to inject them at the end of the history rather ** than the same place new messages go. ** ** If "before" is provided, "name" is ignored. ** ** The reply from this webpage is JSON that describes the new content. ** Format of the json: ** ** | { ** | "msgs":[ ** | { ** | "msgid": integer // message id | > > > > > | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | ** (default=chat-initial-history setting, equivalent to n=0) are ** returned (negative n fetches all older entries). The client then ** needs to take care to inject them at the end of the history rather ** than the same place new messages go. ** ** If "before" is provided, "name" is ignored. ** ** If "raw" is provided, the "xmsg" text is sent back as-is, in ** markdown format, rather than being HTML-ized. This is not used or ** supported by fossil's own chat client but is intended for 3rd-party ** clients. (Specifically, for Brad Harder's curses-based client.) ** ** The reply from this webpage is JSON that describes the new content. ** Format of the json: ** ** | { ** | "msgs":[ ** | { ** | "msgid": integer // message id |
︙ | ︙ | |||
540 541 542 543 544 545 546 547 548 549 550 551 552 553 | Blob json; /* The json to be constructed and returned */ sqlite3_int64 dataVersion; /* Data version. Used for polling. */ const int iDelay = 1000; /* Delay until next poll (milliseconds) */ int nDelay; /* Maximum delay.*/ int msgid = atoi(PD("name","0")); const int msgBefore = atoi(PD("before","0")); int nLimit = msgBefore>0 ? atoi(PD("n","0")) : 0; Blob sql = empty_blob; Stmt q1; nDelay = db_get_int("chat-poll-timeout",420); /* Default about 7 minutes */ login_check_credentials(); if( !g.perm.Chat ) { chat_emit_permissions_error(1); return; | > | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 | Blob json; /* The json to be constructed and returned */ sqlite3_int64 dataVersion; /* Data version. Used for polling. */ const int iDelay = 1000; /* Delay until next poll (milliseconds) */ int nDelay; /* Maximum delay.*/ int msgid = atoi(PD("name","0")); const int msgBefore = atoi(PD("before","0")); int nLimit = msgBefore>0 ? atoi(PD("n","0")) : 0; const int bRaw = P("raw")!=0; Blob sql = empty_blob; Stmt q1; nDelay = db_get_int("chat-poll-timeout",420); /* Default about 7 minutes */ login_check_credentials(); if( !g.perm.Chat ) { chat_emit_permissions_error(1); return; |
︙ | ︙ | |||
617 618 619 620 621 622 623 | }else{ /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */ blob_appendf(&json, "null,"); } blob_appendf(&json, "\"uclr\":%!j,", user_color(zFrom ? zFrom : "nobody")); | > > > | | | > | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | }else{ /* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */ blob_appendf(&json, "null,"); } blob_appendf(&json, "\"uclr\":%!j,", user_color(zFrom ? zFrom : "nobody")); if(bRaw){ blob_appendf(&json, "\"xmsg\":%!j,", zRawMsg); }else{ zMsg = chat_format_to_html(zRawMsg ? zRawMsg : ""); blob_appendf(&json, "\"xmsg\":%!j,", zMsg); fossil_free(zMsg); } if( nByte==0 ){ blob_appendf(&json, "\"fsize\":0"); }else{ blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j", nByte, zFName, zFMime); } |
︙ | ︙ |
Changes to src/diff.c.
︙ | ︙ | |||
119 120 121 122 123 124 125 | ** of the line. If any line is longer than LENGTH_MASK characters, ** the file is considered binary. */ typedef struct DLine DLine; struct DLine { const char *z; /* The text of the line */ u64 h; /* Hash of the line */ | | > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** of the line. If any line is longer than LENGTH_MASK characters, ** the file is considered binary. */ typedef struct DLine DLine; struct DLine { const char *z; /* The text of the line */ u64 h; /* Hash of the line */ unsigned short indent; /* Index of first non-space */ unsigned short n; /* number of bytes */ unsigned short nw; /* number of bytes without leading/trailing space */ unsigned int iNext; /* 1+(Index of next line with same the same hash) */ /* an array of DLine elements serves two purposes. The fields ** above are one per line of input text. But each entry is also ** a bucket in a hash table, as follows: */ unsigned int iHash; /* 1+(first entry in the hash chain) */ }; |
︙ | ︙ | |||
161 162 163 164 165 166 167 | int *aEdit; /* Array of copy/delete/insert triples */ int nEdit; /* Number of integers (3x num of triples) in aEdit[] */ int nEditAlloc; /* Space allocated for aEdit[] */ DLine *aFrom; /* File on left side of the diff */ int nFrom; /* Number of lines in aFrom[] */ DLine *aTo; /* File on right side of the diff */ int nTo; /* Number of lines in aTo[] */ | | > > > > > > > > > > > > > > > > > > > > > > | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | int *aEdit; /* Array of copy/delete/insert triples */ int nEdit; /* Number of integers (3x num of triples) in aEdit[] */ int nEditAlloc; /* Space allocated for aEdit[] */ DLine *aFrom; /* File on left side of the diff */ int nFrom; /* Number of lines in aFrom[] */ DLine *aTo; /* File on right side of the diff */ int nTo; /* Number of lines in aTo[] */ int (*xDiffer)(const DLine *,const DLine *); /* comparison function */ }; /* Fast isspace for use by diff */ static const char diffIsSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 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 diff_isspace(X) (diffIsSpace[(unsigned char)(X)]) /* ** Count the number of lines in the input string. Include the last line ** in the count even if it lacks the \n terminator. If an empty string ** is specified, the number of lines is zero. For the purposes of this ** function, a string is considered empty if it contains no characters ** -OR- it contains only NUL characters. |
︙ | ︙ | |||
243 244 245 246 247 248 249 | } a[i].z = z; k = nn; if( diffFlags & DIFF_STRIP_EOLCR ){ if( k>0 && z[k-1]=='\r' ){ k--; } } a[i].n = k; | < | | > > | | < | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | } a[i].z = z; k = nn; if( diffFlags & DIFF_STRIP_EOLCR ){ if( k>0 && z[k-1]=='\r' ){ k--; } } a[i].n = k; if( diffFlags & DIFF_IGNORE_EOLWS ){ while( k>0 && diff_isspace(z[k-1]) ){ k--; } } if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ int numws = 0; for(s=0; s<k && z[s]<=' '; s++){} a[i].indent = s; a[i].nw = k - s; for(h=0, x=s; x<k; x++){ char c = z[x]; if( diff_isspace(c) ){ ++numws; }else{ h = (h^c)*9000000000000000041LL; } } k -= numws; }else{ int k2 = k & ~0x7; u64 m; for(h=x=s=0; x<k2; x += 8){ memcpy(&m, z+x, 8); h = (h^m)*9000000000000000041LL; } m = 0; memcpy(&m, z+x, k-k2); h ^= m; } a[i].h = h = ((h%281474976710597LL)<<LENGTH_MASK_SZ) | (k-s); h2 = h % nLine; a[i].iNext = a[h2].iHash; a[h2].iHash = i+1; z += nn+1; n -= nn+1; i++; }while( zNL[0]!='\0' && zNL[1]!='\0' ); |
︙ | ︙ | |||
298 299 300 301 302 303 304 | } /* ** Return zero if two DLine elements are identical, ignoring ** all whitespace. The indent field of pA/pB already points ** to the first non-space character in the string. */ | < < > > > > | | | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | } /* ** Return zero if two DLine elements are identical, ignoring ** all whitespace. The indent field of pA/pB already points ** to the first non-space character in the string. */ static int compare_dline_ignore_allws(const DLine *pA, const DLine *pB){ if( pA->h==pB->h ){ int a, b; if( memcmp(pA->z, pB->z, pA->h&LENGTH_MASK)==0 ) return 0; a = pA->indent; b = pB->indent; while( a<pA->n || b<pB->n ){ if( a<pA->n && b<pB->n && pA->z[a++] != pB->z[b++] ) return 1; while( a<pA->n && diff_isspace(pA->z[a])) ++a; while( b<pB->n && diff_isspace(pB->z[b])) ++b; } return pA->n-a != pB->n-b; } return 1; } /* |
︙ | ︙ | |||
336 337 338 339 340 341 342 | /* ** Append a single line of context-diff output to pOut. */ static void appendDiffLine( Blob *pOut, /* Where to write the line of output */ char cPrefix, /* One of " ", "+", or "-" */ | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | /* ** Append a single line of context-diff output to pOut. */ static void appendDiffLine( Blob *pOut, /* Where to write the line of output */ char cPrefix, /* One of " ", "+", or "-" */ const DLine *pLine /* The line to be output */ ){ blob_append_char(pOut, cPrefix); blob_append(pOut, pLine->z, pLine->n); blob_append_char(pOut, '\n'); } /* |
︙ | ︙ | |||
369 370 371 372 373 374 375 | ** Output a patch-style text diff. */ static void contextDiff( DContext *p, /* The difference */ Blob *pOut, /* Output a context diff to here */ DiffConfig *pCfg /* Configuration options */ ){ | | | | | | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | ** Output a patch-style text diff. */ static void contextDiff( DContext *p, /* The difference */ Blob *pOut, /* Output a context diff to here */ DiffConfig *pCfg /* Configuration options */ ){ const DLine *A; /* Left side of the diff */ const DLine *B; /* Right side of the diff */ int a = 0; /* Index of next line in A[] */ int b = 0; /* Index of next line in B[] */ int *R; /* Array of COPY/DELETE/INSERT triples */ int r; /* Index into R[] */ int nr; /* Number of COPY/DELETE/INSERT triples to process */ int mxr; /* Maximum value for r */ int na, nb; /* Number of lines shown from A and B */ int i, j; /* Loop counters */ int m; /* Number of lines to output */ |
︙ | ︙ | |||
617 618 619 620 621 622 623 | } /* ** Return true if the string starts with n spaces */ static int allSpaces(const char *z, int n){ int i; | | | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | } /* ** Return true if the string starts with n spaces */ static int allSpaces(const char *z, int n){ int i; for(i=0; i<n && diff_isspace(z[i]); i++){} return i==n; } /* ** Try to improve the human-readability of the LineChange p. ** ** (1) If the first change span shows a change of indentation, try to |
︙ | ︙ | |||
743 744 745 746 747 748 749 | int iBestVal = -1; int i; int nLong = nLeft<nRight ? nRight : nLeft; int nGap = nLong - nShort; for(i=nShort-nSuffix; i<=nPrefix; i++){ int iVal = 0; char c = zLeft[i]; | | | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 | int iBestVal = -1; int i; int nLong = nLeft<nRight ? nRight : nLeft; int nGap = nLong - nShort; for(i=nShort-nSuffix; i<=nPrefix; i++){ int iVal = 0; char c = zLeft[i]; if( diff_isspace(c) ){ iVal += 5; }else if( !fossil_isalnum(c) ){ iVal += 2; } c = zLeft[i+nGap-1]; if( diff_isspace(c) ){ iVal += 5; }else if( !fossil_isalnum(c) ){ iVal += 2; } if( iVal>iBestVal ){ iBestVal = iVal; iBest = i; |
︙ | ︙ | |||
887 888 889 890 891 892 893 | */ typedef struct DiffBuilder DiffBuilder; struct DiffBuilder { void (*xSkip)(DiffBuilder*, unsigned int, int); void (*xCommon)(DiffBuilder*,const DLine*); void (*xInsert)(DiffBuilder*,const DLine*); void (*xDelete)(DiffBuilder*,const DLine*); | | | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | */ typedef struct DiffBuilder DiffBuilder; struct DiffBuilder { void (*xSkip)(DiffBuilder*, unsigned int, int); void (*xCommon)(DiffBuilder*,const DLine*); void (*xInsert)(DiffBuilder*,const DLine*); void (*xDelete)(DiffBuilder*,const DLine*); void (*xReplace)(DiffBuilder*,const DLine*,const DLine*); void (*xEdit)(DiffBuilder*,const DLine*,const DLine*); void (*xEnd)(DiffBuilder*); unsigned int lnLeft; /* Lines seen on the left (delete) side */ unsigned int lnRight; /* Lines seen on the right (insert) side */ unsigned int nPending; /* Number of pending lines */ int eState; /* State of the output */ int width; /* Display width */ |
︙ | ︙ | |||
1731 1732 1733 1734 1735 1736 1737 | ** (1) Remove leading and trailing whitespace. ** (2) Truncate both strings to at most 250 characters ** (3) If the two strings have a common prefix, measure that prefix ** (4) Find the length of the longest common subsequence that is ** at least 150% longer than the common prefix. ** (5) Longer common subsequences yield lower scores. */ | | > > > > > > > > > > > | > > > > | | < < < | 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 | ** (1) Remove leading and trailing whitespace. ** (2) Truncate both strings to at most 250 characters ** (3) If the two strings have a common prefix, measure that prefix ** (4) Find the length of the longest common subsequence that is ** at least 150% longer than the common prefix. ** (5) Longer common subsequences yield lower scores. */ static int match_dline(DLine *pA, DLine *pB){ const char *zA; /* Left string */ const char *zB; /* right string */ int nA; /* Bytes in zA[] */ int nB; /* Bytes in zB[] */ int nMin; int nPrefix; int avg; /* Average length of A and B */ int i, j, k; /* Loop counters */ int best = 0; /* Longest match found so far */ int score; /* Final score. 0..100 */ unsigned char c; /* Character being examined */ unsigned char aFirst[256]; /* aFirst[X] = index in zB[] of first char X */ unsigned char aNext[252]; /* aNext[i] = index in zB[] of next zB[i] char */ zA = pA->z; if( pA->nw==0 && pA->n ){ for(i=0; i<pA->n && diff_isspace(zA[i]); i++){} pA->indent = i; for(j=pA->n-1; j>i && diff_isspace(zA[j]); j--){} pA->nw = j - i + 1; } zA += pA->indent; nA = pA->nw; zB = pB->z; if( pB->nw==0 && pB->n ){ for(i=0; i<pB->n && diff_isspace(zB[i]); i++){} pB->indent = i; for(j=pB->n-1; j>i && diff_isspace(zB[j]); j--){} pB->nw = j - i + 1; } zB += pB->indent; nB = pB->nw; if( nA>250 ) nA = 250; if( nB>250 ) nB = 250; avg = (nA+nB)/2; if( avg==0 ) return 0; nMin = nA; if( nB<nMin ) nMin = nB; if( nMin==0 ) return 68; |
︙ | ︙ | |||
1783 1784 1785 1786 1787 1788 1789 | c = (unsigned char)zA[i]; for(j=aFirst[c]; j<nB-best && memcmp(&zA[i],&zB[j],best)==0; j = aNext[j]){ int limit = minInt(nA-i, nB-j); for(k=best; k<=limit && zA[k+i]==zB[k+j]; k++){} if( k>best ) best = k; } } | | | 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 | c = (unsigned char)zA[i]; for(j=aFirst[c]; j<nB-best && memcmp(&zA[i],&zB[j],best)==0; j = aNext[j]){ int limit = minInt(nA-i, nB-j); for(k=best; k<=limit && zA[k+i]==zB[k+j]; k++){} if( k>best ) best = k; } } score = 5 + ((best>=avg) ? 0 : (avg - best)*95/avg); #if 0 fprintf(stderr, "A: [%.*s]\nB: [%.*s]\nbest=%d avg=%d score=%d\n", nA, zA+1, nB, zB+1, best, avg, score); #endif /* Return the result */ |
︙ | ︙ | |||
1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 | a.z = g.argv[2]; a.n = (int)strlen(a.z); b.z = g.argv[3]; b.n = (int)strlen(b.z); x = match_dline(&a, &b); fossil_print("%d\n", x); } /* ** The threshold at which diffBlockAlignment transitions from the ** O(N*N) Wagner minimum-edit-distance algorithm to a less process ** O(NlogN) divide-and-conquer approach. */ #define DIFF_ALIGN_MX 1225 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 | a.z = g.argv[2]; a.n = (int)strlen(a.z); b.z = g.argv[3]; b.n = (int)strlen(b.z); x = match_dline(&a, &b); fossil_print("%d\n", x); } /* Forward declarations for recursion */ static unsigned char *diffBlockAlignment( DLine *aLeft, int nLeft, /* Text on the left */ DLine *aRight, int nRight, /* Text on the right */ DiffConfig *pCfg, /* Configuration options */ int *pNResult /* OUTPUT: Bytes of result */ ); static void longestCommonSequence( DContext *p, /* Two files being compared */ int iS1, int iE1, /* Range of lines in p->aFrom[] */ int iS2, int iE2, /* Range of lines in p->aTo[] */ int *piSX, int *piEX, /* Write p->aFrom[] common segment here */ int *piSY, int *piEY /* Write p->aTo[] common segment here */ ); /* ** Make a copy of a list of nLine DLine objects from one array to ** another. Hash the new array to ignore whitespace. */ static void diffDLineXfer( DLine *aTo, const DLine *aFrom, int nLine ){ int i, j, k; u64 h, h2; for(i=0; i<nLine; i++) aTo[i].iHash = 0; for(i=0; i<nLine; i++){ const char *z = aFrom[i].z; int n = aFrom[i].n; for(j=0; j<n && diff_isspace(z[j]); j++){} aTo[i].z = &z[j]; for(k=aFrom[i].n; k>j && diff_isspace(z[k-1]); k--){} aTo[i].n = n = k-j; aTo[i].indent = 0; aTo[i].nw = 0; for(h=0; j<k; j++){ char c = z[j]; if( !diff_isspace(c) ){ h = (h^c)*9000000000000000041LL; } } aTo[i].h = h = ((h%281474976710597LL)<<LENGTH_MASK_SZ) | n; h2 = h % nLine; aTo[i].iNext = aTo[h2].iHash; aTo[h2].iHash = i+1; } } /* ** For a difficult diff-block alignment that was originally for ** the default consider-all-whitespace algorithm, try to find the ** longest common subsequence between the two blocks that involves ** only whitespace changes. */ static unsigned char *diffBlockAlignmentIgnoreSpace( DLine *aLeft, int nLeft, /* Text on the left */ DLine *aRight, int nRight, /* Text on the right */ DiffConfig *pCfg, /* Configuration options */ int *pNResult /* OUTPUT: Bytes of result */ ){ DContext dc; int iSX, iEX; /* Start and end of LCS on the left */ int iSY, iEY; /* Start and end of the LCS on the right */ unsigned char *a1, *a2; int n1, n2, nLCS; dc.aEdit = 0; dc.nEdit = 0; dc.nEditAlloc = 0; dc.nFrom = nLeft; dc.nTo = nRight; dc.xDiffer = compare_dline_ignore_allws; dc.aFrom = fossil_malloc( sizeof(DLine)*(nLeft+nRight) ); dc.aTo = &dc.aFrom[dc.nFrom]; diffDLineXfer(dc.aFrom, aLeft, nLeft); diffDLineXfer(dc.aTo, aRight, nRight); longestCommonSequence(&dc,0,nLeft,0,nRight,&iSX,&iEX,&iSY,&iEY); fossil_free(dc.aFrom); nLCS = iEX - iSX; if( nLCS<5 ) return 0; /* No good LCS was found */ if( pCfg->diffFlags & DIFF_DEBUG ){ fossil_print(" LCS size=%d\n" " [%.*s]\n" " [%.*s]\n", nLCS, aLeft[iSX].n, aLeft[iSX].z, aLeft[iEX-1].n, aLeft[iEX-1].z); } a1 = diffBlockAlignment(aLeft,iSX,aRight,iSY,pCfg,&n1); a2 = diffBlockAlignment(aLeft+iEX, nLeft-iEX, aRight+iEY, nRight-iEY, pCfg, &n2); a1 = fossil_realloc(a1, n1+nLCS+n2); memcpy(a1+n1+nLCS,a2,n2); memset(a1+n1,3,nLCS); fossil_free(a2); *pNResult = n1+n2+nLCS; return a1; } /* ** This is a helper route for diffBlockAlignment(). In this case, ** a very large block is encountered that might be too expensive to ** use the O(N*N) Wagner edit distance algorithm. So instead, this ** block implements a less-precise but faster O(N*logN) divide-and-conquer ** approach. */ static unsigned char *diffBlockAlignmentDivideAndConquer( DLine *aLeft, int nLeft, /* Text on the left */ DLine *aRight, int nRight, /* Text on the right */ DiffConfig *pCfg, /* Configuration options */ int *pNResult /* OUTPUT: Bytes of result */ ){ DLine *aSmall; /* The smaller of aLeft and aRight */ DLine *aBig; /* The larger of aLeft and aRight */ int nSmall, nBig; /* Size of aSmall and aBig. nSmall<=nBig */ int iDivSmall, iDivBig; /* Divider point for aSmall and aBig */ int iDivLeft, iDivRight; /* Divider point for aLeft and aRight */ unsigned char *a1, *a2; /* Results of the alignments on two halves */ int n1, n2; /* Number of entries in a1 and a2 */ int score, bestScore; /* Score and best score seen so far */ int i; /* Loop counter */ if( nLeft>nRight ){ aSmall = aRight; nSmall = nRight; aBig = aLeft; nBig = nLeft; }else{ aSmall = aLeft; nSmall = nLeft; aBig = aRight; nBig = nRight; } iDivBig = nBig/2; iDivSmall = nSmall/2; if( pCfg->diffFlags & DIFF_DEBUG ){ fossil_print(" Divide at [%.*s]\n", aBig[iDivBig].n, aBig[iDivBig].z); } bestScore = 10000; for(i=0; i<nSmall; i++){ score = match_dline(aBig+iDivBig, aSmall+i) + abs(i-nSmall/2)*2; if( score<bestScore ){ bestScore = score; iDivSmall = i; } } if( aSmall==aRight ){ iDivRight = iDivSmall; iDivLeft = iDivBig; }else{ iDivRight = iDivBig; iDivLeft = iDivSmall; } a1 = diffBlockAlignment(aLeft,iDivLeft,aRight,iDivRight,pCfg,&n1); a2 = diffBlockAlignment(aLeft+iDivLeft, nLeft-iDivLeft, aRight+iDivRight, nRight-iDivRight, pCfg, &n2); a1 = fossil_realloc(a1, n1+n2 ); memcpy(a1+n1,a2,n2); fossil_free(a2); *pNResult = n1+n2; return a1; } /* ** The threshold at which diffBlockAlignment transitions from the ** O(N*N) Wagner minimum-edit-distance algorithm to a less process ** O(NlogN) divide-and-conquer approach. */ #define DIFF_ALIGN_MX 1225 |
︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by ** adding a cost to each match based on how well the two rows match ** each other. Insertion and deletion costs are 50. Match costs ** are between 0 and 100 where 0 is a perfect match 100 is a complete ** mismatch. */ static unsigned char *diffBlockAlignment( | | | | | | 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by ** adding a cost to each match based on how well the two rows match ** each other. Insertion and deletion costs are 50. Match costs ** are between 0 and 100 where 0 is a perfect match 100 is a complete ** mismatch. */ static unsigned char *diffBlockAlignment( DLine *aLeft, int nLeft, /* Text on the left */ DLine *aRight, int nRight, /* Text on the right */ DiffConfig *pCfg, /* Configuration options */ int *pNResult /* OUTPUT: Bytes of result */ ){ int i, j, k; /* Loop counters */ int *a; /* One row of the Wagner matrix */ int *pToFree; /* Space that needs to be freed */ unsigned char *aM; /* Wagner result matrix */ int nMatch, iMatch; /* Number of matching lines and match score */ int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
︙ | ︙ | |||
1873 1874 1875 1876 1877 1878 1879 | if( nRight==0 ){ aM = fossil_malloc( nLeft + 2 ); memset(aM, 1, nLeft); *pNResult = nLeft; return aM; } | > | > > > | > | < < < < < | | < < < < < | < < < < < | < < < < < < < < < < < | < < < < < < | | < < < < < < | 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 | if( nRight==0 ){ aM = fossil_malloc( nLeft + 2 ); memset(aM, 1, nLeft); *pNResult = nLeft; return aM; } if( pCfg->diffFlags & DIFF_DEBUG ){ fossil_print("BlockAlignment:\n [%.*s] + %d\n [%.*s] + %d\n", aLeft[0].n, aLeft[0].z, nLeft, aRight[0].n, aRight[0].z, nRight); } /* For large alignments, try to use alternative algorithms that are ** faster than the O(N*N) Wagner edit distance. */ if( nLeft*nRight>DIFF_ALIGN_MX && (pCfg->diffFlags & DIFF_SLOW_SBS)==0 ){ if( (pCfg->diffFlags & DIFF_IGNORE_ALLWS)==0 ){ unsigned char *aRes; aRes = diffBlockAlignmentIgnoreSpace( aLeft, nLeft,aRight, nRight,pCfg,pNResult); if( aRes ) return aRes; } return diffBlockAlignmentDivideAndConquer( aLeft, nLeft,aRight, nRight,pCfg,pNResult); } /* If we reach this point, we will be doing an O(N*N) Wagner minimum ** edit distance to compute the alignment. */ if( nRight < count(aBuf)-1 ){ pToFree = 0; |
︙ | ︙ | |||
2024 2025 2026 2027 2028 2029 2030 | ** Format a diff using a DiffBuilder object */ static void formatDiff( DContext *p, /* The computed diff */ DiffConfig *pCfg, /* Configuration options */ DiffBuilder *pBuilder /* The formatter object */ ){ | | | | 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 | ** Format a diff using a DiffBuilder object */ static void formatDiff( DContext *p, /* The computed diff */ DiffConfig *pCfg, /* Configuration options */ DiffBuilder *pBuilder /* The formatter object */ ){ DLine *A; /* Left side of the diff */ DLine *B; /* Right side of the diff */ unsigned int a = 0; /* Index of next line in A[] */ unsigned int b = 0; /* Index of next line in B[] */ const int *R; /* Array of COPY/DELETE/INSERT triples */ unsigned int r; /* Index into R[] */ unsigned int nr; /* Number of COPY/DELETE/INSERT triples to process */ unsigned int mxr; /* Maximum value for r */ unsigned int na, nb; /* Number of lines shown from A and B */ |
︙ | ︙ | |||
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 | expandEdit(p, p->nEdit*2 + 15); if( p->aEdit==0 ) return; } p->aEdit[p->nEdit++] = nCopy; p->aEdit[p->nEdit++] = nDel; p->aEdit[p->nEdit++] = nIns; } /* ** Do a single step in the difference. Compute a sequence of ** copy/delete/insert steps that will convert lines iS1 through iE1-1 of ** the input into lines iS2 through iE2-1 of the output and write ** that sequence into the difference context. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 | expandEdit(p, p->nEdit*2 + 15); if( p->aEdit==0 ) return; } p->aEdit[p->nEdit++] = nCopy; p->aEdit[p->nEdit++] = nDel; p->aEdit[p->nEdit++] = nIns; } /* ** A common subsequene between p->aFrom and p->aTo has been found. ** This routine tries to judge if the subsequence really is a valid ** match or rather is just an artifact of an indentation change. ** ** Return non-zero if the subsequence is valid. Return zero if the ** subsequence seems likely to be an editing artifact and should be ** ignored. ** ** This routine is a heuristic optimization intended to give more ** intuitive diff results following an indentation change it code that ** is formatted similarly to C/C++, Javascript, Go, TCL, and similar ** languages that use {...} for nesting. A correct diff is computed ** even if this routine always returns true (non-zero). But sometimes ** a more intuitive diff can result if this routine returns false. ** ** The subsequences consists of the rows iSX through iEX-1 (inclusive) ** in p->aFrom[]. The total sequences is iS1 through iE1-1 (inclusive) ** of p->aFrom[]. ** ** Example where this heuristic is useful, see the diff at ** https://www.sqlite.org/src/fdiff?v1=0e79dd15cbdb4f48&v2=33955a6fd874dd97 ** ** See also discussion at https://fossil-scm.org/forum/forumpost/9ba3284295 ** ** ALGORITHM (subject to change and refinement): ** ** 1. If the subsequence is larger than 1/7th of the original span, ** then consider it valid. --> return 1 ** ** 2. If the subsequence contains any charaters other than '}', '{", ** or whitespace, then consider it valid. --> return 1 ** ** 3. Otherwise, it is potentially an artifact of an indentation ** change. --> return 0 */ static int likelyNotIndentChngArtifact( DContext *p, /* The complete diff context */ int iS1, /* Start of the main segment */ int iSX, /* Start of the subsequence */ int iEX, /* First row past the end of the subsequence */ int iE1 /* First row past the end of the main segment */ ){ int i, j; if( (iEX-iSX)*7 >= (iE1-iS1) ) return 1; for(i=iSX; i<iEX; i++){ const char *z = p->aFrom[i].z; for(j=p->aFrom[i].n-1; j>=0; j--){ char c = z[j]; if( c!='}' && c!='{' && !diff_isspace(c) ) return 1; } } return 0; } /* ** Do a single step in the difference. Compute a sequence of ** copy/delete/insert steps that will convert lines iS1 through iE1-1 of ** the input into lines iS2 through iE2-1 of the output and write ** that sequence into the difference context. ** |
︙ | ︙ | |||
2440 2441 2442 2443 2444 2445 2446 | appendTriple(p, 0, iE1-iS1, 0); return; } /* Find the longest matching segment between the two sequences */ longestCommonSequence(p, iS1, iE1, iS2, iE2, &iSX, &iEX, &iSY, &iEY); | | > > | 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 | appendTriple(p, 0, iE1-iS1, 0); return; } /* Find the longest matching segment between the two sequences */ longestCommonSequence(p, iS1, iE1, iS2, iE2, &iSX, &iEX, &iSY, &iEY); if( iEX>iSX+5 || (iEX>iSX && likelyNotIndentChngArtifact(p,iS1,iSX,iEX,iE1) ) ){ /* A common segment has been found. ** Recursively diff either side of the matching segment */ diff_step(p, iS1, iSX, iS2, iSY); if( iEX>iSX ){ appendTriple(p, iEX - iSX, 0, 0); } diff_step(p, iEX, iE1, iEY, iE2); |
︙ | ︙ | |||
3118 3119 3120 3121 3122 3123 3124 | if( zLimit ){ if( strcmp(zLimit,"none")==0 ){ iLimit = 0; mxTime = 0; }else if( sqlite3_strglob("*[0-9]s", zLimit)==0 ){ iLimit = 0; | > | | 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 | if( zLimit ){ if( strcmp(zLimit,"none")==0 ){ iLimit = 0; mxTime = 0; }else if( sqlite3_strglob("*[0-9]s", zLimit)==0 ){ iLimit = 0; mxTime = (sqlite3_int64)(current_time_in_milliseconds() + 1000.0*atof(zLimit)); }else{ iLimit = atoi(zLimit); if( iLimit<=0 ) iLimit = 30; mxTime = 0; } }else{ /* Default limit is as much as we can do in 1.000 seconds */ |
︙ | ︙ |
Changes to src/dispatch.c.
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 | ** Documentation on universal command-line options. */ /* @-comment: # */ static const char zOptions[] = @ Command-line options common to all commands: @ @ --args FILENAME Read additional arguments and options from FILENAME @ --cgitrace Active CGI tracing @ --comfmtflags VALUE Set comment formatting flags to VALUE @ --comment-format VALUE Alias for --comfmtflags @ --errorlog FILENAME Log errors to FILENAME @ --help Show help on the command rather than running it @ --httptrace Trace outbound HTTP requests @ --localtime Display times using the local timezone @ --no-th-hook Do not run TH1 hooks @ --quiet Reduce the amount of output @ --sqlstats Show SQL usage statistics when done @ --sqltrace Trace all SQL commands @ --sshtrace Trace SSH activity @ --ssl-identity NAME Set the SSL identity to NAME @ --systemtrace Trace calls to system() | > > > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | ** Documentation on universal command-line options. */ /* @-comment: # */ static const char zOptions[] = @ Command-line options common to all commands: @ @ --args FILENAME Read additional arguments and options from FILENAME @ --case-sensitive BOOL Set case sensitivity for file names @ --cgitrace Active CGI tracing @ --chdir PATH Change to PATH before performing any operations @ --comfmtflags VALUE Set comment formatting flags to VALUE @ --comment-format VALUE Alias for --comfmtflags @ --errorlog FILENAME Log errors to FILENAME @ --help Show help on the command rather than running it @ --httptrace Trace outbound HTTP requests @ --localtime Display times using the local timezone @ --nocgi Do not act as GCI @ --no-th-hook Do not run TH1 hooks @ --quiet Reduce the amount of output @ --sqlstats Show SQL usage statistics when done @ --sqltrace Trace all SQL commands @ --sshtrace Trace SSH activity @ --ssl-identity NAME Set the SSL identity to NAME @ --systemtrace Trace calls to system() |
︙ | ︙ |
Changes to src/fusefs.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** This module implements the userspace side of a Fuse Filesystem that ** contains all check-ins for a fossil repository. ** ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for ** the Fuse Filesystem, of course. */ | < > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** This module implements the userspace side of a Fuse Filesystem that ** contains all check-ins for a fossil repository. ** ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for ** the Fuse Filesystem, of course. */ #include "config.h" #include <stdio.h> #include <string.h> #ifdef FOSSIL_HAVE_FUSEFS #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include "fusefs.h" |
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 | } static struct fuse_operations fusefs_methods = { .getattr = fusefs_getattr, .readdir = fusefs_readdir, .read = fusefs_read, }; /* ** COMMAND: fusefs* ** ** Usage: %fossil fusefs [--debug] DIRECTORY ** ** This command uses the Fuse Filesystem (FuseFS) to mount a directory | > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | } static struct fuse_operations fusefs_methods = { .getattr = fusefs_getattr, .readdir = fusefs_readdir, .read = fusefs_read, }; #endif /* FOSSIL_HAVE_FUSEFS */ /* ** COMMAND: fusefs* ** ** Usage: %fossil fusefs [--debug] DIRECTORY ** ** This command uses the Fuse Filesystem (FuseFS) to mount a directory |
︙ | ︙ | |||
312 313 314 315 316 317 318 319 320 321 322 323 324 325 | ** appropriate support libraries. ** ** After stopping the "fossil fusefs" command, it might also be necessary ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it ** again. */ void fusefs_cmd(void){ char *zMountPoint; char *azNewArgv[5]; int doDebug = find_option("debug","d",0)!=0; db_find_and_open_repository(0,0); verify_all_options(); blob_init(&fusefs.content, 0, 0); | > | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | ** appropriate support libraries. ** ** After stopping the "fossil fusefs" command, it might also be necessary ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it ** again. */ void fusefs_cmd(void){ #ifdef FOSSIL_HAVE_FUSEFS char *zMountPoint; char *azNewArgv[5]; int doDebug = find_option("debug","d",0)!=0; db_find_and_open_repository(0,0); verify_all_options(); blob_init(&fusefs.content, 0, 0); |
︙ | ︙ | |||
333 334 335 336 337 338 339 | azNewArgv[2] = "-s"; azNewArgv[3] = zMountPoint; azNewArgv[4] = 0; g.localOpen = 0; /* Prevent tags like "current" and "prev" */ fuse_main(4, azNewArgv, &fusefs_methods, NULL); fusefs_reset(); fusefs_clear_path(); | < > > > > | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | azNewArgv[2] = "-s"; azNewArgv[3] = zMountPoint; azNewArgv[4] = 0; g.localOpen = 0; /* Prevent tags like "current" and "prev" */ fuse_main(4, azNewArgv, &fusefs_methods, NULL); fusefs_reset(); fusefs_clear_path(); #else fprintf(stderr, "The FuseFS is not available in this build.\n"); exit(1); #endif /* FOSSIL_HAVE_FUSEFS */ } /* ** Return version numbers for the FUSE header that was used at compile-time ** and/or the FUSE library that was loaded at runtime. */ const char *fusefs_lib_version(void){ #if defined(FOSSIL_HAVE_FUSEFS) && FUSE_MAJOR_VERSION>=3 |
︙ | ︙ |
Changes to src/http_ssl.c.
︙ | ︙ | |||
768 769 770 771 772 773 774 | }else{ assert( sslIsInit==2 ); } } typedef struct SslServerConn { SSL *ssl; /* The SSL codec */ | < < | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | }else{ assert( sslIsInit==2 ); } } typedef struct SslServerConn { SSL *ssl; /* The SSL codec */ int iSocket; /* The socket */ BIO *bio; /* BIO object. Needed for EOF detection. */ } SslServerConn; /* ** Create a new server-side codec. The argument is the socket's file ** descriptor from which the codec reads and writes. The returned ** memory must eventually be passed to ssl_close_server(). */ void *ssl_new_server(int iSocket){ SslServerConn *pServer = fossil_malloc_zero(sizeof(*pServer)); BIO *b = BIO_new_socket(iSocket, 0); pServer->ssl = SSL_new(sslCtx); pServer->iSocket = iSocket; pServer->bio = b; SSL_set_bio(pServer->ssl, b, b); SSL_accept(pServer->ssl); return (void*)pServer; } |
︙ | ︙ | |||
805 806 807 808 809 810 811 | /* ** Return TRUE if there are no more bytes available to be read from ** the client. */ int ssl_eof(void *pServerArg){ SslServerConn *pServer = (SslServerConn*)pServerArg; | | > > > > > > > > > | | | | | < < | < < | < | > > | | | 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 | /* ** Return TRUE if there are no more bytes available to be read from ** the client. */ int ssl_eof(void *pServerArg){ SslServerConn *pServer = (SslServerConn*)pServerArg; return BIO_eof(pServer->bio); } /* ** Read cleartext bytes that have been received from the client and ** decrypted by the SSL server codec. ** ** If the expected payload size unknown, i.e. if the HTTP ** Content-Length: header field has not been parsed, the doLoop ** argument should be 0, or SSL_read() may block and wait for more ** data than is eventually going to arrive (on Windows). On ** non-Windows builds, it has been our experience that the final ** argument must always be true, as discussed at length at: ** ** https://fossil-scm.org/forum/forumpost/2f818850abb72719 */ size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf, int doLoop){ int n; size_t rc = 0; SslServerConn *pServer = (SslServerConn*)pServerArg; if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); } while( nBuf!=rc && BIO_eof(pServer->bio)==0 ){ n = SSL_read(pServer->ssl, zBuf + rc, (int)(nBuf - rc)); if( n>0 ){ rc += n; } if( doLoop==0 || n<=0 ){ break; } } return rc; } /* ** Read a single line of text from the client, up to nBuf-1 bytes. On ** success, writes nBuf-1 bytes to zBuf and NUL-terminates zBuf. ** Returns NULL on an I/O error or at EOF. */ char *ssl_gets(void *pServerArg, char *zBuf, int nBuf){ int n = 0; int i; SslServerConn *pServer = (SslServerConn*)pServerArg; if( BIO_eof(pServer->bio) ) return 0; for(i=0; i<nBuf-1; i++){ n = SSL_read(pServer->ssl, &zBuf[i], 1); if( n<=0 ){ return 0; } if( zBuf[i]=='\n' ) break; } |
︙ | ︙ | |||
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 | }else{ return n; } } #endif /* FOSSIL_ENABLE_SSL */ /* ** zPath is a name that might be a file or directory containing a trust ** store. *pzStore is the name of the trust store to actually use. ** ** If *pzStore is not NULL (meaning no trust store has been found yet) ** and if zPath exists, then set *pzStore to point to zPath. */ static void trust_location_usable(const char *zPath, const char **pzStore){ if( *pzStore!=0 ) return; if( file_isdir(zPath, ExtFILE)>0 ) *pzStore = zPath; } /* ** COMMAND: tls-config* ** COMMAND: ssl-config ** ** Usage: %fossil ssl-config [SUBCOMMAND] [OPTIONS...] [ARGS...] ** | > > | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 | }else{ return n; } } #endif /* FOSSIL_ENABLE_SSL */ #ifdef FOSSIL_ENABLE_SSL /* ** zPath is a name that might be a file or directory containing a trust ** store. *pzStore is the name of the trust store to actually use. ** ** If *pzStore is not NULL (meaning no trust store has been found yet) ** and if zPath exists, then set *pzStore to point to zPath. */ static void trust_location_usable(const char *zPath, const char **pzStore){ if( *pzStore!=0 ) return; if( file_isdir(zPath, ExtFILE)>0 ) *pzStore = zPath; } #endif /* FOSSIL_ENABLE_SSL */ /* ** COMMAND: tls-config* ** COMMAND: ssl-config ** ** Usage: %fossil ssl-config [SUBCOMMAND] [OPTIONS...] [ARGS...] ** |
︙ | ︙ | |||
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 | db_multi_exec( "PRAGMA secure_delete=ON;" "DELETE FROM config WHERE name GLOB 'ssl-*';" ); db_protect_pop(); }else if( strncmp("show",zCmd,nCmd)==0 ){ const char *zName, *zValue; const char *zUsed = 0; /* Trust store location actually used */ size_t nName; Stmt q; int verbose = find_option("verbose","v",0)!=0; verify_all_options(); #if !defined(FOSSIL_ENABLE_SSL) fossil_print("OpenSSL-version: (none)\n"); if( verbose ){ | > > | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 | db_multi_exec( "PRAGMA secure_delete=ON;" "DELETE FROM config WHERE name GLOB 'ssl-*';" ); db_protect_pop(); }else if( strncmp("show",zCmd,nCmd)==0 ){ #if defined(FOSSIL_ENABLE_SSL) const char *zName, *zValue; const char *zUsed = 0; /* Trust store location actually used */ size_t nName; #endif Stmt q; int verbose = find_option("verbose","v",0)!=0; verify_all_options(); #if !defined(FOSSIL_ENABLE_SSL) fossil_print("OpenSSL-version: (none)\n"); if( verbose ){ |
︙ | ︙ |
Changes to src/json.c.
1 2 | #ifdef FOSSIL_ENABLE_JSON /* | | | 1 2 3 4 5 6 7 8 9 10 | #ifdef FOSSIL_ENABLE_JSON /* ** Copyright (c) 2011-2022 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of |
︙ | ︙ | |||
170 171 172 173 174 175 176 | **/ int cson_data_dest_Blob(void * pState, void const * src, unsigned int n){ Blob * b = (Blob*)pState; blob_append( b, (char const *)src, (int)n ) /* will die on OOM */; return 0; } | < < < < < < < < < < < | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | **/ int cson_data_dest_Blob(void * pState, void const * src, unsigned int n){ Blob * b = (Blob*)pState; blob_append( b, (char const *)src, (int)n ) /* will die on OOM */; return 0; } /* ** Convenience wrapper around cson_output() which appends the output ** to pDest. pOpt may be NULL, in which case g.json.outOpt will be used. */ int cson_output_Blob( cson_value const * pVal, Blob * pDest, cson_output_opt const * pOpt ){ return cson_output( pVal, cson_data_dest_Blob, pDest, pOpt ? pOpt : &g.json.outOpt ); |
︙ | ︙ | |||
202 203 204 205 206 207 208 | ** about the parse state when this function returns. ** ** On success a new JSON Object or Array is returned (owned by the ** caller). On error NULL is returned. */ cson_value * cson_parse_Blob( Blob * pSrc, cson_parse_info * pInfo ){ cson_value * root = NULL; | < | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | ** about the parse state when this function returns. ** ** On success a new JSON Object or Array is returned (owned by the ** caller). On error NULL is returned. */ cson_value * cson_parse_Blob( Blob * pSrc, cson_parse_info * pInfo ){ cson_value * root = NULL; cson_parse_string( &root, blob_str(pSrc), blob_size(pSrc), NULL, pInfo ); return root; } /* ** Implements the cson_data_dest_f() interface and outputs the data to ** cgi_append_content(). pState is ignored. **/ |
︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | /* Simulate JSON POST data via input file. Pedantic reminder: error handling does not honor user-supplied g.json.outOpt because outOpt cannot (generically) be configured until after POST-reading is finished. */ FILE * inFile = NULL; char const * jfile = find_option("json-input",NULL,1); if(!jfile || !*jfile){ break; } inFile = (0==strcmp("-",jfile)) ? stdin : fossil_fopen(jfile,"rb"); if(!inFile){ g.json.resultCode = FSL_JSON_E_FILE_OPEN_FAILED; fossil_fatal("Could not open JSON file [%s].",jfile) /* Does not return. */ ; } | > | > > | 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | /* Simulate JSON POST data via input file. Pedantic reminder: error handling does not honor user-supplied g.json.outOpt because outOpt cannot (generically) be configured until after POST-reading is finished. */ FILE * inFile = NULL; char const * jfile = find_option("json-input",NULL,1); Blob json = BLOB_INITIALIZER; if(!jfile || !*jfile){ break; } inFile = (0==strcmp("-",jfile)) ? stdin : fossil_fopen(jfile,"rb"); if(!inFile){ g.json.resultCode = FSL_JSON_E_FILE_OPEN_FAILED; fossil_fatal("Could not open JSON file [%s].",jfile) /* Does not return. */ ; } blob_read_from_channel(&json, inFile, -1); fossil_fclose(inFile); cgi_parse_POST_JSON(&json); blob_reset(&json); break; } /* g.json.reqPayload exists only to simplify some of our access to the request payload. We currently only use this in the context of Object payloads, not Arrays, strings, etc. */ |
︙ | ︙ |
Changes to src/json_wiki.c.
︙ | ︙ | |||
271 272 273 274 275 276 277 | contentFormat = json_wiki_get_content_format_flag(contentFormat); return json_wiki_get_by_name_or_symname( zPageName, zSymName, contentFormat ); } /* ** Implementation of /json/wiki/preview. | < > > > > > > > > > | > | | > > > | > > > > > > > > | > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | contentFormat = json_wiki_get_content_format_flag(contentFormat); return json_wiki_get_by_name_or_symname( zPageName, zSymName, contentFormat ); } /* ** Implementation of /json/wiki/preview. */ static cson_value * json_wiki_preview(){ char const * zContent = NULL; char const * zMime = NULL; cson_string * sContent = NULL; cson_value * pay = NULL; Blob contentOrig = empty_blob; Blob contentHtml = empty_blob; if( !g.perm.WrWiki ){ json_set_err(FSL_JSON_E_DENIED, "Requires 'k' access."); return NULL; } if(g.json.reqPayload.o){ sContent = cson_value_get_string( cson_object_get(g.json.reqPayload.o, "body")); zMime = cson_value_get_cstr(cson_object_get(g.json.reqPayload.o, "mimetype")); }else{ sContent = cson_value_get_string(g.json.reqPayload.v); } if(!sContent) { json_set_err(FSL_JSON_E_MISSING_ARGS, "The 'payload' property must be either a string containing the " "Fossil wiki code to preview or an object with body + mimetype " "properties."); return NULL; } zContent = cson_string_cstr(sContent); blob_append( &contentOrig, zContent, (int)cson_string_length_bytes(sContent) ); zMime = wiki_filter_mimetypes(zMime); if( 0==fossil_strcmp(zMime, "text/x-markdown") ){ markdown_to_html(&contentOrig, 0, &contentHtml); }else if( 0==fossil_strcmp(zMime, "text/plain") ){ blob_append(&contentHtml, "<pre class='textPlain'>", -1); blob_append(&contentHtml, blob_str(&contentOrig), blob_size(&contentOrig)); blob_append(&contentHtml, "</pre>", -1); }else{ wiki_convert( &contentOrig, &contentHtml, 0 ); } blob_reset( &contentOrig ); pay = cson_value_new_string( blob_str(&contentHtml), (unsigned int)blob_size(&contentHtml)); blob_reset( &contentHtml ); return pay; } |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | /* ** COMMAND: http* ** ** Usage: %fossil http ?REPOSITORY? ?OPTIONS? ** ** Handle a single HTTP request appearing on stdin. The resulting webpage ** is delivered on stdout. This method is used to launch an HTTP request | | | < < < < < < < < < | | | | > > | > | | | | > | | > | | 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | /* ** COMMAND: http* ** ** Usage: %fossil http ?REPOSITORY? ?OPTIONS? ** ** Handle a single HTTP request appearing on stdin. The resulting webpage ** is delivered on stdout. This method is used to launch an HTTP request ** handler from inetd, for example. The REPOSITORY argument is the name of ** the repository. ** ** If REPOSITORY is a directory that contains one or more repositories, ** either directly in REPOSITORY itself or in subdirectories, and ** with names of the form "*.fossil" then a prefix of the URL pathname ** selects from among the various repositories. If the pathname does ** not select a valid repository and the --notfound option is available, ** then the server redirects (HTTP code 302) to the URL of --notfound. ** When REPOSITORY is a directory, the pathname must contain only ** alphanumerics, "_", "/", "-" and "." and no "-" may occur after a "/" ** and every "." must be surrounded on both sides by alphanumerics or else ** a 404 error is returned. Static content files in the directory are ** returned if they match comma-separate GLOB pattern specified by --files ** and do not match "*.fossil*" and have a well-known suffix. ** ** Options: ** --acme Deliver files from the ".well-known" subdirectory ** --baseurl URL base URL (useful with reverse proxies) ** --cert FILE Use TLS (HTTPS) encryption with the certificate (the ** fullchain.pem) taken from FILE. ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias N Treat URIs of the form /doc/N/... as if they were ** /doc/ckout/... ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOB Comma-separate glob patterns for static file to serve ** --host NAME DNS Hostname of the server ** --https The HTTP request originated from https but has already ** been decoded by a reverse proxy. Hence, URLs created ** by Fossil should use "https:" rather than "http:". ** --in FILE Take input from FILE instead of standard input ** --ipaddr ADDR Assume the request comes from the given IP address ** --jsmode MODE Determine how JavaScript is delivered with pages. ** Mode can be one of: ** inline All JavaScript is inserted inline at ** one or more points in the HTML file. ** separate Separate HTTP requests are made for ** each JavaScript file. ** bundled Groups JavaScript files into one or ** more bundled requests which ** concatenate scripts together. ** Depending on the needs of any given page, inline ** and bundled modes might result in a single ** amalgamated script or several, but both approaches ** result in fewer HTTP requests than the separate mode. ** --localauth Connections from localhost are given "setup" ** privileges without having to log in. ** --mainmenu FILE Override the mainmenu config setting with the contents ** of the given file. ** --nocompress Do not compress HTTP replies ** --nodelay Omit backoffice processing if it would delay ** process exit ** --nojail Drop root privilege but do not enter the chroot jail ** --nossl Do not do http: to https: redirects, regardless of ** the redirect-to-https setting. ** --notfound URL Use URL as the "HTTP 404, object not found" page. ** --out FILE Write the HTTP reply to FILE instead of to ** standard output ** --pkey FILE Read the private key used for TLS from FILE. ** --repolist If REPOSITORY is directory, URL "/" lists all repos ** --scgi Interpret input as SCGI rather than HTTP ** --skin LABEL Use override skin LABEL ** --th-trace Trace TH1 execution (for debugging purposes) ** --usepidkey Use saved encryption key from parent process. This is ** only necessary when using SEE on Windows. ** ** See also: [[cgi]], [[server]], [[winsrv]] */ void cmd_http(void){ const char *zIpAddr = 0; |
︙ | ︙ | |||
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 | zInFile = find_option("in",0,1); if( zInFile ){ backoffice_disable(); g.httpIn = fossil_fopen(zInFile, "rb"); if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile); }else{ g.httpIn = stdin; } zOutFile = find_option("out",0,1); if( zOutFile ){ g.httpOut = fossil_fopen(zOutFile, "wb"); if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile); }else{ g.httpOut = stdout; } zIpAddr = find_option("ipaddr",0,1); useSCGI = find_option("scgi", 0, 0)!=0; zAltBase = find_option("baseurl", 0, 1); if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); if( zAltBase ) set_base_url(zAltBase); if( find_option("https",0,0)!=0 ){ | > > > > > > | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 | zInFile = find_option("in",0,1); if( zInFile ){ backoffice_disable(); g.httpIn = fossil_fopen(zInFile, "rb"); if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile); }else{ g.httpIn = stdin; #if defined(_WIN32) _setmode(_fileno(stdin), _O_BINARY); #endif } zOutFile = find_option("out",0,1); if( zOutFile ){ g.httpOut = fossil_fopen(zOutFile, "wb"); if( g.httpOut==0 ) fossil_fatal("cannot open \"%s\" for writing", zOutFile); }else{ g.httpOut = stdout; #if defined(_WIN32) _setmode(_fileno(stdout), _O_BINARY); #endif } zIpAddr = find_option("ipaddr",0,1); useSCGI = find_option("scgi", 0, 0)!=0; zAltBase = find_option("baseurl", 0, 1); if( find_option("nodelay",0,0)!=0 ) backoffice_no_delay(); if( zAltBase ) set_base_url(zAltBase); if( find_option("https",0,0)!=0 ){ |
︙ | ︙ |
Changes to src/repolist.c.
︙ | ︙ | |||
172 173 174 175 176 177 178 | while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); int nName = (int)strlen(zName); char *zUrl; char *zAge; char *zFull; RepoInfo x; | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); int nName = (int)strlen(zName); char *zUrl; char *zAge; char *zFull; RepoInfo x; sqlite3_int64 iAge; if( nName<7 ) continue; zUrl = sqlite3_mprintf("%.*s", nName-7, zName); if( zName[0]=='/' #ifdef _WIN32 || sqlite3_strglob("[a-zA-Z]:/*", zName)==0 #endif ){ |
︙ | ︙ | |||
203 204 205 206 207 208 209 | continue; } if( x.isRepolistSkin==2 && !allRepo ){ /* Repositories with repolist-skin==2 are omitted from directory ** scan lists, but included in "fossil all ui" lists */ continue; } | > | > | > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | continue; } if( x.isRepolistSkin==2 && !allRepo ){ /* Repositories with repolist-skin==2 are omitted from directory ** scan lists, but included in "fossil all ui" lists */ continue; } if( rNow <= x.rMTime ){ x.rMTime = rNow; }else if( x.rMTime<0.0 ){ x.rMTime = rNow; } iAge = (int)(rNow - x.rMTime)*86400; zAge = human_readable_age(rNow - x.rMTime); if( x.rMTime==0.0 ){ /* This repository has no entry in the "event" table. ** Its age will still be maximum, so data-sortkey will work. */ zAge = mprintf("unknown"); } blob_append_sql(&html, "<tr><td valign='top'>"); if( sqlite3_strglob("*.fossil", zName)!=0 ){ /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands ** do not work for repositories whose names do not end in ".fossil". ** So do not hyperlink those cases. */ blob_append_sql(&html,"%h",zName); } else if( sqlite3_strglob("*/.*", zName)==0 ){ |
︙ | ︙ |
Changes to src/stat.c.
︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 | db_prepare(&q, "SELECT szCmpr FROM artstat ORDER BY 1 DESC"); r = 0; n = 0; while( db_step(&q)==SQLITE_ROW ){ r += db_column_int(&q, 0); if( n50pct==0 && r>=sumCmpr/2 ) n50pct = n; | | | | | > > > | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | db_prepare(&q, "SELECT szCmpr FROM artstat ORDER BY 1 DESC"); r = 0; n = 0; while( db_step(&q)==SQLITE_ROW ){ r += db_column_int(&q, 0); if( n50pct==0 && r>=sumCmpr/2 ) n50pct = n; if( n==(nTotal+99)/100 ) sz1pct = (sqlite3_int64)r; if( n==(nTotal+9)/10 ) sz10pct = (sqlite3_int64)r; if( n==(nTotal+4)/5 ) sz25pct = (sqlite3_int64)r; if( n==(nTotal+1)/2 ){ sz50pct = (sqlite3_int64)r; medCmpr = db_column_int(&q,0); } n++; } db_finalize(&q); @ <h1>Overall Artifact Size Statistics:</h1> @ <table class="label-value"> @ <tr><th>Number of artifacts:</th><td>%,d(nTotal)</td></tr> |
︙ | ︙ |
Changes to src/tar.c.
︙ | ︙ | |||
494 495 496 497 498 499 500 | blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ int flg, eflg = 0; | | | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ int flg, eflg = 0; mTime = (unsigned)((pManifest->rDate - 2440587.5)*86400.0); if( pTar ) tar_begin(mTime); flg = db_get_manifest_setting(); if( flg ){ /* eflg is the effective flags, taking include/exclude into account */ if( (pInclude==0 || glob_match(pInclude, "manifest")) && !glob_match(pExclude, "manifest") && (flg & MFESTFLG_RAW) ){ |
︙ | ︙ |
Changes to src/winhttp.c.
︙ | ︙ | |||
361 362 363 364 365 366 367 | #ifdef FOSSIL_ENABLE_SSL sslConn = ssl_new_server(p->s); #endif } while( amt<szHdr ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL | | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | #ifdef FOSSIL_ENABLE_SSL sslConn = ssl_new_server(p->s); #endif } while( amt<szHdr ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL got = ssl_read_server(sslConn, &zBuf[amt], szHdr-1-amt, 0); #endif }else{ got = recv(p->s, &zBuf[amt], szHdr-1-amt, 0); if( got==SOCKET_ERROR ) goto end_request; } if( got==0 ){ wanted = 0; break; } amt += got; |
︙ | ︙ | |||
392 393 394 395 396 397 398 | if( amt>=szHdr ) goto end_request; out = fossil_fopen(zRequestFName, "wb"); if( out==0 ) goto end_request; fwrite(zBuf, 1, amt, out); while( wanted>0 ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL | | | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | if( amt>=szHdr ) goto end_request; out = fossil_fopen(zRequestFName, "wb"); if( out==0 ) goto end_request; fwrite(zBuf, 1, amt, out); while( wanted>0 ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL got = ssl_read_server(sslConn, zBuf, min(wanted, sizeof(zBuf)), 1); #endif }else{ got = recv(p->s, zBuf, sizeof(zBuf), 0); if( got==SOCKET_ERROR ) goto end_request; } if( got>0 ){ fwrite(zBuf, 1, got, out); |
︙ | ︙ | |||
435 436 437 438 439 440 441 442 443 444 445 446 447 448 | "\"%s\" http -args \"%s\"%s%s", g.nameOfExe, zCmdFName, g.httpUseSSL ? "" : " --nossl", p->zOptions ); in = fossil_fopen(zReplyFName, "w+b"); fflush(out); fflush(aux); fossil_system(zCmd); if( in ){ while( (got = fread(zBuf, 1, sizeof(zBuf), in))>0 ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL ssl_write_server(sslConn, zBuf, got); #endif | > > > | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | "\"%s\" http -args \"%s\"%s%s", g.nameOfExe, zCmdFName, g.httpUseSSL ? "" : " --nossl", p->zOptions ); in = fossil_fopen(zReplyFName, "w+b"); fflush(out); fflush(aux); if( g.fHttpTrace ){ fossil_print("%s\n", zCmd); } fossil_system(zCmd); if( in ){ while( (got = fread(zBuf, 1, sizeof(zBuf), in))>0 ){ if( sslConn ){ #ifdef FOSSIL_ENABLE_SSL ssl_write_server(sslConn, zBuf, got); #endif |
︙ | ︙ | |||
463 464 465 466 467 468 469 | #endif } if( shutdown(p->s,1)==0 ) shutdown(p->s,0); closesocket(p->s); /* Make multiple attempts to delete the temporary files. Sometimes AV ** software keeps the files open for a few seconds, preventing the file ** from being deleted on the first try. */ | > | | | > | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | #endif } if( shutdown(p->s,1)==0 ) shutdown(p->s,0); closesocket(p->s); /* Make multiple attempts to delete the temporary files. Sometimes AV ** software keeps the files open for a few seconds, preventing the file ** from being deleted on the first try. */ if( !g.fHttpTrace ){ for(i=1; i<=10 && file_delete(zRequestFName); i++){ Sleep(1000*i); } for(i=1; i<=10 && file_delete(zCmdFName); i++){ Sleep(1000*i); } for(i=1; i<=10 && file_delete(zReplyFName); i++){ Sleep(1000*i); } } fossil_free(p); } /* ** Process a single incoming SCGI request. */ static void win32_scgi_request(void *pAppData){ |
︙ | ︙ | |||
650 651 652 653 654 655 656 | fossil_fatal("unable to open listening socket on any" " port in the range %d..%d", mnPort, mxPort); } } if( !GetTempPathW(MAX_PATH, zTmpPath) ){ fossil_panic("unable to get path to the temporary directory."); } | > > > | | > | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | fossil_fatal("unable to open listening socket on any" " port in the range %d..%d", mnPort, mxPort); } } if( !GetTempPathW(MAX_PATH, zTmpPath) ){ fossil_panic("unable to get path to the temporary directory."); } if( g.fHttpTrace ){ zTempPrefix = mprintf("httptrace"); }else{ zTempPrefix = mprintf("%sfossil_server_P%d", fossil_unicode_to_utf8(zTmpPath), iPort); } fossil_print("Temporary files: %s*\n", zTempPrefix); fossil_print("Listening for %s requests on TCP port %d\n", (flags&HTTP_SERVER_SCGI)!=0 ? "SCGI" : g.httpUseSSL ? "TLS-encrypted HTTPS" : "HTTP", iPort); if( zBrowser ){ zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); fossil_print("Launch webbrowser: %s\n", zBrowser); |
︙ | ︙ |
Changes to src/zip.c.
︙ | ︙ | |||
234 235 236 237 238 239 240 | /* ** Set the date and time from a julian day number. */ void zip_set_timedate(double rDate){ char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate); zip_set_timedate_from_str(zDate); fossil_free(zDate); | | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | /* ** Set the date and time from a julian day number. */ void zip_set_timedate(double rDate){ char *zDate = db_text(0, "SELECT datetime(%.17g)", rDate); zip_set_timedate_from_str(zDate); fossil_free(zDate); unixTime = (int)((rDate - 2440587.5)*86400.0); } /* ** Append a single file to a growing ZIP archive. ** ** pFile is the file to be appended. zName is the name ** that the file should be saved as. |
︙ | ︙ |
Changes to tools/makemake.tcl.
︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | writeln "\t+translate\$E \$** > \$@\n" } writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E " foreach s [lsort $src] { writeln -nonewline "${s}_.c:$s.h " } writeln "\$(SRCDIR_extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR_extsrc)\\cson_amalgamation.h" writeln "\t@copy /Y nul: headers" close $output_file # # End of the win/Makefile.dmc output ############################################################################## | > > > | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 | writeln "\t+translate\$E \$** > \$@\n" } writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E " foreach s [lsort $src] { writeln -nonewline "${s}_.c:$s.h " } foreach s [lsort $src_ext] { writeln -nonewline "\$(SRCDIR_extsrc)\\${s}.c:$s.h " } writeln "\$(SRCDIR_extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR_extsrc)\\cson_amalgamation.h" writeln "\t@copy /Y nul: headers" close $output_file # # End of the win/Makefile.dmc output ############################################################################## |
︙ | ︙ | |||
1569 1570 1571 1572 1573 1574 1575 | SSLDIR = $(B)\compat\openssl SSLINCDIR = $(SSLDIR)\include !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR) !else SSLLIBDIR = $(SSLDIR) !endif | < | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 | SSLDIR = $(B)\compat\openssl SSLINCDIR = $(SSLDIR)\include !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR) !else SSLLIBDIR = $(SSLDIR) !endif SSLLIB = libssl.lib libcrypto.lib user32.lib gdi32.lib crypt32.lib !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" !message Using 'x64' platform for OpenSSL... SSLCONFIG = VC-WIN64A no-asm no-ssl3 no-weak-ssl-ciphers !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLCONFIG = $(SSLCONFIG) shared !else |
︙ | ︙ | |||
1626 1627 1628 1629 1630 1631 1632 | INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" !endif | | > > > > | | > > > > > > > | 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 | INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" !endif CFLAGS = /nologo /W2 /WX LDFLAGS = CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS CFLAGS = $(CFLAGS) /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_NONSTDC_NO_WARNINGS !if $(FOSSIL_DYNAMIC_BUILD)!=0 LDFLAGS = $(LDFLAGS) /MANIFEST !else LDFLAGS = $(LDFLAGS) /NODEFAULTLIB:msvcrt /MANIFEST:NO !endif !if $(FOSSIL_ENABLE_WINXP)!=0 XPCFLAGS = $(XPCFLAGS) /D_WIN32_WINNT=0x0501 /D_USING_V110_SDK71_=1 CFLAGS = $(CFLAGS) $(XPCFLAGS) # # NOTE: For regular builds, /OSVERSION defaults to the /SUBSYSTEM version and # explicit initialization is redundant, but is required for post-built edits. # !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" XPLDFLAGS = $(XPLDFLAGS) /OSVERSION:5.02 /SUBSYSTEM:CONSOLE,5.02 !else XPLDFLAGS = $(XPLDFLAGS) /OSVERSION:5.01 /SUBSYSTEM:CONSOLE,5.01 !endif LDFLAGS = $(LDFLAGS) $(XPLDFLAGS) # # NOTE: Only XPCFLAGS is forwarded to the OpenSSL configuration, and XPLDFLAGS # is applied in a separate post-build step, see below for more information. # !if $(FOSSIL_ENABLE_SSL)!=0 SSLCONFIG = $(SSLCONFIG) $(XPCFLAGS) !endif !endif !if $(FOSSIL_DYNAMIC_BUILD)!=0 !if $(DEBUG)!=0 CRTFLAGS = /MDd !else CRTFLAGS = /MD |
︙ | ︙ | |||
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 | foreach s [lsort $src] { if {$i > 0} { writeln " \\" writeln -nonewline " " } writeln -nonewline "\"\$(OX)\\${s}_.c\""; incr i } writeln "\n" writeln -nonewline "EXTRA_FILES = " set i 0 foreach s [lsort $extra_files] { if {$i > 0} { writeln " \\" writeln -nonewline " " | > > > > > | 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 | foreach s [lsort $src] { if {$i > 0} { writeln " \\" writeln -nonewline " " } writeln -nonewline "\"\$(OX)\\${s}_.c\""; incr i } foreach s [lsort $src_ext] { writeln " \\" writeln -nonewline " " writeln -nonewline "\"\$(SRCDIR_extsrc)\\${s}.c\""; incr i } writeln "\n" writeln -nonewline "EXTRA_FILES = " set i 0 foreach s [lsort $extra_files] { if {$i > 0} { writeln " \\" writeln -nonewline " " |
︙ | ︙ | |||
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | clean-zlib: @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc clean && popd !if $(FOSSIL_ENABLE_SSL)!=0 openssl: @echo Building OpenSSL from "$(SSLDIR)"... !ifdef PERLDIR @pushd "$(SSLDIR)" && "$(PERLDIR)\$(PERL)" Configure $(SSLCONFIG) && popd !else @pushd "$(SSLDIR)" && "$(PERL)" Configure $(SSLCONFIG) && popd !endif | > > > > | > > > > > > > > > > > > > > > > | < > > > | > | 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 | clean-zlib: @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc clean && popd !if $(FOSSIL_ENABLE_SSL)!=0 openssl: @echo Building OpenSSL from "$(SSLDIR)"... !if $(FOSSIL_ENABLE_WINXP)!=0 @echo Passing XPCFLAGS = [ $(XPCFLAGS) ] to the OpenSSL configuration... !endif !ifdef PERLDIR @pushd "$(SSLDIR)" && "$(PERLDIR)\$(PERL)" Configure $(SSLCONFIG) && popd !else @pushd "$(SSLDIR)" && "$(PERL)" Configure $(SSLCONFIG) && popd !endif @pushd "$(SSLDIR)" && $(MAKE) && popd !if $(FOSSIL_ENABLE_WINXP)!=0 && $(FOSSIL_DYNAMIC_BUILD)!=0 # # NOTE: Appending custom linker flags to the OpenSSL default linker flags is # somewhat difficult, as summarized in this Fossil Forum post: # # https://fossil-scm.org/forum/forumpost/a9a2d6af28b # # Therefore the custom linker flags required for Windows XP dynamic builds are # applied in a separate post-build step. # # If the build stops here, or if the custom linker flags are outside the scope # of `editbin` or `link /EDIT` (i.e. additional libraries), consider tweaking # the OpenSSL makefile by hand. # # Also note that this step changes the subsystem for the OpenSSL DLLs from # WINDOWS to CONSOLE, but which has no effect on DLLs. # @echo Applying XPLDFLAGS = [ $(XPLDFLAGS) ] to the OpenSSL DLLs... @for /F "usebackq delims=" %F in (`dir /A:-D/B "$(SSLDIR)\*.dll" 2^>nul`) <<<NEXT_LINE>>> do @( <<<NEXT_LINE>>> echo %F & <<<NEXT_LINE>>> link /EDIT /NOLOGO $(XPLDFLAGS) "$(SSLDIR)\%F" || exit 1 <<<NEXT_LINE>>> ) !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif !if $(FOSSIL_BUILD_ZLIB)!=0 |
︙ | ︙ | |||
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 | foreach s [lsort $src] { if {$i > 0} { writeln " \\" writeln -nonewline "\t\t\t" } writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i } writeln " \\\n\t\t\t\"\$(SRCDIR_extsrc)\\sqlite3.h\" \\" writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\" writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\" writeln "\t\t\t\"\$(SRCDIR_extsrc)\\cson_amalgamation.h\"" writeln "\t@copy /Y nul: $@" | > > > > > | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | foreach s [lsort $src] { if {$i > 0} { writeln " \\" writeln -nonewline "\t\t\t" } writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i } foreach s [lsort $src_ext] { writeln " \\" writeln -nonewline "\t\t\t" writeln -nonewline "\"\$(SRCDIR_extsrc)\\${s}.c\":\"\$(OX)\\$s.h\""; incr i } writeln " \\\n\t\t\t\"\$(SRCDIR_extsrc)\\sqlite3.h\" \\" writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\" writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\" writeln "\t\t\t\"\$(SRCDIR_extsrc)\\cson_amalgamation.h\"" writeln "\t@copy /Y nul: $@" |
︙ | ︙ |
Changes to tools/mkversion.c.
︙ | ︙ | |||
86 87 88 89 90 91 92 | int main(int argc, char *argv[]){ FILE *m,*u,*v; char *z; #if defined(__DMC__) /* e.g. 0x857 */ int i = 0; #endif | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | int main(int argc, char *argv[]){ FILE *m,*u,*v; char *z; #if defined(__DMC__) /* e.g. 0x857 */ int i = 0; #endif int j = 0, x = 0, d = 0, p = 0; size_t n; int vn[3]; char b[1000]; char vx[1000]; if( argc!=4 ){ fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]); exit(1); |
︙ | ︙ | |||
198 199 200 201 202 203 204 205 206 | i = (__DMC__ & 0x00F); /* revision */ printf("#define COMPILER_VERSION \"%d.%d.%d\"\n", d, x, i); #elif defined(__POCC__) /* e.g. 700 */ d = (__POCC__ / 100); /* major */ x = (__POCC__ % 100); /* minor */ printf("#define COMPILER_VERSION \"%d.%02d\"\n", d, x); #elif defined(_MSC_VER) /* e.g. 1800 */ d = (_MSC_VER / 100); /* major */ x = (_MSC_VER % 100); /* minor */ | > > | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | i = (__DMC__ & 0x00F); /* revision */ printf("#define COMPILER_VERSION \"%d.%d.%d\"\n", d, x, i); #elif defined(__POCC__) /* e.g. 700 */ d = (__POCC__ / 100); /* major */ x = (__POCC__ % 100); /* minor */ printf("#define COMPILER_VERSION \"%d.%02d\"\n", d, x); #elif defined(_MSC_VER) /* e.g. 1800 */ /* _MSC_FULL_VER also defined, e.g. 193030709 */ d = (_MSC_VER / 100); /* major */ x = (_MSC_VER % 100); /* minor */ p = (_MSC_FULL_VER % 100000); /* build (patch) */ printf("#define COMPILER_VERSION \"%d.%02d.%05d\"\n", d, x, p); #endif return 0; } |
Changes to win/Makefile.dmc.
︙ | ︙ | |||
1005 1006 1007 1008 1009 1010 1011 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h | | | 1005 1006 1007 1008 1009 1010 1011 1012 1013 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR_extsrc)\pikchr.c:pikchr.h $(SRCDIR_extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR_extsrc)\cson_amalgamation.h @copy /Y nul: headers |
Changes to win/Makefile.msc.
︙ | ︙ | |||
114 115 116 117 118 119 120 | SSLDIR = $(B)\compat\openssl SSLINCDIR = $(SSLDIR)\include !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR) !else SSLLIBDIR = $(SSLDIR) !endif | < | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | SSLDIR = $(B)\compat\openssl SSLINCDIR = $(SSLDIR)\include !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR) !else SSLLIBDIR = $(SSLDIR) !endif SSLLIB = libssl.lib libcrypto.lib user32.lib gdi32.lib crypt32.lib !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" !message Using 'x64' platform for OpenSSL... SSLCONFIG = VC-WIN64A no-asm no-ssl3 no-weak-ssl-ciphers !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLCONFIG = $(SSLCONFIG) shared !else |
︙ | ︙ | |||
171 172 173 174 175 176 177 | INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" !endif | | > > > > | | > > > > > > > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" !endif CFLAGS = /nologo /W2 /WX LDFLAGS = CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS CFLAGS = $(CFLAGS) /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_NONSTDC_NO_WARNINGS !if $(FOSSIL_DYNAMIC_BUILD)!=0 LDFLAGS = $(LDFLAGS) /MANIFEST !else LDFLAGS = $(LDFLAGS) /NODEFAULTLIB:msvcrt /MANIFEST:NO !endif !if $(FOSSIL_ENABLE_WINXP)!=0 XPCFLAGS = $(XPCFLAGS) /D_WIN32_WINNT=0x0501 /D_USING_V110_SDK71_=1 CFLAGS = $(CFLAGS) $(XPCFLAGS) # # NOTE: For regular builds, /OSVERSION defaults to the /SUBSYSTEM version and # explicit initialization is redundant, but is required for post-built edits. # !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" XPLDFLAGS = $(XPLDFLAGS) /OSVERSION:5.02 /SUBSYSTEM:CONSOLE,5.02 !else XPLDFLAGS = $(XPLDFLAGS) /OSVERSION:5.01 /SUBSYSTEM:CONSOLE,5.01 !endif LDFLAGS = $(LDFLAGS) $(XPLDFLAGS) # # NOTE: Only XPCFLAGS is forwarded to the OpenSSL configuration, and XPLDFLAGS # is applied in a separate post-build step, see below for more information. # !if $(FOSSIL_ENABLE_SSL)!=0 SSLCONFIG = $(SSLCONFIG) $(XPCFLAGS) !endif !endif !if $(FOSSIL_DYNAMIC_BUILD)!=0 !if $(DEBUG)!=0 CRTFLAGS = /MDd !else CRTFLAGS = /MD |
︙ | ︙ | |||
488 489 490 491 492 493 494 | "$(OX)\vfile_.c" \ "$(OX)\wiki_.c" \ "$(OX)\wikiformat_.c" \ "$(OX)\winfile_.c" \ "$(OX)\winhttp_.c" \ "$(OX)\xfer_.c" \ "$(OX)\xfersetup_.c" \ | | > | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | "$(OX)\vfile_.c" \ "$(OX)\wiki_.c" \ "$(OX)\wikiformat_.c" \ "$(OX)\winfile_.c" \ "$(OX)\winhttp_.c" \ "$(OX)\xfer_.c" \ "$(OX)\xfersetup_.c" \ "$(OX)\zip_.c" \ "$(SRCDIR_extsrc)\pikchr.c" EXTRA_FILES = "$(SRCDIR)\..\skins\ardoise\css.txt" \ "$(SRCDIR)\..\skins\ardoise\details.txt" \ "$(SRCDIR)\..\skins\ardoise\footer.txt" \ "$(SRCDIR)\..\skins\ardoise\header.txt" \ "$(SRCDIR)\..\skins\black_and_white\css.txt" \ "$(SRCDIR)\..\skins\black_and_white\details.txt" \ |
︙ | ︙ | |||
792 793 794 795 796 797 798 799 800 801 802 803 | clean-zlib: @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc clean && popd !if $(FOSSIL_ENABLE_SSL)!=0 openssl: @echo Building OpenSSL from "$(SSLDIR)"... !ifdef PERLDIR @pushd "$(SSLDIR)" && "$(PERLDIR)\$(PERL)" Configure $(SSLCONFIG) && popd !else @pushd "$(SSLDIR)" && "$(PERL)" Configure $(SSLCONFIG) && popd !endif | > > > > | > > > > > > > > > > > > > > > > | > > | | > | 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | clean-zlib: @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc clean && popd !if $(FOSSIL_ENABLE_SSL)!=0 openssl: @echo Building OpenSSL from "$(SSLDIR)"... !if $(FOSSIL_ENABLE_WINXP)!=0 @echo Passing XPCFLAGS = [ $(XPCFLAGS) ] to the OpenSSL configuration... !endif !ifdef PERLDIR @pushd "$(SSLDIR)" && "$(PERLDIR)\$(PERL)" Configure $(SSLCONFIG) && popd !else @pushd "$(SSLDIR)" && "$(PERL)" Configure $(SSLCONFIG) && popd !endif @pushd "$(SSLDIR)" && $(MAKE) && popd !if $(FOSSIL_ENABLE_WINXP)!=0 && $(FOSSIL_DYNAMIC_BUILD)!=0 # # NOTE: Appending custom linker flags to the OpenSSL default linker flags is # somewhat difficult, as summarized in this Fossil Forum post: # # https://fossil-scm.org/forum/forumpost/a9a2d6af28b # # Therefore the custom linker flags required for Windows XP dynamic builds are # applied in a separate post-build step. # # If the build stops here, or if the custom linker flags are outside the scope # of `editbin` or `link /EDIT` (i.e. additional libraries), consider tweaking # the OpenSSL makefile by hand. # # Also note that this step changes the subsystem for the OpenSSL DLLs from # WINDOWS to CONSOLE, but which has no effect on DLLs. # @echo Applying XPLDFLAGS = [ $(XPLDFLAGS) ] to the OpenSSL DLLs... @for /F "usebackq delims=" %F in (`dir /A:-D/B "$(SSLDIR)\*.dll" 2^>nul`) \ do @( \ echo %F & \ link /EDIT /NOLOGO $(XPLDFLAGS) "$(SSLDIR)\%F" || exit 1 \ ) !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif !if $(FOSSIL_BUILD_ZLIB)!=0 |
︙ | ︙ | |||
2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 | "$(OX)\wiki_.c":"$(OX)\wiki.h" \ "$(OX)\wikiformat_.c":"$(OX)\wikiformat.h" \ "$(OX)\winfile_.c":"$(OX)\winfile.h" \ "$(OX)\winhttp_.c":"$(OX)\winhttp.h" \ "$(OX)\xfer_.c":"$(OX)\xfer.h" \ "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \ "$(OX)\zip_.c":"$(OX)\zip.h" \ "$(SRCDIR_extsrc)\sqlite3.h" \ "$(SRCDIR)\th.h" \ "$(OX)\VERSION.h" \ "$(SRCDIR_extsrc)\cson_amalgamation.h" @copy /Y nul: $@ | > | 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 | "$(OX)\wiki_.c":"$(OX)\wiki.h" \ "$(OX)\wikiformat_.c":"$(OX)\wikiformat.h" \ "$(OX)\winfile_.c":"$(OX)\winfile.h" \ "$(OX)\winhttp_.c":"$(OX)\winhttp.h" \ "$(OX)\xfer_.c":"$(OX)\xfer.h" \ "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \ "$(OX)\zip_.c":"$(OX)\zip.h" \ "$(SRCDIR_extsrc)\pikchr.c":"$(OX)\pikchr.h" \ "$(SRCDIR_extsrc)\sqlite3.h" \ "$(SRCDIR)\th.h" \ "$(OX)\VERSION.h" \ "$(SRCDIR_extsrc)\cson_amalgamation.h" @copy /Y nul: $@ |
Changes to www/changes.wiki.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | * For "fossil pull" with the --from-parent-project option, if not URL is specified used the last URL specified for the --from-parent-project. * Add options --project-name and --project-desc to the "[/help?cmd=init|fossil init]" command. * Query parameter "year=YYYY" is now accepted by [/help?cmd=/timeline|/timeline]. * Add the "--as FILENAME" option to the "[/help?cmd=chat|fossil chat send]" command. * Submenu of the [/help?cmd=/rptview|/rptview] and [/help?cmd=/wiki|/wiki] pages may be [branch/rptview-submenu-paralink|extended with auxiliary hyperlinks]. <h2 id='v2_17'>Changes for version 2.17 (2021-10-09)</h2> * Major improvements to the "diff" subsystem, including: <ul> | > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | * For "fossil pull" with the --from-parent-project option, if not URL is specified used the last URL specified for the --from-parent-project. * Add options --project-name and --project-desc to the "[/help?cmd=init|fossil init]" command. * Query parameter "year=YYYY" is now accepted by [/help?cmd=/timeline|/timeline]. * Add the "--as FILENAME" option to the "[/help?cmd=chat|fossil chat send]" command. * The [/help?cmd=/ext|/ext page] generates the SERVER_SOFTWARE environment variable for clients. * The [/help?cmd=tar|tar] and [/help?cmd=zip|zip commands] no longer sterilize the manifest file. * Submenu of the [/help?cmd=/rptview|/rptview] and [/help?cmd=/wiki|/wiki] pages may be [branch/rptview-submenu-paralink|extended with auxiliary hyperlinks]. <h2 id='v2_17'>Changes for version 2.17 (2021-10-09)</h2> * Major improvements to the "diff" subsystem, including: <ul> |
︙ | ︙ |
Changes to www/defcsp.md.
︙ | ︙ | |||
28 29 30 31 32 33 34 | default-src 'self' data:; script-src 'self' 'nonce-$nonce'; style-src 'self' 'unsafe-inline'; img-src * data:; </pre> The default is recommended for most installations. However, | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | default-src 'self' data:; script-src 'self' 'nonce-$nonce'; style-src 'self' 'unsafe-inline'; img-src * data:; </pre> The default is recommended for most installations. However, the site administrators can overwrite this default CSP using the [default-csp setting](/help?cmd=default-csp). For example, CSP restrictions can be completely disabled by setting the default-csp to: <pre> default-src *; </pre> |
︙ | ︙ |
Changes to www/env-opts.md.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | `--case-sensitive BOOL`: Override the `case-sensitive` setting, which can override the native preferences of the platform for case sensitive file names: insensitive on Windows, sensitive on Unix. There are probably odd interactions possible if you mix case sensitive and case insensitive file systems on any single platform. This option or the global setting should be used to force the case sensitivity to the most sensible condition. `--chdir DIRECTORY`: Change to the named directory before processing any commands. `--comfmtflags NUMBER`: Specify flags that control how check-in comments and certain other text outputs are formatted for display. The flags are | > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | `--case-sensitive BOOL`: Override the `case-sensitive` setting, which can override the native preferences of the platform for case sensitive file names: insensitive on Windows, sensitive on Unix. There are probably odd interactions possible if you mix case sensitive and case insensitive file systems on any single platform. This option or the global setting should be used to force the case sensitivity to the most sensible condition. `--cgitrace`: Active CGI tracing. `--chdir DIRECTORY`: Change to the named directory before processing any commands. `--comfmtflags NUMBER`: Specify flags that control how check-in comments and certain other text outputs are formatted for display. The flags are |
︙ | ︙ | |||
309 310 311 312 313 314 315 | environment. See the comment above the implementation of [`json_getenv`][json.c] for some further discussion. [json.c]: /artifact/6df1d80dece8968b?ln=277,290 | < < < < < < | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | environment. See the comment above the implementation of [`json_getenv`][json.c] for some further discussion. [json.c]: /artifact/6df1d80dece8968b?ln=277,290 ### Comment Editor The editor used to edit a check-in or stash comment is named by the local or global setting `editor`. If neither is set, then the environment variables `VISUAL`, and `EDITOR` are checked in that order. On Windows, if no editor is named, then Notepad is used. Note that the |
︙ | ︙ |
Changes to www/json-api/api-wiki.md.
︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | **Request options** (via GET or `POST.payload` object): - `name=string` specifies the page name. - `content=string` is the body text.\ Content is required for save (unless `createIfNotExists` is true *and* the page does not exist), optional for create. It *may* be an empty string. - Save (not create) supports a `createIfNotExists` boolean option which makes it a functional superset of the create/save features. i.e. it will create if needed, else it will update. If createIfNotExists is false (the default) then save will fail if given a page name which does not refer to an existing page. - **TODO:** add `commitMessage` string property. The fossil internals don't have a way to do this at the moment (they can as of late 2019). Since fossil wiki commits have always had the same default commit message, this is not a high-priority addition. See:\ [](/doc/trunk/www/fileformat.wiki#wikichng) - **Potential TODO:** we *could* optionally also support multi-page saving using an array of pages in the request payload:\ `[… page objects … ]` <a id="diffs"></a> # Wiki Diffs **Status:** implemented 20120304 | > > > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | **Request options** (via GET or `POST.payload` object): - `name=string` specifies the page name. - `content=string` is the body text.\ Content is required for save (unless `createIfNotExists` is true *and* the page does not exist), optional for create. It *may* be an empty string. - `mimetype=string` specifies the mimetype for the body, noting any any unrecognized/unsupported mimetype is silently treated as `text/x-fossil-wiki`. - Save (not create) supports a `createIfNotExists` boolean option which makes it a functional superset of the create/save features. i.e. it will create if needed, else it will update. If createIfNotExists is false (the default) then save will fail if given a page name which does not refer to an existing page. - **TODO:** add `commitMessage` string property. The fossil internals don't have a way to do this at the moment (they can as of late 2019). Since fossil wiki commits have always had the same default commit message, this is not a high-priority addition. See:\ [](/doc/trunk/www/fileformat.wiki#wikichng) - **Potential TODO:** we *could* optionally also support multi-page saving using an array of pages in the request payload:\ `[… page objects … ]` <a id="diffs"></a> # Wiki Diffs **Status:** implemented 20120304 |
︙ | ︙ | |||
236 237 238 239 240 241 242 | - `/json/wiki/preview` This command wiki-processes arbitrary text sent from the client. To help curb potential abuse, its use is restricted to those with "k" access rights. | | | > | > > > > > > | | < < < < < < | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | - `/json/wiki/preview` This command wiki-processes arbitrary text sent from the client. To help curb potential abuse, its use is restricted to those with "k" access rights. The `POST.payload` property must be either: 1) A string containing Fossil wiki markup. 2) An Object with a `body` property holding the text to render and a `mimetype` property describing the wiki format: `text/x-fossil-wiki` (the default), `text/x-markdown`, or `text/plain`. Any unknown type is treated as `text/x-fossil-wiki`. The response payload is a string containing the rendered page. Whether or not "all HTML" is allowed depends on site-level configuration options, and that changes how the input is processed. Note that the links in the generated page are for the HTML interface, and will not work as-is for arbitrary JSON clients. In order to integrate the parsed content with JSON-based clients the HTML will probably need to be post-processed, e.g. using jQuery to fish out the links and re-map wiki page links to a JSON-capable page handler. <a id="todo"></a> # Notes and TODOs - When server-parsing the wiki content, the generated intra-wiki/intra-site links will only be useful in the context of the original fossil UI (or a work-alike), not arbitrary JSON client apps. Potential TODOs: - `/wiki/history` analog to the [](/whistory) page. |
Changes to www/userlinks.wiki.
︙ | ︙ | |||
29 30 31 32 33 34 35 | | read-only mailing list archives] house discussions spanning Fossil's first decade. * [./stats.wiki | Performance statistics] taken from real-world projects hosted on Fossil. * How to [./shunning.wiki | delete content] from a Fossil repository. * How Fossil does [./password.wiki | password management]. * On-line [/help | help]. | < < < < > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | | read-only mailing list archives] house discussions spanning Fossil's first decade. * [./stats.wiki | Performance statistics] taken from real-world projects hosted on Fossil. * How to [./shunning.wiki | delete content] from a Fossil repository. * How Fossil does [./password.wiki | password management]. * On-line [/help | help]. * List of [./th1.md | TH1 commands provided by Fossil itself] that expose its key functionality to TH1 scripts. * List of [./th1-hooks.md | TH1 hooks exposed by Fossil] that enable customization of commands and web pages. * A free hosting server for Fossil repositories is available at [http://chiselapp.com/]. * How to [./server/ | set up a server] for your repository. * Customizing the [./custom_ticket.wiki | ticket system]. * Methods to [./checkin_names.wiki | identify a specific check-in]. * [./inout.wiki | Import and export] from and to Git. * [./fossil-v-git.wiki | Fossil versus Git]. * [./fiveminutes.wiki | Up and running in 5 minutes as a single user] (contributed by Gilles Ganault on 2013-01-08). * [./antibot.wiki | How Fossil defends against abuse by spiders and bots]. * [./wsl_caveats.wiki | Using Fossil on WSL], caveats and guidance. |
Changes to www/wsl_caveats.wiki.
1 2 3 4 5 6 | <title>Caveats and Precautions for Fossil Usage with Windows Subsystem for Linux</title> <h2>When These Issues Matter</h2> The discussion following is relevant to those who: | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <title>Caveats and Precautions for Fossil Usage with Windows Subsystem for Linux</title> <h2>When These Issues Matter</h2> The discussion following is relevant to those who: * Are using the Windows Subsystem for Linux (aka "WSL"); * Create a Fossil checkout in a directory accessible from WSL and Windows; * Use both Linux Fossil and Windows tools to modify files in a checkout; * Desire to or must preserve execute permissions set for repository files; * and Use Linux Fossil to commit changes made within the checkout. Note that these criteria apply conjunctively; if any are not met, then the consequences of the issues below are at worst annoying and otherwise harmless or absent. <h2>What Can Go Wrong (Why It Matters)</h2> |
︙ | ︙ | |||
72 73 74 75 76 77 78 | Hence, inadvertant X-bit changes are unavoidable, or avoided only by luck, in the general usage case noted above. <h2>Problematic Usage Scenarios</h2> <h3>A Simple Example</h3> | | | | | | | | | | | | | | | | | | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | Hence, inadvertant X-bit changes are unavoidable, or avoided only by luck, in the general usage case noted above. <h2>Problematic Usage Scenarios</h2> <h3>A Simple Example</h3> * Open a checkout in Windows (using fossil.exe) from a project whose files have a mixture of executable and non-executable files. Use a checkout directory visible when running under WSL. * Navigate to the same directory in a Linux shell on WSL, then run "fossil status". * Depending upon /etc/wsl.conf content (or defaults in its absence), the status ouput will tag checkout files as EXECUTABLE or NOEXEC. <h3>Continuation of Simple Example</h3> * In the same checkout as above "Simple Example", on WSL, run "fossil revert" to correct all those errant X-bit values. * Run "fossil status" again in WSL to verify absence of toggled X-bits. * Run "ls -l" from WSL to find two files, one with its X-bit set and the other with it clear. * From Windows, perform these steps on each of those files:<br> (1) read the_file content into a buffer<br> (2) rename the_file the_file.bak<br> (3) write buffer content to new file, the_file<br> (4) del the_file.bak (or leave it)<br> (Note that this sequence is similar to what many editors do when a user modifies a file then uses undo to reverse the changes.) * Run "fossil status" again in WSL and observe that one of the two files has had its X-bit toggled. <h3>A Fossil-Only Example</h3> * In the another (different) checkout of the same version, somehow cause "legitimate" X-bit toggles of two files whose X-bits differ. (This "somehow" probably will involve WSL to toggle file bits and fossil on WSL to commit the toggles.) * In the Simple Example checkout, use fossil.exe on Windows to update the checkout, ostensibly bringing the X-bit toggles into the affected checkout files. * In the Simple Example checkout, use fossil on WSL to run "fossil status", and observe at least one X-bit discrepancy. <h2>Recommended Workflow</h2> There are two simple approaches for dealing with this issue when one wishes to continue using the same checkout directory from Windows and WSL. Either one is effective. These are: * Do not use fossil on WSL for any operations which will modify the repository. Instead, block those operations in some manner. * Do not use any tools on Windows, (including certain subcommands of fossil.exe,) which may modify the X-bits on files within the shared checkout, instead restricting use of Windows tools to those which are known to only (and actually) modify file content in place while preserving X-bit values. (The "actually" proviso emphasizes that tools which only simulate in-place file modification, but do so via create combined with delete and rename, are to be avoided. A simulation which works flawlessly on Windows may not preserve |
︙ | ︙ |