Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Update the built-in SQLite to the latest from upstream that includes the skip-scan optimization and the improved EXPLAIN display in the shell. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
28c508679e0dfc5ff6a586876f54a961 |
| User & Date: | drh 2013-11-14 19:36:30.164 |
Context
|
2013-11-15
| ||
| 12:58 | Update custom makefile as well. If fossil is linked with external SQLite library, make sure it is used single-threaded. check-in: 1928cf526e user: jan.nijtmans tags: trunk | |
|
2013-11-14
| ||
| 19:36 | Update the built-in SQLite to the latest from upstream that includes the skip-scan optimization and the improved EXPLAIN display in the shell. check-in: 28c508679e user: drh tags: trunk | |
|
2013-11-13
| ||
| 11:28 | Take over latest change in src/mem1.c (usage of _msize function) from SQLite trunk, and modify MinGW build to use it as well. check-in: bcd979daef user: jan.nijtmans tags: trunk | |
Changes
Changes to src/main.mk.
| ︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | $(OBJDIR)/translate $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c | | | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 | $(OBJDIR)/translate $(SRCDIR)/zip.c >$(OBJDIR)/zip_.c $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dsqlite3_strglob=strglob -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o $(OBJDIR)/th.o: $(SRCDIR)/th.c $(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
286 287 288 289 290 291 292 |
}
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
#append opt " -DSQLITE_ENABLE_FTS3=1"
| > > | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
}
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
set opt {-DSQLITE_OMIT_LOAD_EXTENSION=1}
append opt " -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4"
#append opt " -DSQLITE_ENABLE_FTS3=1"
#append opt " -DSQLITE_ENABLE_STAT4"
append opt " -DSQLITE_OMIT_DEPRECATED"
append opt " -DSQLITE_ENABLE_EXPLAIN_COMMENTS"
append opt " -Dlocaltime=fossil_localtime"
append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
append opt " -DSQLITE_WIN32_NO_ANSI"
set SQLITE_OPTIONS $opt
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
char *zFreeOnClose; /* Filename to free when closing */
const char *zVfs; /* Name of VFS to use */
sqlite3_stmt *pStmt; /* Current statement if any. */
FILE *pLog; /* Write log output here */
};
/*
** These are the allowed modes.
*/
#define MODE_Line 0 /* One column per line. Blank line between records */
#define MODE_Column 1 /* One record per line in neat columns */
| > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
char *zFreeOnClose; /* Filename to free when closing */
const char *zVfs; /* Name of VFS to use */
sqlite3_stmt *pStmt; /* Current statement if any. */
FILE *pLog; /* Write log output here */
int *aiIndent; /* Array of indents used in MODE_Explain */
int nIndent; /* Size of array aiIndent[] */
};
/*
** These are the allowed modes.
*/
#define MODE_Line 0 /* One column per line. Blank line between records */
#define MODE_Column 1 /* One record per line in neat columns */
|
| ︙ | ︙ | |||
761 762 763 764 765 766 767 |
for(i=0; i<nArg; i++){
int w;
if( i<ArraySize(p->actualWidth) ){
w = p->actualWidth[i];
}else{
w = 10;
}
| | < > > > > > > | 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 |
for(i=0; i<nArg; i++){
int w;
if( i<ArraySize(p->actualWidth) ){
w = p->actualWidth[i];
}else{
w = 10;
}
if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
w = strlen30(azArg[i]);
}
if( i==1 && p->aiIndent && p->pStmt ){
int iOp = sqlite3_column_int(p->pStmt, 0);
if( iOp<p->nIndent ){
fprintf(p->out, "%*.s", p->aiIndent[iOp], "");
}
}
if( w<0 ){
fprintf(p->out,"%*.*s%s",-w,-w,
azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
}else{
fprintf(p->out,"%-*.*s%s",w,w,
azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
|
| ︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 |
fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
}
return 0;
}
/*
** Execute a statement or set of statements. Print
** any result rows/columns depending on the current mode
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec()
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 |
fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
}
return 0;
}
/*
** Parameter azArray points to a zero-terminated array of strings. zStr
** points to a single nul-terminated string. Return non-zero if zStr
** is equal, according to strcmp(), to any of the strings in the array.
** Otherwise, return zero.
*/
static int str_in_array(const char *zStr, const char **azArray){
int i;
for(i=0; azArray[i]; i++){
if( 0==strcmp(zStr, azArray[i]) ) return 1;
}
return 0;
}
/*
** If compiled statement pSql appears to be an EXPLAIN statement, allocate
** and populate the callback_data.aiIndent[] array with the number of
** spaces each opcode should be indented before it is output.
**
** The indenting rules are:
**
** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
** all opcodes that occur between the p2 jump destination and the opcode
** itself by 2 spaces.
**
** * For each "Goto", if the jump destination is a "Yield", "SeekGt",
** or "SeekLt" instruction that occurs earlier in the program than
** the Goto itself, indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
const char *zSql; /* The text of the SQL statement */
const char *z; /* Used to check if this is an EXPLAIN */
int *abYield = 0; /* True if op is an OP_Yield */
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp;
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", 0 };
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", 0 };
const char *azGoto[] = { "Goto", 0 };
/* Try to figure out if this is really an EXPLAIN statement. If this
** cannot be verified, return early. */
zSql = sqlite3_sql(pSql);
if( zSql==0 ) return;
for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
if( sqlite3_strnicmp(z, "explain", 7) ) return;
for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
int i;
const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
int p2 = sqlite3_column_int(pSql, 3);
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) ){
for(i=p2; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2<p->nIndent && abYield[p2] ){
for(i=p2+1; i<iOp; i++) p->aiIndent[i] += 2;
}
}
sqlite3_free(abYield);
sqlite3_reset(pSql);
}
/*
** Free the array allocated by explain_data_prepare().
*/
static void explain_data_delete(struct callback_data *p){
sqlite3_free(p->aiIndent);
p->aiIndent = 0;
p->nIndent = 0;
}
/*
** Execute a statement or set of statements. Print
** any result rows/columns depending on the current mode
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec()
|
| ︙ | ︙ | |||
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 |
if( pArg && pArg->mode==MODE_Explain ){
const char *zExplain = 0;
sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
if( zExplain && zExplain[0] ){
fprintf(pArg->out, "%s", zExplain);
}
}
/* perform the first step. this will tell us if we
** have a result set or not and how wide it is.
*/
rc = sqlite3_step(pStmt);
/* if we have a result set... */
if( SQLITE_ROW == rc ){
| > > > > > > | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 |
if( pArg && pArg->mode==MODE_Explain ){
const char *zExplain = 0;
sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
if( zExplain && zExplain[0] ){
fprintf(pArg->out, "%s", zExplain);
}
}
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg->mode==MODE_Explain ){
explain_data_prepare(pArg, pStmt);
}
/* perform the first step. this will tell us if we
** have a result set or not and how wide it is.
*/
rc = sqlite3_step(pStmt);
/* if we have a result set... */
if( SQLITE_ROW == rc ){
|
| ︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
}
}else{
do{
rc = sqlite3_step(pStmt);
} while( rc == SQLITE_ROW );
}
}
/* print usage stats if stats on */
if( pArg && pArg->statsOn ){
display_stats(db, pArg, 0);
}
/* Finalize the statement just executed. If this fails, save a
| > > | 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 |
}
}else{
do{
rc = sqlite3_step(pStmt);
} while( rc == SQLITE_ROW );
}
}
explain_data_delete(pArg);
/* print usage stats if stats on */
if( pArg && pArg->statsOn ){
display_stats(db, pArg, 0);
}
/* Finalize the statement just executed. If this fails, save a
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
133 134 135 136 137 138 139 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.2" #define SQLITE_VERSION_NUMBER 3008002 | | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.2" #define SQLITE_VERSION_NUMBER 3008002 #define SQLITE_SOURCE_ID "2013-11-14 19:34:10 10d59226382adcb8016fc2d927e5a0c0b36f3980" /* ** 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 |
| ︙ | ︙ | |||
9235 9236 9237 9238 9239 9240 9241 | SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); | < | 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 | SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); #endif SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); |
| ︙ | ︙ | |||
10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 | #define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */ #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ | > | 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 | #define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */ #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ |
| ︙ | ︙ | |||
13698 13699 13700 13701 13702 13703 13704 |
#endif
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
| < < < | 13698 13699 13700 13701 13702 13703 13704 13705 13706 13707 13708 13709 13710 13711 |
#endif
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
#ifdef SQLITE_ENABLE_TREE_EXPLAIN
Explain *pExplain; /* The explainer */
char *zExplain; /* Explanation of data structures */
#endif
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
int nFrame; /* Number of frames in pFrame list */
|
| ︙ | ︙ | |||
61011 61012 61013 61014 61015 61016 61017 | pB->pPrev = pTmp; zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; pB->isPrepareV2 = pA->isPrepareV2; } | < < < < < < < < < | 61008 61009 61010 61011 61012 61013 61014 61015 61016 61017 61018 61019 61020 61021 | pB->pPrev = pTmp; zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; pB->isPrepareV2 = pA->isPrepareV2; } /* ** Resize the Vdbe.aOp array so that it is at least one op larger than ** it was. ** ** If an out-of-memory error occurs while resizing the array, return ** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain ** unchanged (this is so that any opcodes already allocated can be |
| ︙ | ︙ | |||
61915 61916 61917 61918 61919 61920 61921 |
zTemp[i++] = ')';
zTemp[i] = 0;
assert( i<nTemp );
break;
}
case P4_COLLSEQ: {
CollSeq *pColl = pOp->p4.pColl;
| | | 61903 61904 61905 61906 61907 61908 61909 61910 61911 61912 61913 61914 61915 61916 61917 |
zTemp[i++] = ')';
zTemp[i] = 0;
assert( i<nTemp );
break;
}
case P4_COLLSEQ: {
CollSeq *pColl = pOp->p4.pColl;
sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
break;
}
case P4_FUNCDEF: {
FuncDef *pDef = pOp->p4.pFunc;
sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
|
| ︙ | ︙ | |||
62348 62349 62350 62351 62352 62353 62354 |
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_DEBUG
/*
** Print the SQL that was used to generate a VDBE program.
*/
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
| > > | < | | | | | < | > > | 62336 62337 62338 62339 62340 62341 62342 62343 62344 62345 62346 62347 62348 62349 62350 62351 62352 62353 62354 62355 62356 62357 62358 62359 62360 |
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_DEBUG
/*
** Print the SQL that was used to generate a VDBE program.
*/
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
const char *z = 0;
if( p->zSql ){
z = p->zSql;
}else if( p->nOp>=1 ){
const VdbeOp *pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
z = pOp->p4.z;
while( sqlite3Isspace(*z) ) z++;
}
}
if( z ) printf("SQL: [%s]\n", z);
}
#endif
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** Print an IOTRACE message showing SQL content.
*/
|
| ︙ | ︙ | |||
66364 66365 66366 66367 66368 66369 66370 | } #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ | | | | | | | | < | | | | | | | 66354 66355 66356 66357 66358 66359 66360 66361 66362 66363 66364 66365 66366 66367 66368 66369 66370 66371 66372 66373 66374 66375 66376 66377 66378 66379 66380 66381 66382 66383 66384 66385 66386 66387 66388 66389 66390 66391 66392 66393 66394 66395 66396 66397 |
}
#endif
#ifdef SQLITE_DEBUG
/*
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(Mem *p){
if( p->flags & MEM_Invalid ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
printf(" NULL");
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
printf(" si:%lld", p->u.i);
}else if( p->flags & MEM_Int ){
printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
printf(" r:%g", p->r);
#endif
}else if( p->flags & MEM_RowSet ){
printf(" (rowset)");
}else{
char zBuf[200];
sqlite3VdbeMemPrettyPrint(p, zBuf);
printf(" %s", zBuf);
}
}
static void registerTrace(int iReg, Mem *p){
printf("REG[%d] = ", iReg);
memTracePrint(p);
printf("\n");
}
#endif
#ifdef SQLITE_DEBUG
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
# define REGISTER_TRACE(R,M)
#endif
#ifdef VDBE_PROFILE
|
| ︙ | ︙ | |||
67049 67050 67051 67052 67053 67054 67055 |
}else{
nProgressLimit %= (unsigned)db->nProgressOps;
}
}
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
| | > > | > > | | | > > > > > > > > > > > | < < | < < | 67038 67039 67040 67041 67042 67043 67044 67045 67046 67047 67048 67049 67050 67051 67052 67053 67054 67055 67056 67057 67058 67059 67060 67061 67062 67063 67064 67065 67066 67067 67068 67069 67070 67071 67072 67073 67074 67075 67076 67077 67078 67079 67080 67081 67082 67083 67084 67085 67086 67087 67088 67089 67090 67091 |
}else{
nProgressLimit %= (unsigned)db->nProgressOps;
}
}
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
if( p->pc==0
&& (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
){
int i;
int once = 1;
sqlite3VdbePrintSql(p);
if( p->db->flags & SQLITE_VdbeListing ){
printf("VDBE Program Listing:\n");
for(i=0; i<p->nOp; i++){
sqlite3VdbePrintOp(stdout, i, &aOp[i]);
}
}
if( p->db->flags & SQLITE_VdbeEQP ){
for(i=0; i<p->nOp; i++){
if( aOp[i].opcode==OP_Explain ){
if( once ) printf("VDBE Query Plan:\n");
printf("%s\n", aOp[i].p4.z);
once = 0;
}
}
}
if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n");
}
sqlite3EndBenignMalloc();
#endif
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
if( db->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
origPc = pc;
start = sqlite3Hwtime();
#endif
nVmStep++;
pOp = &aOp[pc];
/* Only allow tracing if SQLITE_DEBUG is defined.
*/
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
sqlite3VdbePrintOp(stdout, pc, pOp);
}
#endif
/* Check to see if we need to simulate an interrupt. This only happens
** if we have a special test build.
*/
|
| ︙ | ︙ | |||
67208 67209 67210 67211 67212 67213 67214 |
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
| | > | < < < < | 67208 67209 67210 67211 67212 67213 67214 67215 67216 67217 67218 67219 67220 67221 67222 67223 67224 67225 67226 67227 |
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
assert( db->nProgressOps!=0 );
nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
if( db->xProgress(db->pProgressArg) ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
}
#endif
break;
}
/* Opcode: Gosub P1 P2 * * *
|
| ︙ | ︙ | |||
67652 67653 67654 67655 67656 67657 67658 67659 67660 67661 67662 67663 67664 67665 |
#if 0 /* local variables moved into u.ag */
Mem *pMem;
int i;
#endif /* local variables moved into u.ag */
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
/* If this statement has violated immediate foreign key constraints, do
** not return the number of rows modified. And do not RELEASE the statement
** transaction. It needs to be rolled back. */
if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
assert( db->flags&SQLITE_CountRows );
assert( p->usesStmtJournal );
| > > > > > > > > > > > > | 67649 67650 67651 67652 67653 67654 67655 67656 67657 67658 67659 67660 67661 67662 67663 67664 67665 67666 67667 67668 67669 67670 67671 67672 67673 67674 |
#if 0 /* local variables moved into u.ag */
Mem *pMem;
int i;
#endif /* local variables moved into u.ag */
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Run the progress counter just before returning.
*/
if( db->xProgress!=0
&& nVmStep>=nProgressLimit
&& db->xProgress(db->pProgressArg)!=0
){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
#endif
/* If this statement has violated immediate foreign key constraints, do
** not return the number of rows modified. And do not RELEASE the statement
** transaction. It needs to be rolled back. */
if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
assert( db->flags&SQLITE_CountRows );
assert( p->usesStmtJournal );
|
| ︙ | ︙ | |||
72860 72861 72862 72863 72864 72865 72866 |
** On the other hand, it does burn CPU cycles every time through
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
| | | | | | 72869 72870 72871 72872 72873 72874 72875 72876 72877 72878 72879 72880 72881 72882 72883 72884 72885 72886 72887 72888 72889 |
** On the other hand, it does burn CPU cycles every time through
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
if( rc!=0 ) printf("rc=%d\n",rc);
if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
registerTrace(pOp->p2, &aMem[pOp->p2]);
}
if( pOp->opflags & OPFLG_OUT3 ){
registerTrace(pOp->p3, &aMem[pOp->p3]);
}
}
#endif /* SQLITE_DEBUG */
#endif /* NDEBUG */
} /* The end of the for(;;) loop the loops through opcodes */
/* If we reach this point, it means that execution is finished with
|
| ︙ | ︙ | |||
83104 83105 83106 83107 83108 83109 83110 |
if( argv==0 || argv[0]==0 || argv[2]==0 ){
return 0;
}
pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase);
if( pTable==0 ){
return 0;
}
| | | > > | | 83113 83114 83115 83116 83117 83118 83119 83120 83121 83122 83123 83124 83125 83126 83127 83128 83129 83130 83131 83132 |
if( argv==0 || argv[0]==0 || argv[2]==0 ){
return 0;
}
pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase);
if( pTable==0 ){
return 0;
}
if( argv[1]==0 ){
pIndex = 0;
}else if( sqlite3_stricmp(argv[0],argv[1])==0 ){
pIndex = sqlite3PrimaryKeyIndex(pTable);
}else{
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
}
z = argv[2];
if( pIndex ){
decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
}else{
|
| ︙ | ︙ | |||
84465 84466 84467 84468 84469 84470 84471 |
}
}
/* Get the VDBE program ready for execution
*/
if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
| < < < < | 84476 84477 84478 84479 84480 84481 84482 84483 84484 84485 84486 84487 84488 84489 |
}
}
/* Get the VDBE program ready for execution
*/
if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
|
| ︙ | ︙ | |||
96678 96679 96680 96681 96682 96683 96684 96685 96686 96687 96688 96689 96690 96691 |
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_VdbeAddopTrace },
{ /* zName: */ "vdbe_debug",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
{ /* zName: */ "vdbe_listing",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_VdbeListing },
{ /* zName: */ "vdbe_trace",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
| > > > > | 96685 96686 96687 96688 96689 96690 96691 96692 96693 96694 96695 96696 96697 96698 96699 96700 96701 96702 |
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_VdbeAddopTrace },
{ /* zName: */ "vdbe_debug",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
{ /* zName: */ "vdbe_eqp",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_VdbeEQP },
{ /* zName: */ "vdbe_listing",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_VdbeListing },
{ /* zName: */ "vdbe_trace",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
|
| ︙ | ︙ | |||
96705 96706 96707 96708 96709 96710 96711 |
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{ /* zName: */ "writable_schema",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
| | | 96716 96717 96718 96719 96720 96721 96722 96723 96724 96725 96726 96727 96728 96729 96730 |
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{ /* zName: */ "writable_schema",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 56 on by default, 69 total. */
/* End of the automatically generated pragma table.
***************************************************************************/
/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
** unrecognized string argument. The FULL option is disallowed
|
| ︙ | ︙ | |||
107927 107928 107929 107930 107931 107932 107933 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is responsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ | | > > > > > > > > > > > > > > > > > | 107938 107939 107940 107941 107942 107943 107944 107945 107946 107947 107948 107949 107950 107951 107952 107953 107954 107955 107956 107957 107958 107959 107960 107961 107962 107963 107964 107965 107966 107967 107968 107969 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is responsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ /************** Include whereInt.h in the middle of where.c ******************/ /************** Begin file whereInt.h ****************************************/ /* ** 2013-11-12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains structure and macro definitions for the query ** planner logic in "where.c". These definitions are broken out into ** a separate source file for easier editing. */ /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) /***/ int sqlite3WhereTrace = 0; #endif |
| ︙ | ︙ | |||
107979 107980 107981 107982 107983 107984 107985 107986 107987 107988 107989 107990 107991 107992 |
*/
struct WhereLevel {
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
int iTabCur; /* The VDBE cursor used to access the table */
int iIdxCur; /* The VDBE cursor used to access pIdx */
int addrBrk; /* Jump here to break out of the loop */
int addrNxt; /* Jump here to start the next IN combination */
int addrCont; /* Jump here to continue with the next loop cycle */
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to ends the loop */
union { /* Information that depends on pWLoop->wsFlags */
| > | 108007 108008 108009 108010 108011 108012 108013 108014 108015 108016 108017 108018 108019 108020 108021 |
*/
struct WhereLevel {
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
int iTabCur; /* The VDBE cursor used to access the table */
int iIdxCur; /* The VDBE cursor used to access pIdx */
int addrBrk; /* Jump here to break out of the loop */
int addrNxt; /* Jump here to start the next IN combination */
int addrSkip; /* Jump here for next iteration of skip-scan */
int addrCont; /* Jump here to continue with the next loop cycle */
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to ends the loop */
union { /* Information that depends on pWLoop->wsFlags */
|
| ︙ | ︙ | |||
108028 108029 108030 108031 108032 108033 108034 |
u8 iSortIdx; /* Sorting index number. 0==None */
LogEst rSetup; /* One-time setup cost (ex: create transient index) */
LogEst rRun; /* Cost of running each loop */
LogEst nOut; /* Estimated number of output rows */
union {
struct { /* Information for internal btree tables */
u16 nEq; /* Number of equality constraints */
| | | 108057 108058 108059 108060 108061 108062 108063 108064 108065 108066 108067 108068 108069 108070 108071 |
u8 iSortIdx; /* Sorting index number. 0==None */
LogEst rSetup; /* One-time setup cost (ex: create transient index) */
LogEst rRun; /* Cost of running each loop */
LogEst nOut; /* Estimated number of output rows */
union {
struct { /* Information for internal btree tables */
u16 nEq; /* Number of equality constraints */
u16 nSkip; /* Number of initial index columns to skip */
Index *pIndex; /* Index used, or NULL */
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u8 needFree; /* True if sqlite3_free(idxStr) is needed */
u8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
|
| ︙ | ︙ | |||
108369 108370 108371 108372 108373 108374 108375 108376 108377 108378 108379 108380 108381 108382 |
#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
/*
** Return the estimated number of output rows from a WHERE clause
*/
SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
return sqlite3LogEstToInt(pWInfo->nRowOut);
}
| > > > > | 108398 108399 108400 108401 108402 108403 108404 108405 108406 108407 108408 108409 108410 108411 108412 108413 108414 108415 |
#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
/************** End of whereInt.h ********************************************/
/************** Continuing where we left off in where.c **********************/
/*
** Return the estimated number of output rows from a WHERE clause
*/
SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
return sqlite3LogEstToInt(pWInfo->nRowOut);
}
|
| ︙ | ︙ | |||
110773 110774 110775 110776 110777 110778 110779 | } disableTerm(pLevel, pTerm); return iReg; } /* ** Generate code that will evaluate all == and IN constraints for an | | > > > > > | | | > | 110806 110807 110808 110809 110810 110811 110812 110813 110814 110815 110816 110817 110818 110819 110820 110821 110822 110823 110824 110825 110826 110827 110828 110829 110830 110831 110832 110833 110834 110835 110836 110837 110838 110839 110840 110841 110842 110843 | } disableTerm(pLevel, pTerm); return iReg; } /* ** Generate code that will evaluate all == and IN constraints for an ** index scan. ** ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 ** The index has as many as three equality constraints, but in this ** example, the third "c" value is an inequality. So only two ** constraints are coded. This routine will generate code to evaluate ** a==5 and b IN (1,2,3). The current values for a and b will be stored ** in consecutive registers and the index of the first register is returned. ** ** In the example above nEq==2. But this subroutine works for any value ** of nEq including 0. If nEq==0, this routine is nearly a no-op. ** The only thing it does is allocate the pLevel->iMem memory cell and ** compute the affinity string. ** ** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints ** are == or IN and are covered by the nEq. nExtraReg is 1 if there is ** an inequality constraint (such as the "c>=5 AND c<10" in the example) that ** occurs after the nEq quality constraints. ** ** This routine allocates a range of nEq+nExtraReg memory cells and returns ** the index of the first memory cell in that range. The code that ** calls this routine will use that memory range to store keys for ** start and termination conditions of the loop. ** key value of the loop. If one or more IN operators appear, then ** this routine allocates an additional nEq memory cells for internal ** use. ** ** Before returning, *pzAff is set to point to a buffer containing a ** copy of the column affinity string of the index allocated using ** sqlite3DbMalloc(). Except, entries in the copy of the string associated |
| ︙ | ︙ | |||
110817 110818 110819 110820 110821 110822 110823 |
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
int bRev, /* Reverse the order of IN operators */
int nExtraReg, /* Number of extra registers to allocate */
char **pzAff /* OUT: Set to point to affinity string */
){
| | > > > > > > > > > > > > > > > > > | | | 110856 110857 110858 110859 110860 110861 110862 110863 110864 110865 110866 110867 110868 110869 110870 110871 110872 110873 110874 110875 110876 110877 110878 110879 110880 110881 110882 110883 110884 110885 110886 110887 110888 110889 110890 110891 110892 110893 110894 110895 110896 110897 110898 110899 110900 110901 110902 110903 110904 110905 110906 110907 110908 110909 110910 110911 110912 110913 110914 110915 110916 110917 110918 110919 110920 110921 110922 |
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
int bRev, /* Reverse the order of IN operators */
int nExtraReg, /* Number of extra registers to allocate */
char **pzAff /* OUT: Set to point to affinity string */
){
u16 nEq; /* The number of == or IN constraints to code */
u16 nSkip; /* Number of left-most columns to skip */
Vdbe *v = pParse->pVdbe; /* The vm under construction */
Index *pIdx; /* The index being used for this loop */
WhereTerm *pTerm; /* A single constraint term */
WhereLoop *pLoop; /* The WhereLoop object */
int j; /* Loop counter */
int regBase; /* Base register */
int nReg; /* Number of registers to allocate */
char *zAff; /* Affinity string to return */
/* This module is only called on query plans that use an index. */
pLoop = pLevel->pWLoop;
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
nEq = pLoop->u.btree.nEq;
nSkip = pLoop->u.btree.nSkip;
pIdx = pLoop->u.btree.pIndex;
assert( pIdx!=0 );
/* Figure out how many memory cells we will need then allocate them.
*/
regBase = pParse->nMem + 1;
nReg = pLoop->u.btree.nEq + nExtraReg;
pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
if( !zAff ){
pParse->db->mallocFailed = 1;
}
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
j = sqlite3VdbeAddOp0(v, OP_Goto);
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLt:OP_SeekGt),
iIdxCur, 0, regBase, nSkip);
sqlite3VdbeJumpHere(v, j);
for(j=0; j<nSkip; j++){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
assert( pIdx->aiColumn[j]>=0 );
VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName));
}
}
/* Evaluate the equality constraints
*/
assert( zAff==0 || (int)strlen(zAff)>=nEq );
for(j=nSkip; j<nEq; j++){
int r1;
pTerm = pLoop->aLTerm[j];
assert( pTerm!=0 );
/* The following testcase is true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
|
| ︙ | ︙ | |||
110926 110927 110928 110929 110930 110931 110932 |
**
** The returned pointer points to memory obtained from sqlite3DbMalloc().
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
Index *pIndex = pLoop->u.btree.pIndex;
| | > > | > > > > > > | 110982 110983 110984 110985 110986 110987 110988 110989 110990 110991 110992 110993 110994 110995 110996 110997 110998 110999 111000 111001 111002 111003 111004 111005 111006 111007 111008 111009 111010 111011 111012 111013 111014 111015 111016 111017 111018 |
**
** The returned pointer points to memory obtained from sqlite3DbMalloc().
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
Index *pIndex = pLoop->u.btree.pIndex;
u16 nEq = pLoop->u.btree.nEq;
u16 nSkip = pLoop->u.btree.nSkip;
int i, j;
Column *aCol = pTab->aCol;
i16 *aiColumn = pIndex->aiColumn;
StrAccum txt;
if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
return 0;
}
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
for(i=0; i<nEq; i++){
char *z = (i==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[i]].zName;
if( i>=nSkip ){
explainAppendTerm(&txt, i, z, "=");
}else{
if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
sqlite3StrAccumAppend(&txt, "ANY(", 4);
sqlite3StrAccumAppend(&txt, z, -1);
sqlite3StrAccumAppend(&txt, ")", 1);
}
}
j = i;
if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i++, z, ">");
}
|
| ︙ | ︙ | |||
110970 110971 110972 110973 110974 110975 110976 |
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
int iLevel, /* Value for "level" column of output */
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
| > | > > | 111034 111035 111036 111037 111038 111039 111040 111041 111042 111043 111044 111045 111046 111047 111048 111049 111050 111051 |
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
int iLevel, /* Value for "level" column of output */
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
#ifndef SQLITE_DEBUG
if( pParse->explain==2 )
#endif
{
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
|
| ︙ | ︙ | |||
111076 111077 111078 111079 111080 111081 111082 |
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
| | | 111143 111144 111145 111146 111147 111148 111149 111150 111151 111152 111153 111154 111155 111156 111157 |
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeNoopComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
** Jump to cont to go immediately to the next iteration of the
** loop.
**
** When there is an IN operator, we also have a "addrNxt" label that
|
| ︙ | ︙ | |||
111303 111304 111305 111306 111307 111308 111309 |
OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
};
static const u8 aEndOp[] = {
OP_Noop, /* 0: (!end_constraints) */
OP_IdxGE, /* 1: (end_constraints && !bRev) */
OP_IdxLT /* 2: (end_constraints && bRev) */
};
| | | > | < | 111370 111371 111372 111373 111374 111375 111376 111377 111378 111379 111380 111381 111382 111383 111384 111385 111386 111387 111388 111389 111390 111391 111392 111393 111394 111395 111396 111397 111398 111399 111400 111401 111402 111403 111404 111405 111406 111407 111408 111409 111410 111411 111412 111413 111414 111415 111416 111417 |
OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
};
static const u8 aEndOp[] = {
OP_Noop, /* 0: (!end_constraints) */
OP_IdxGE, /* 1: (end_constraints && !bRev) */
OP_IdxLT /* 2: (end_constraints && bRev) */
};
u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
int regBase; /* Base register holding constraint values */
int r1; /* Temp register */
WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */
WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */
int startEq; /* True if range start uses ==, >= or <= */
int endEq; /* True if range end uses ==, >= or <= */
int start_constraints; /* Start of range is constrained */
int nConstraint; /* Number of constraint terms */
Index *pIdx; /* The index we will be using */
int iIdxCur; /* The VDBE cursor for the index */
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
char *zEndAff; /* Affinity for end of range constraint */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
assert( nEq>=pLoop->u.btree.nSkip );
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
** a single iteration. This means that the first row returned
** should not have a NULL value stored in 'x'. If column 'x' is
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
&& (pWInfo->bOBSat!=0)
&& (pIdx->nKeyCol>nEq)
){
assert( pLoop->u.btree.nSkip==0 );
isMinQuery = 1;
nExtraReg = 1;
}
/* Find any inequality constraint terms for the start and end
** of the range.
*/
|
| ︙ | ︙ | |||
111467 111468 111469 111470 111471 111472 111473 |
/* If there are inequality constraints, check that the value
** of the table column that the inequality contrains is not NULL.
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
| | > > > > | 111534 111535 111536 111537 111538 111539 111540 111541 111542 111543 111544 111545 111546 111547 111548 111549 111550 111551 111552 111553 |
/* If there are inequality constraints, check that the value
** of the table column that the inequality contrains is not NULL.
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
&& (j = pIdx->aiColumn[nEq])>=0
&& pIdx->pTable->aCol[j].notNull==0
){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName));
sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
sqlite3ReleaseTempReg(pParse, r1);
/* Seek the table cursor, if required */
disableTerm(pLevel, pRangeStart);
disableTerm(pLevel, pRangeEnd);
|
| ︙ | ︙ | |||
111856 111857 111858 111859 111860 111861 111862 |
const char *zName;
if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){
if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
int i = sqlite3Strlen30(zName) - 1;
while( zName[i]!='_' ) i--;
zName += i;
}
| < < < < | < | 111927 111928 111929 111930 111931 111932 111933 111934 111935 111936 111937 111938 111939 111940 111941 |
const char *zName;
if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){
if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
int i = sqlite3Strlen30(zName) - 1;
while( zName[i]!='_' ) i--;
zName += i;
}
sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
}else{
sqlite3DebugPrintf("%20s","");
}
}else{
char *z;
if( p->u.vtab.idxStr ){
z = sqlite3_mprintf("(%d,\"%s\",%x)",
|
| ︙ | ︙ | |||
111888 111889 111890 111891 111892 111893 111894 111895 111896 111897 111898 111899 111900 111901 |
*/
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */
int i;
Vdbe *v = pWInfo->pParse->pVdbe;
sqlite3ExplainBegin(v);
for(i=0; i<p->nLTerm; i++){
WhereTerm *pTerm = p->aLTerm[i];
sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a));
sqlite3ExplainPush(v);
whereExplainTerm(v, pTerm);
sqlite3ExplainPop(v);
sqlite3ExplainNL(v);
}
sqlite3ExplainFinish(v);
| > | 111954 111955 111956 111957 111958 111959 111960 111961 111962 111963 111964 111965 111966 111967 111968 |
*/
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */
int i;
Vdbe *v = pWInfo->pParse->pVdbe;
sqlite3ExplainBegin(v);
for(i=0; i<p->nLTerm; i++){
WhereTerm *pTerm = p->aLTerm[i];
if( pTerm==0 ) continue;
sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a));
sqlite3ExplainPush(v);
whereExplainTerm(v, pTerm);
sqlite3ExplainPop(v);
sqlite3ExplainNL(v);
}
sqlite3ExplainFinish(v);
|
| ︙ | ︙ | |||
112171 112172 112173 112174 112175 112176 112177 112178 112179 112180 112181 112182 112183 112184 |
}
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
for(j=pLoop->nLTerm-1; j>=0; j--){
pX = pLoop->aLTerm[j];
if( pX==pTerm ) break;
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ) pLoop->nOut += pTerm->truthProb;
}
}
| > | 112238 112239 112240 112241 112242 112243 112244 112245 112246 112247 112248 112249 112250 112251 112252 |
}
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
for(j=pLoop->nLTerm-1; j>=0; j--){
pX = pLoop->aLTerm[j];
if( pX==0 ) continue;
if( pX==pTerm ) break;
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ) pLoop->nOut += pTerm->truthProb;
}
}
|
| ︙ | ︙ | |||
112200 112201 112202 112203 112204 112205 112206 | sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ int opMask; /* Valid operators for constraints */ WhereScan scan; /* Iterator for WHERE terms */ Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ | | > | 112268 112269 112270 112271 112272 112273 112274 112275 112276 112277 112278 112279 112280 112281 112282 112283 | sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ int opMask; /* Valid operators for constraints */ WhereScan scan; /* Iterator for WHERE terms */ Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ u16 saved_nEq; /* Original value of pNew->u.btree.nEq */ u16 saved_nSkip; /* Original value of pNew->u.btree.nSkip */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ LogEst saved_nOut; /* Original value of pNew->nOut */ int iCol; /* Index of the column in the table */ int rc = SQLITE_OK; /* Return code */ LogEst nRowEst; /* Estimated index selectivity */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ |
| ︙ | ︙ | |||
112235 112236 112237 112238 112239 112240 112241 112242 112243 112244 112245 112246 112247 112248 112249 112250 112251 112252 112253 112254 |
}else{
iCol = -1;
nRowEst = 0;
}
pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
opMask, pProbe);
saved_nEq = pNew->u.btree.nEq;
saved_nLTerm = pNew->nLTerm;
saved_wsFlags = pNew->wsFlags;
saved_prereq = pNew->prereq;
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nRecValid = pBuilder->nRecValid;
#endif
if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
&& (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
| > > > > > > > > > > > > > > | 112304 112305 112306 112307 112308 112309 112310 112311 112312 112313 112314 112315 112316 112317 112318 112319 112320 112321 112322 112323 112324 112325 112326 112327 112328 112329 112330 112331 112332 112333 112334 112335 112336 112337 |
}else{
iCol = -1;
nRowEst = 0;
}
pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
opMask, pProbe);
saved_nEq = pNew->u.btree.nEq;
saved_nSkip = pNew->u.btree.nSkip;
saved_nLTerm = pNew->nLTerm;
saved_wsFlags = pNew->wsFlags;
saved_prereq = pNew->prereq;
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
if( pTerm==0
&& saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
&& pProbe->aiRowEst[saved_nEq+1]>50
){
LogEst nIter;
pNew->u.btree.nEq++;
pNew->u.btree.nSkip++;
pNew->aLTerm[pNew->nLTerm++] = 0;
pNew->wsFlags |= WHERE_SKIPSCAN;
nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]);
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter);
}
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nRecValid = pBuilder->nRecValid;
#endif
if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
&& (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
|
| ︙ | ︙ | |||
112276 112277 112278 112279 112280 112281 112282 |
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
pNew->rRun += nIn;
pNew->u.btree.nEq++;
pNew->nOut = nRowEst + nInMul + nIn;
}else if( pTerm->eOperator & (WO_EQ) ){
| > | | > | 112359 112360 112361 112362 112363 112364 112365 112366 112367 112368 112369 112370 112371 112372 112373 112374 112375 112376 |
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
pNew->rRun += nIn;
pNew->u.btree.nEq++;
pNew->nOut = nRowEst + nInMul + nIn;
}else if( pTerm->eOperator & (WO_EQ) ){
assert(
(pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN|WHERE_SKIPSCAN))!=0
|| nInMul==0
);
pNew->wsFlags |= WHERE_COLUMN_EQ;
if( iCol<0
|| (pProbe->onError!=OE_None && nInMul==0
&& pNew->u.btree.nEq==pProbe->nKeyCol-1)
){
assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
pNew->wsFlags |= WHERE_ONEROW;
|
| ︙ | ︙ | |||
112358 112359 112360 112361 112362 112363 112364 112365 112366 112367 112368 112369 112370 112371 |
pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
pBuilder->nRecValid = nRecValid;
#endif
}
pNew->prereq = saved_prereq;
pNew->u.btree.nEq = saved_nEq;
pNew->wsFlags = saved_wsFlags;
pNew->nOut = saved_nOut;
pNew->nLTerm = saved_nLTerm;
return rc;
}
/*
| > | 112443 112444 112445 112446 112447 112448 112449 112450 112451 112452 112453 112454 112455 112456 112457 |
pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
pBuilder->nRecValid = nRecValid;
#endif
}
pNew->prereq = saved_prereq;
pNew->u.btree.nEq = saved_nEq;
pNew->u.btree.nSkip = saved_nSkip;
pNew->wsFlags = saved_wsFlags;
pNew->nOut = saved_nOut;
pNew->nLTerm = saved_nLTerm;
return rc;
}
/*
|
| ︙ | ︙ | |||
112504 112505 112506 112507 112508 112509 112510 112511 112512 112513 112514 112515 112516 112517 |
/* Generate auto-index WhereLoops */
WhereTerm *pTerm;
WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
if( pTerm->prereqRight & pNew->maskSelf ) continue;
if( termCanDriveIndex(pTerm, pSrc, 0) ){
pNew->u.btree.nEq = 1;
pNew->u.btree.pIndex = 0;
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
/* TUNING: One-time cost for computing the automatic index is
** approximately 7*N*log2(N) where N is the number of rows in
** the table being indexed. */
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
| > | 112590 112591 112592 112593 112594 112595 112596 112597 112598 112599 112600 112601 112602 112603 112604 |
/* Generate auto-index WhereLoops */
WhereTerm *pTerm;
WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
if( pTerm->prereqRight & pNew->maskSelf ) continue;
if( termCanDriveIndex(pTerm, pSrc, 0) ){
pNew->u.btree.nEq = 1;
pNew->u.btree.nSkip = 0;
pNew->u.btree.pIndex = 0;
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
/* TUNING: One-time cost for computing the automatic index is
** approximately 7*N*log2(N) where N is the number of rows in
** the table being indexed. */
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
|
| ︙ | ︙ | |||
112533 112534 112535 112536 112537 112538 112539 112540 112541 112542 112543 112544 112545 112546 |
*/
for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
if( pProbe->pPartIdxWhere!=0
&& !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
continue; /* Partial index inappropriate for this query */
}
pNew->u.btree.nEq = 0;
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
pNew->rSetup = 0;
pNew->prereq = mExtra;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
| > | 112620 112621 112622 112623 112624 112625 112626 112627 112628 112629 112630 112631 112632 112633 112634 |
*/
for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
if( pProbe->pPartIdxWhere!=0
&& !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
continue; /* Partial index inappropriate for this query */
}
pNew->u.btree.nEq = 0;
pNew->u.btree.nSkip = 0;
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
pNew->rSetup = 0;
pNew->prereq = mExtra;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
|
| ︙ | ︙ | |||
112618 112619 112620 112621 112622 112623 112624 | #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. */ static int whereLoopAddVirtual( | | > | 112706 112707 112708 112709 112710 112711 112712 112713 112714 112715 112716 112717 112718 112719 112720 112721 |
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
*/
static int whereLoopAddVirtual(
WhereLoopBuilder *pBuilder, /* WHERE clause information */
Bitmask mExtra
){
WhereInfo *pWInfo; /* WHERE analysis context */
Parse *pParse; /* The parsing context */
WhereClause *pWC; /* The WHERE clause */
struct SrcList_item *pSrc; /* The FROM clause term to search */
Table *pTab;
sqlite3 *db;
|
| ︙ | ︙ | |||
112708 112709 112710 112711 112712 112713 112714 |
pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
rc = vtabBestIndex(pParse, pTab, pIdxInfo);
if( rc ) goto whereLoopAddVtab_exit;
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
| | | 112797 112798 112799 112800 112801 112802 112803 112804 112805 112806 112807 112808 112809 112810 112811 |
pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
rc = vtabBestIndex(pParse, pTab, pIdxInfo);
if( rc ) goto whereLoopAddVtab_exit;
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
pNew->prereq = mExtra;
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
pNew->u.vtab.omitMask = 0;
for(i=0; i<nConstraint; i++, pIdxCons++){
if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
j = pIdxCons->iTermOffset;
|
| ︙ | ︙ | |||
112835 112836 112837 112838 112839 112840 112841 |
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
| | < | 112924 112925 112926 112927 112928 112929 112930 112931 112932 112933 112934 112935 112936 112937 112938 |
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mExtra);
}else
#endif
{
rc = whereLoopAddBtree(&sSubBuild, mExtra);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
|
| ︙ | ︙ | |||
112906 112907 112908 112909 112910 112911 112912 |
pNew->iTab = iTab;
pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
mExtra = mPrior;
}
priorJoinType = pItem->jointype;
if( IsVirtual(pItem->pTab) ){
| | | 112994 112995 112996 112997 112998 112999 113000 113001 113002 113003 113004 113005 113006 113007 113008 |
pNew->iTab = iTab;
pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
mExtra = mPrior;
}
priorJoinType = pItem->jointype;
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(pBuilder, mExtra);
}else{
rc = whereLoopAddBtree(pBuilder, mExtra);
}
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(pBuilder, mExtra);
}
mPrior |= pNew->maskSelf;
|
| ︙ | ︙ | |||
113067 113068 113069 113070 113071 113072 113073 113074 113075 113076 113077 113078 113079 113080 |
rev = revSet = 0;
distinctColumns = 0;
for(j=0; j<nColumn; j++){
u8 bOnce; /* True to run the ORDER BY search loop */
/* Skip over == and IS NULL terms */
if( j<pLoop->u.btree.nEq
&& ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
){
if( i & WO_ISNULL ){
testcase( isOrderDistinct );
isOrderDistinct = 0;
}
continue;
| > | 113155 113156 113157 113158 113159 113160 113161 113162 113163 113164 113165 113166 113167 113168 113169 |
rev = revSet = 0;
distinctColumns = 0;
for(j=0; j<nColumn; j++){
u8 bOnce; /* True to run the ORDER BY search loop */
/* Skip over == and IS NULL terms */
if( j<pLoop->u.btree.nEq
&& pLoop->u.btree.nSkip==0
&& ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
){
if( i & WO_ISNULL ){
testcase( isOrderDistinct );
isOrderDistinct = 0;
}
continue;
|
| ︙ | ︙ | |||
113492 113493 113494 113495 113496 113497 113498 113499 113500 113501 113502 113503 113504 113505 |
pTab = pItem->pTab;
if( IsVirtual(pTab) ) return 0;
if( pItem->zIndex ) return 0;
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
if( pTerm ){
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
pLoop->aLTerm[0] = pTerm;
pLoop->nLTerm = 1;
pLoop->u.btree.nEq = 1;
/* TUNING: Cost of a rowid lookup is 10 */
| > | 113581 113582 113583 113584 113585 113586 113587 113588 113589 113590 113591 113592 113593 113594 113595 |
pTab = pItem->pTab;
if( IsVirtual(pTab) ) return 0;
if( pItem->zIndex ) return 0;
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
pLoop->u.btree.nSkip = 0;
pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
if( pTerm ){
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
pLoop->aLTerm[0] = pTerm;
pLoop->nLTerm = 1;
pLoop->u.btree.nEq = 1;
/* TUNING: Cost of a rowid lookup is 10 */
|
| ︙ | ︙ | |||
114035 114036 114037 114038 114039 114040 114041 114042 114043 114044 114045 114046 114047 114048 |
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
notReady = codeOneLoopStart(pWInfo, ii, notReady);
pWInfo->iContinue = pLevel->addrCont;
}
/* Done. */
return pWInfo;
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
| > | 114125 114126 114127 114128 114129 114130 114131 114132 114133 114134 114135 114136 114137 114138 114139 |
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
notReady = codeOneLoopStart(pWInfo, ii, notReady);
pWInfo->iContinue = pLevel->addrCont;
}
/* Done. */
VdbeNoopComment((v, "Begin WHERE-core"));
return pWInfo;
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
|
| ︙ | ︙ | |||
114061 114062 114063 114064 114065 114066 114067 114068 114069 114070 114071 114072 114073 114074 114075 114076 114077 114078 114079 114080 114081 114082 114083 114084 114085 114086 114087 114088 114089 |
WhereLevel *pLevel;
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
/* Generate loop termination code.
*/
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
pLevel = &pWInfo->a[i];
pLoop = pLevel->pWLoop;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->iLeftJoin ){
| > > > > > > > > < | | 114152 114153 114154 114155 114156 114157 114158 114159 114160 114161 114162 114163 114164 114165 114166 114167 114168 114169 114170 114171 114172 114173 114174 114175 114176 114177 114178 114179 114180 114181 114182 114183 114184 114185 114186 114187 114188 114189 114190 114191 114192 114193 114194 114195 114196 114197 114198 114199 114200 114201 114202 114203 114204 114205 114206 114207 114208 114209 114210 114211 114212 |
WhereLevel *pLevel;
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
/* Generate loop termination code.
*/
VdbeNoopComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];
pLoop = pLevel->pWLoop;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->addrSkip ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
}
if( pLevel->iLeftJoin ){
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|| (pLoop->wsFlags & WHERE_INDEXED)!=0 );
if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
}
if( pLoop->wsFlags & WHERE_INDEXED ){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
}else{
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
}
sqlite3VdbeJumpHere(v, addr);
}
VdbeNoopComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
/* The "break" point is here, just past the end of the outer loop.
** Set it.
*/
sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
|
| ︙ | ︙ | |||
123685 123686 123687 123688 123689 123690 123691 123692 123693 123694 123695 123696 123697 123698 | char *zTerm; /* Pointer to term buffer */ int nTerm; /* Size of zTerm in bytes */ char *aDoclist; /* Pointer to doclist buffer */ int nDoclist; /* Size of aDoclist[] in bytes */ }; SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); /* fts3.c */ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); | > > > > | 123783 123784 123785 123786 123787 123788 123789 123790 123791 123792 123793 123794 123795 123796 123797 123798 123799 123800 | char *zTerm; /* Pointer to term buffer */ int nTerm; /* Size of zTerm in bytes */ char *aDoclist; /* Pointer to doclist buffer */ int nDoclist; /* Size of aDoclist[] in bytes */ }; SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); #define fts3GetVarint32(p, piVal) ( \ (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \ ) /* fts3.c */ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); |
| ︙ | ︙ | |||
123793 123794 123795 123796 123797 123798 123799 123800 123801 123802 123803 123804 123805 |
vu >>= 7;
}while( vu!=0 );
q[-1] &= 0x7f; /* turn off high bit in final byte */
assert( q - (unsigned char *)p <= FTS3_VARINT_MAX );
return (int) (q - (unsigned char *)p);
}
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
| > > > > | > | > | > > > > > | > | > > < | | > | | > > > > > > > > > > | | | 123895 123896 123897 123898 123899 123900 123901 123902 123903 123904 123905 123906 123907 123908 123909 123910 123911 123912 123913 123914 123915 123916 123917 123918 123919 123920 123921 123922 123923 123924 123925 123926 123927 123928 123929 123930 123931 123932 123933 123934 123935 123936 123937 123938 123939 123940 123941 123942 123943 123944 123945 123946 123947 123948 123949 123950 123951 123952 123953 123954 123955 123956 123957 123958 |
vu >>= 7;
}while( vu!=0 );
q[-1] &= 0x7f; /* turn off high bit in final byte */
assert( q - (unsigned char *)p <= FTS3_VARINT_MAX );
return (int) (q - (unsigned char *)p);
}
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
v = (v & mask1) | ( (*ptr++) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
const char *pStart = p;
u32 a;
u64 b;
int shift;
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *v, 1);
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2);
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
b = (a & 0x0FFFFFFF );
for(shift=28; shift<=63; shift+=7){
u64 c = *p++;
b += (c&0x7F) << shift;
if( (c & 0x80)==0 ) break;
}
*v = b;
return p - pStart;
}
/*
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
** 32-bit integer before it is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
u32 a;
#ifndef fts3GetVarint32
GETVARINT_STEP(a, p, 0, 0x00, 0x80, *pi, 1);
#else
a = (*p++);
assert( a & 0x80 );
#endif
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
*pi = (int)(a | ((u32)(*p & 0x0F) << 28));
return 5;
}
/*
** Return the number of bytes required to encode v as a varint
*/
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64 v){
int i = 0;
|
| ︙ | ︙ | |||
125178 125179 125180 125181 125182 125183 125184 |
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
| | | | 125304 125305 125306 125307 125308 125309 125310 125311 125312 125313 125314 125315 125316 125317 125318 125319 125320 125321 |
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
zCsr += fts3GetVarint32(zCsr, &nPrefix);
}
isFirstTerm = 0;
zCsr += fts3GetVarint32(zCsr, &nSuffix);
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
if( nPrefix+nSuffix>nAlloc ){
char *zNew;
|
| ︙ | ︙ | |||
125269 125270 125271 125272 125273 125274 125275 |
sqlite3_int64 *piLeaf2 /* Selected leaf node */
){
int rc; /* Return code */
int iHeight; /* Height of this node in tree */
assert( piLeaf || piLeaf2 );
| | | 125395 125396 125397 125398 125399 125400 125401 125402 125403 125404 125405 125406 125407 125408 125409 |
sqlite3_int64 *piLeaf2 /* Selected leaf node */
){
int rc; /* Return code */
int iHeight; /* Height of this node in tree */
assert( piLeaf || piLeaf2 );
fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
char *zBlob = 0; /* Blob read from %_segments table */
int nBlob; /* Size of zBlob in bytes */
|
| ︙ | ︙ | |||
125471 125472 125473 125474 125475 125476 125477 |
char *p1 = *pp1;
char *p2 = *pp2;
while( *p1 || *p2 ){
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
| | | | 125597 125598 125599 125600 125601 125602 125603 125604 125605 125606 125607 125608 125609 125610 125611 125612 125613 125614 125615 |
char *p1 = *pp1;
char *p2 = *pp2;
while( *p1 || *p2 ){
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else iCol1 = 0;
if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else iCol2 = 0;
if( iCol1==iCol2 ){
sqlite3_int64 i1 = 0; /* Last position from pp1 */
sqlite3_int64 i2 = 0; /* Last position from pp2 */
sqlite3_int64 iPrev = 0;
|
| ︙ | ︙ | |||
125568 125569 125570 125571 125572 125573 125574 |
/* Never set both isSaveLeft and isExact for the same invocation. */
assert( isSaveLeft==0 || isExact==0 );
assert( p!=0 && *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
| | | | 125694 125695 125696 125697 125698 125699 125700 125701 125702 125703 125704 125705 125706 125707 125708 125709 125710 125711 125712 |
/* Never set both isSaveLeft and isExact for the same invocation. */
assert( isSaveLeft==0 || isExact==0 );
assert( p!=0 && *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
}
if( *p2==POS_COLUMN ){
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
}
while( 1 ){
if( iCol1==iCol2 ){
char *pSave = p;
sqlite3_int64 iPrev = 0;
sqlite3_int64 iPos1 = 0;
|
| ︙ | ︙ | |||
125622 125623 125624 125625 125626 125627 125628 |
fts3ColumnlistCopy(0, &p1);
fts3ColumnlistCopy(0, &p2);
assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 );
if( 0==*p1 || 0==*p2 ) break;
p1++;
| | | | | | 125748 125749 125750 125751 125752 125753 125754 125755 125756 125757 125758 125759 125760 125761 125762 125763 125764 125765 125766 125767 125768 125769 125770 125771 125772 125773 125774 125775 125776 125777 125778 125779 125780 125781 |
fts3ColumnlistCopy(0, &p1);
fts3ColumnlistCopy(0, &p2);
assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 );
if( 0==*p1 || 0==*p2 ) break;
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
}
/* Advance pointer p1 or p2 (whichever corresponds to the smaller of
** iCol1 and iCol2) so that it points to either the 0x00 that marks the
** end of the position list, or the 0x01 that precedes the next
** column-number in the position list.
*/
else if( iCol1<iCol2 ){
fts3ColumnlistCopy(0, &p1);
if( 0==*p1 ) break;
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
}else{
fts3ColumnlistCopy(0, &p2);
if( 0==*p2 ) break;
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
}
}
fts3PoslistCopy(0, &p2);
fts3PoslistCopy(0, &p1);
*pp1 = p1;
*pp2 = p2;
|
| ︙ | ︙ | |||
128808 128809 128810 128811 128812 128813 128814 |
/* aMI[iCol*3 + 1] = Number of occurrences
** aMI[iCol*3 + 2] = Number of rows containing at least one instance
*/
pExpr->aMI[iCol*3 + 1] += iCnt;
pExpr->aMI[iCol*3 + 2] += (iCnt>0);
if( *p==0x00 ) break;
p++;
| | | 128934 128935 128936 128937 128938 128939 128940 128941 128942 128943 128944 128945 128946 128947 128948 |
/* aMI[iCol*3 + 1] = Number of occurrences
** aMI[iCol*3 + 2] = Number of rows containing at least one instance
*/
pExpr->aMI[iCol*3 + 1] += iCnt;
pExpr->aMI[iCol*3 + 2] += (iCnt>0);
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
}
}
fts3EvalUpdateCounts(pExpr->pLeft);
fts3EvalUpdateCounts(pExpr->pRight);
}
}
|
| ︙ | ︙ | |||
129109 129110 129111 129112 129113 129114 129115 |
if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
}
if( pIter==0 ) return SQLITE_OK;
if( *pIter==0x01 ){
pIter++;
| | | | 129235 129236 129237 129238 129239 129240 129241 129242 129243 129244 129245 129246 129247 129248 129249 129250 129251 129252 129253 129254 129255 129256 129257 |
if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
}
if( pIter==0 ) return SQLITE_OK;
if( *pIter==0x01 ){
pIter++;
pIter += fts3GetVarint32(pIter, &iThis);
}else{
iThis = 0;
}
while( iThis<iCol ){
fts3ColumnlistCopy(0, &pIter);
if( *pIter==0x00 ) return 0;
pIter++;
pIter += fts3GetVarint32(pIter, &iThis);
}
*ppOut = ((iCol==iThis)?pIter:0);
return SQLITE_OK;
}
/*
|
| ︙ | ︙ | |||
134566 134567 134568 134569 134570 134571 134572 | assert( !fts3SegReaderIsPending(pReader) ); rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2); if( rc!=SQLITE_OK ) return rc; /* Because of the FTS3_NODE_PADDING bytes of padding, the following is ** safe (no risk of overread) even if the node data is corrupted. */ | | | | 134692 134693 134694 134695 134696 134697 134698 134699 134700 134701 134702 134703 134704 134705 134706 134707 |
assert( !fts3SegReaderIsPending(pReader) );
rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
if( rc!=SQLITE_OK ) return rc;
/* Because of the FTS3_NODE_PADDING bytes of padding, the following is
** safe (no risk of overread) even if the node data is corrupted. */
pNext += fts3GetVarint32(pNext, &nPrefix);
pNext += fts3GetVarint32(pNext, &nSuffix);
if( nPrefix<0 || nSuffix<=0
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
){
return FTS_CORRUPT_VTAB;
}
if( nPrefix+nSuffix>pReader->nTermAlloc ){
|
| ︙ | ︙ | |||
134590 134591 134592 134593 134594 134595 134596 | rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX); if( rc!=SQLITE_OK ) return rc; memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix); pReader->nTerm = nPrefix+nSuffix; pNext += nSuffix; | | | 134716 134717 134718 134719 134720 134721 134722 134723 134724 134725 134726 134727 134728 134729 134730 | rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX); if( rc!=SQLITE_OK ) return rc; memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix); pReader->nTerm = nPrefix+nSuffix; pNext += nSuffix; pNext += fts3GetVarint32(pNext, &pReader->nDoclist); pReader->aDoclist = pNext; pReader->pOffsetList = 0; /* Check that the doclist does not appear to extend past the end of the ** b-tree node. And that the final byte of the doclist is 0x00. If either ** of these statements is untrue, then the data structure is corrupt. */ |
| ︙ | ︙ | |||
135751 135752 135753 135754 135755 135756 135757 |
nList -= (int)(p - pList);
pList = p;
if( nList==0 ){
break;
}
p = &pList[1];
| | | 135877 135878 135879 135880 135881 135882 135883 135884 135885 135886 135887 135888 135889 135890 135891 |
nList -= (int)(p - pList);
pList = p;
if( nList==0 ){
break;
}
p = &pList[1];
p += fts3GetVarint32(p, &iCurrent);
}
if( bZero && &pList[nList]!=pEnd ){
memset(&pList[nList], 0, pEnd - &pList[nList]);
}
*ppList = pList;
*pnList = nList;
|
| ︙ | ︙ | |||
136716 136717 136718 136719 136720 136721 136722 |
assert( p->aNode );
if( p->iChild && bFirst==0 ) p->iChild++;
if( p->iOff>=p->nNode ){
/* EOF */
p->aNode = 0;
}else{
if( bFirst==0 ){
| | | | | 136842 136843 136844 136845 136846 136847 136848 136849 136850 136851 136852 136853 136854 136855 136856 136857 136858 136859 136860 136861 136862 136863 136864 136865 136866 |
assert( p->aNode );
if( p->iChild && bFirst==0 ) p->iChild++;
if( p->iOff>=p->nNode ){
/* EOF */
p->aNode = 0;
}else{
if( bFirst==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
p->term.n = nPrefix+nSuffix;
p->iOff += nSuffix;
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
}
}
}
assert( p->iOff<=p->nNode );
|
| ︙ | ︙ | |||
137778 137779 137780 137781 137782 137783 137784 | i = pHint->n-2; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); | | | 137904 137905 137906 137907 137908 137909 137910 137911 137912 137913 137914 137915 137916 137917 137918 | i = pHint->n-2; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); if( i!=nHint ) return SQLITE_CORRUPT_VTAB; return SQLITE_OK; } /* |
| ︙ | ︙ | |||
138771 138772 138773 138774 138775 138776 138777 |
** When this function is called, *pp points to the start of an element of
** the list. *piPos contains the value of the previous entry in the list.
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
static void fts3GetDeltaPosition(char **pp, int *piPos){
int iVal;
| | | 138897 138898 138899 138900 138901 138902 138903 138904 138905 138906 138907 138908 138909 138910 138911 |
** When this function is called, *pp points to the start of an element of
** the list. *piPos contains the value of the previous entry in the list.
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
static void fts3GetDeltaPosition(char **pp, int *piPos){
int iVal;
*pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
}
/*
** Helper function for fts3ExprIterate() (see below).
*/
static int fts3ExprIterate2(
|
| ︙ | ︙ |
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.2" #define SQLITE_VERSION_NUMBER 3008002 | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.2" #define SQLITE_VERSION_NUMBER 3008002 #define SQLITE_SOURCE_ID "2013-11-14 19:34:10 10d59226382adcb8016fc2d927e5a0c0b36f3980" /* ** 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 |
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc |
| ︙ | ︙ |
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
1683 1684 1685 1686 1687 1688 1689 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c | | | 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -D_HAVE_SQLITE_CONFIG_H -DSQLITE_USE_MALLOC_H -DSQLITE_USE_MSIZE -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
| ︙ | ︙ |
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 |
LIBS = $(LIBS) $(SSLLIB)
LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
!endif
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DSQLITE_THREADSAFE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
| > | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
LIBS = $(LIBS) $(SSLLIB)
LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
!endif
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DSQLITE_THREADSAFE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
/Dlocaltime=fossil_localtime \
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
/DSQLITE_WIN32_NO_ANSI
SRC = add_.c \
allrepo_.c \
attach_.c \
|
| ︙ | ︙ |