Fossil SCM

merge cleanX branch changes (which all come from trunk)

jan.nijtmans 2013-10-30 10:53 cleanX-no-clean-glob merge
Commit 6934dd3cc0988dd91115a3e15e180719731913d9
81 files changed +1 -1 +186 -137 +1 -12 +1 -12 +77 -25 +1 -1 +1 -1 +1 -1 +1 -1 +277 -8 +38 -23 +38 -23 +2 -2 +26 +12 -7 +6 -1 +11 -3 +11 -3 +124 +1 +1 -1 +27 -11 +20 -6 +1 -1 +3 -3 +10 -3 +1 -1 +14 -1 +17 +71 -206 +1 -1 +20 -7 +1 -1 +1 -1 +1 -1 +3 -3 +2 -1 +38 -5 +41 -30 +6 -6 +1 +5 +2 -1 +3 -6 +53 -4 +1 -1 +3 -3 +1 -1 +2022 -1223 +14 -14 +1 -1 +2 -1 +6 +3 -6 +2 -2 +1 -1 +1 -2 +19 -19 +262 -42 +8 -7 +3 -6 +2 -20 +28 -1 +1 -8 +6 -3 +6 -3 +7 -7 +1 -1 +1 -1 +18 -11 +2 -2 +3 -3 +3 -3 +38 -28 +1 -1 +2 -1 +28 +1 -1 +2 -2 +1 -1 +15 -3
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-1.27
1
+1.28
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.27
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.28
2
+186 -137
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -185,11 +185,11 @@
185185
#endif
186186
187187
#define UCHAR(c) ((unsigned char)(c))
188188
189189
190
-#define JIM_VERSION 73
190
+#define JIM_VERSION 74
191191
192192
#define JIM_OK 0
193193
#define JIM_ERR 1
194194
#define JIM_RETURN 2
195195
#define JIM_BREAK 3
@@ -321,14 +321,14 @@
321321
#define Jim_GetHashTableSize(ht) ((ht)->size)
322322
#define Jim_GetHashTableUsed(ht) ((ht)->used)
323323
324324
325325
typedef struct Jim_Obj {
326
- int refCount;
327326
char *bytes;
328
- int length;
329327
const struct Jim_ObjType *typePtr;
328
+ int refCount;
329
+ int length;
330330
331331
union {
332332
333333
jim_wide wideValue;
334334
@@ -665,12 +665,10 @@
665665
666666
667667
JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
668668
JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
669669
JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
670
-JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes,
671
- int length);
672670
JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
673671
Jim_Obj *objPtr);
674672
JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
675673
int *lenPtr);
676674
JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -877,10 +875,12 @@
877875
JIM_EXPORT void Jim_HistoryShow(void);
878876
879877
880878
JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
881879
JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
880
+JIM_EXPORT int Jim_CheckSignal(Jim_Interp *interp);
881
+#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
882882
883883
884884
JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
885885
JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
886886
@@ -5671,10 +5671,13 @@
56715671
#ifdef JIM_MAINTAINER
56725672
#define JIM_DEBUG_COMMAND
56735673
#define JIM_DEBUG_PANIC
56745674
#endif
56755675
5676
+
5677
+#define JIM_INTEGER_SPACE 24
5678
+
56765679
const char *jim_tt_name(int type);
56775680
56785681
#ifdef JIM_DEBUG_PANIC
56795682
static void JimPanicDump(int panic_condition, const char *fmt, ...);
56805683
#define JimPanic(X) JimPanicDump X
@@ -5690,10 +5693,11 @@
56905693
static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
56915694
int flags);
56925695
static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
56935696
static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
56945697
static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
5698
+static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
56955699
static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
56965700
const char *prefix, const char *const *tablePtr, const char *name);
56975701
static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
56985702
static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
56995703
static int JimSign(jim_wide w);
@@ -5934,15 +5938,42 @@
59345938
}
59355939
return n;
59365940
}
59375941
#endif
59385942
5939
-int Jim_WideToString(char *buf, jim_wide wideValue)
5943
+static int JimWideToString(char *buf, jim_wide wideValue)
59405944
{
5941
- const char *fmt = "%" JIM_WIDE_MODIFIER;
5945
+ int pos = 0;
59425946
5943
- return sprintf(buf, fmt, wideValue);
5947
+ if (wideValue == 0) {
5948
+ buf[pos++] = '0';
5949
+ }
5950
+ else {
5951
+ char tmp[JIM_INTEGER_SPACE];
5952
+ int num = 0;
5953
+ int i;
5954
+
5955
+ if (wideValue < 0) {
5956
+ buf[pos++] = '-';
5957
+
5958
+ i = wideValue % 10;
5959
+ tmp[num++] = (i > 0) ? (10 - i) : -i;
5960
+ wideValue /= -10;
5961
+ }
5962
+
5963
+ while (wideValue) {
5964
+ tmp[num++] = wideValue % 10;
5965
+ wideValue /= 10;
5966
+ }
5967
+
5968
+ for (i = 0; i < num; i++) {
5969
+ buf[pos++] = '0' + tmp[num - i - 1];
5970
+ }
5971
+ }
5972
+ buf[pos] = 0;
5973
+
5974
+ return pos;
59445975
}
59455976
59465977
static int JimCheckConversion(const char *str, const char *endptr)
59475978
{
59485979
if (str[0] == '\0' || str == endptr) {
@@ -6229,10 +6260,18 @@
62296260
ht->sizemask = 0;
62306261
ht->used = 0;
62316262
ht->collisions = 0;
62326263
}
62336264
6265
+static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6266
+{
6267
+ iter->ht = ht;
6268
+ iter->index = -1;
6269
+ iter->entry = NULL;
6270
+ iter->nextEntry = NULL;
6271
+}
6272
+
62346273
62356274
int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
62366275
{
62376276
JimResetHashTable(ht);
62386277
ht->type = type;
@@ -6408,15 +6447,11 @@
64086447
}
64096448
64106449
Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
64116450
{
64126451
Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6413
-
6414
- iter->ht = ht;
6415
- iter->index = -1;
6416
- iter->entry = NULL;
6417
- iter->nextEntry = NULL;
6452
+ JimInitHashTableIterator(ht, iter);
64186453
return iter;
64196454
}
64206455
64216456
Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
64226457
{
@@ -10500,12 +10535,10 @@
1050010535
int Jim_GetExitCode(Jim_Interp *interp)
1050110536
{
1050210537
return interp->exitCode;
1050310538
}
1050410539
10505
-#define JIM_INTEGER_SPACE 24
10506
-
1050710540
static void UpdateStringOfInt(struct Jim_Obj *objPtr);
1050810541
static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
1050910542
1051010543
static const Jim_ObjType intObjType = {
1051110544
"int",
@@ -10522,16 +10555,16 @@
1052210555
UpdateStringOfInt,
1052310556
JIM_TYPE_NONE,
1052410557
};
1052510558
1052610559
10527
-void UpdateStringOfInt(struct Jim_Obj *objPtr)
10560
+static void UpdateStringOfInt(struct Jim_Obj *objPtr)
1052810561
{
1052910562
int len;
1053010563
char buf[JIM_INTEGER_SPACE + 1];
1053110564
10532
- len = Jim_WideToString(buf, JimWideValue(objPtr));
10565
+ len = JimWideToString(buf, JimWideValue(objPtr));
1053310566
objPtr->bytes = Jim_Alloc(len + 1);
1053410567
memcpy(objPtr->bytes, buf, len + 1);
1053510568
objPtr->length = len;
1053610569
}
1053710570
@@ -10755,11 +10788,11 @@
1075510788
}
1075610789
1075710790
#define JIM_ELESTR_SIMPLE 0
1075810791
#define JIM_ELESTR_BRACE 1
1075910792
#define JIM_ELESTR_QUOTE 2
10760
-static int ListElementQuotingType(const char *s, int len)
10793
+static unsigned char ListElementQuotingType(const char *s, int len)
1076110794
{
1076210795
int i, level, blevel, trySimple = 1;
1076310796
1076410797
1076510798
if (len == 0)
@@ -10903,17 +10936,23 @@
1090310936
return p - q;
1090410937
}
1090510938
1090610939
static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
1090710940
{
10941
+ #define STATIC_QUOTING_LEN 32
1090810942
int i, bufLen, realLength;
1090910943
const char *strRep;
1091010944
char *p;
10911
- int *quotingType;
10945
+ unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
1091210946
1091310947
10914
- quotingType = Jim_Alloc(sizeof(int) * objc + 1);
10948
+ if (objc > STATIC_QUOTING_LEN) {
10949
+ quotingType = Jim_Alloc(objc);
10950
+ }
10951
+ else {
10952
+ quotingType = staticQuoting;
10953
+ }
1091510954
bufLen = 0;
1091610955
for (i = 0; i < objc; i++) {
1091710956
int len;
1091810957
1091910958
strRep = Jim_GetString(objv[i], &len);
@@ -10975,11 +11014,14 @@
1097511014
realLength++;
1097611015
}
1097711016
}
1097811017
*p = '\0';
1097911018
objPtr->length = realLength;
10980
- Jim_Free(quotingType);
11019
+
11020
+ if (quotingType != staticQuoting) {
11021
+ Jim_Free(quotingType);
11022
+ }
1098111023
}
1098211024
1098311025
static void UpdateStringOfList(struct Jim_Obj *objPtr)
1098411026
{
1098511027
JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -11000,11 +11042,11 @@
1100011042
if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
1100111043
Jim_Obj **listObjPtrPtr;
1100211044
int len;
1100311045
int i;
1100411046
11005
- Jim_DictPairs(interp, objPtr, &listObjPtrPtr, &len);
11047
+ listObjPtrPtr = JimDictPairs(objPtr, &len);
1100611048
for (i = 0; i < len; i++) {
1100711049
Jim_IncrRefCount(listObjPtrPtr[i]);
1100811050
}
1100911051
1101011052
@@ -11225,14 +11267,22 @@
1122511267
int requiredLen = currentLen + elemc;
1122611268
int i;
1122711269
Jim_Obj **point;
1122811270
1122911271
if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11230
- listPtr->internalRep.listValue.maxLen = requiredLen * 2;
11272
+ if (requiredLen < 2) {
11273
+
11274
+ requiredLen = 4;
11275
+ }
11276
+ else {
11277
+ requiredLen *= 2;
11278
+ }
1123111279
1123211280
listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11233
- sizeof(Jim_Obj *) * listPtr->internalRep.listValue.maxLen);
11281
+ sizeof(Jim_Obj *) * requiredLen);
11282
+
11283
+ listPtr->internalRep.listValue.maxLen = requiredLen;
1123411284
}
1123511285
if (idx < 0) {
1123611286
idx = currentLen;
1123711287
}
1123811288
point = listPtr->internalRep.listValue.ele + idx;
@@ -11523,55 +11573,53 @@
1152311573
}
1152411574
1152511575
void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
1152611576
{
1152711577
Jim_HashTable *ht, *dupHt;
11528
- Jim_HashTableIterator *htiter;
11578
+ Jim_HashTableIterator htiter;
1152911579
Jim_HashEntry *he;
1153011580
1153111581
1153211582
ht = srcPtr->internalRep.ptr;
1153311583
dupHt = Jim_Alloc(sizeof(*dupHt));
1153411584
Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
1153511585
if (ht->size != 0)
1153611586
Jim_ExpandHashTable(dupHt, ht->size);
1153711587
11538
- htiter = Jim_GetHashTableIterator(ht);
11539
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11588
+ JimInitHashTableIterator(ht, &htiter);
11589
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1154011590
const Jim_Obj *keyObjPtr = he->key;
1154111591
Jim_Obj *valObjPtr = he->u.val;
1154211592
1154311593
Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
1154411594
Jim_IncrRefCount(valObjPtr);
1154511595
Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
1154611596
}
11547
- Jim_FreeHashTableIterator(htiter);
1154811597
1154911598
dupPtr->internalRep.ptr = dupHt;
1155011599
dupPtr->typePtr = &dictObjType;
1155111600
}
1155211601
1155311602
static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
1155411603
{
1155511604
Jim_HashTable *ht;
11556
- Jim_HashTableIterator *htiter;
11605
+ Jim_HashTableIterator htiter;
1155711606
Jim_HashEntry *he;
1155811607
Jim_Obj **objv;
1155911608
int i;
1156011609
1156111610
ht = dictPtr->internalRep.ptr;
1156211611
1156311612
1156411613
objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11565
- htiter = Jim_GetHashTableIterator(ht);
11614
+ JimInitHashTableIterator(ht, &htiter);
1156611615
i = 0;
11567
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11616
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1156811617
objv[i++] = (Jim_Obj *)he->key;
1156911618
objv[i++] = he->u.val;
1157011619
}
1157111620
*len = i;
11572
- Jim_FreeHashTableIterator(htiter);
1157311621
return objv;
1157411622
}
1157511623
1157611624
static void UpdateStringOfDict(struct Jim_Obj *objPtr)
1157711625
{
@@ -12089,14 +12137,15 @@
1208912137
1209012138
1209112139
typedef struct Jim_ExprOperator
1209212140
{
1209312141
const char *name;
12094
- int precedence;
12095
- int arity;
1209612142
int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12097
- int lazy;
12143
+ unsigned char precedence;
12144
+ unsigned char arity;
12145
+ unsigned char lazy;
12146
+ unsigned char namelen;
1209812147
} Jim_ExprOperator;
1209912148
1210012149
static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
1210112150
{
1210212151
Jim_IncrRefCount(obj);
@@ -12774,93 +12823,96 @@
1277412823
LAZY_OP,
1277512824
LAZY_LEFT,
1277612825
LAZY_RIGHT
1277712826
};
1277812827
12828
+#define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
12829
+
1277912830
static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12780
- {"*", 200, 2, JimExprOpBin, LAZY_NONE},
12781
- {"/", 200, 2, JimExprOpBin, LAZY_NONE},
12782
- {"%", 200, 2, JimExprOpIntBin, LAZY_NONE},
12783
-
12784
- {"-", 100, 2, JimExprOpBin, LAZY_NONE},
12785
- {"+", 100, 2, JimExprOpBin, LAZY_NONE},
12786
-
12787
- {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12788
- {">>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12789
-
12790
- {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12791
- {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12792
-
12793
- {"<", 80, 2, JimExprOpBin, LAZY_NONE},
12794
- {">", 80, 2, JimExprOpBin, LAZY_NONE},
12795
- {"<=", 80, 2, JimExprOpBin, LAZY_NONE},
12796
- {">=", 80, 2, JimExprOpBin, LAZY_NONE},
12797
-
12798
- {"==", 70, 2, JimExprOpBin, LAZY_NONE},
12799
- {"!=", 70, 2, JimExprOpBin, LAZY_NONE},
12800
-
12801
- {"&", 50, 2, JimExprOpIntBin, LAZY_NONE},
12802
- {"^", 49, 2, JimExprOpIntBin, LAZY_NONE},
12803
- {"|", 48, 2, JimExprOpIntBin, LAZY_NONE},
12804
-
12805
- {"&&", 10, 2, NULL, LAZY_OP},
12806
- {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT},
12807
- {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12808
-
12809
- {"||", 9, 2, NULL, LAZY_OP},
12810
- {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT},
12811
- {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12812
-
12813
- {"?", 5, 2, JimExprOpNull, LAZY_OP},
12814
- {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
12815
- {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12816
-
12817
- {":", 5, 2, JimExprOpNull, LAZY_OP},
12818
- {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
12819
- {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12820
-
12821
- {"**", 250, 2, JimExprOpBin, LAZY_NONE},
12822
-
12823
- {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE},
12824
- {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE},
12825
-
12826
- {"in", 55, 2, JimExprOpStrBin, LAZY_NONE},
12827
- {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE},
12828
-
12829
- {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE},
12830
- {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE},
12831
- {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12832
- {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12833
-
12834
-
12835
-
12836
- {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12837
- {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12838
- {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12839
- {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12840
- {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
12841
- {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
12831
+ OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12832
+ OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12833
+ OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12834
+
12835
+ OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12836
+ OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12837
+
12838
+ OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12839
+ OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12840
+
12841
+ OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12842
+ OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12843
+
12844
+ OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12845
+ OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12846
+ OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12847
+ OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12848
+
12849
+ OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12850
+ OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12851
+
12852
+ OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12853
+ OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12854
+ OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12855
+
12856
+ OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12857
+ OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12858
+ OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12859
+
12860
+ OPRINIT("||", 9, 2, NULL, LAZY_OP),
12861
+ OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12862
+ OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12863
+
12864
+ OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12865
+ OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12866
+ OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12867
+
12868
+ OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12869
+ OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12870
+ OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12871
+
12872
+ OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12873
+
12874
+ OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12875
+ OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12876
+
12877
+ OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12878
+ OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12879
+
12880
+ OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12881
+ OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12882
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12883
+ OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12884
+
12885
+
12886
+
12887
+ OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12888
+ OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12889
+ OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12890
+ OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12891
+ OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12892
+ OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
1284212893
1284312894
#ifdef JIM_MATH_FUNCTIONS
12844
- {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12845
- {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12846
- {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12847
- {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12848
- {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12849
- {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12850
- {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12851
- {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12852
- {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12853
- {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12854
- {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12855
- {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12856
- {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12857
- {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12858
- {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12859
- {"pow", 400, 2, JimExprOpBin, LAZY_NONE},
12895
+ OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896
+ OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897
+ OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898
+ OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899
+ OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900
+ OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901
+ OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902
+ OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903
+ OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904
+ OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905
+ OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12906
+ OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12907
+ OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12908
+ OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12909
+ OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12910
+ OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
1286012911
#endif
1286112912
};
12913
+#undef OPRINIT
1286212914
1286312915
#define JIM_EXPR_OPERATORS_NUM \
1286412916
(sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
1286512917
1286612918
static int JimParseExpression(struct JimParserCtx *pc)
@@ -13026,20 +13078,18 @@
1302613078
int i;
1302713079
int bestIdx = -1, bestLen = 0;
1302813080
1302913081
1303013082
for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13031
- const char *opname;
13032
- int oplen;
13083
+ const char * const opname = Jim_ExprOperators[i].name;
13084
+ const int oplen = Jim_ExprOperators[i].namelen;
1303313085
13034
- opname = Jim_ExprOperators[i].name;
13035
- if (opname == NULL) {
13086
+ if (opname == NULL || opname[0] != pc->p[0]) {
1303613087
continue;
1303713088
}
13038
- oplen = strlen(opname);
1303913089
13040
- if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) {
13090
+ if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
1304113091
bestIdx = i + JIM_TT_EXPR_OP;
1304213092
bestLen = oplen;
1304313093
}
1304413094
}
1304513095
if (bestIdx == -1) {
@@ -13111,12 +13161,12 @@
1311113161
};
1311213162
1311313163
1311413164
typedef struct ExprByteCode
1311513165
{
13116
- int len;
1311713166
ScriptToken *token;
13167
+ int len;
1311813168
int inUse;
1311913169
} ExprByteCode;
1312013170
1312113171
static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
1312213172
{
@@ -13855,16 +13905,16 @@
1385513905
1385613906
1385713907
1385813908
typedef struct ScanFmtPartDescr
1385913909
{
13860
- char type;
13861
- char modifier;
13910
+ char *arg;
13911
+ char *prefix;
1386213912
size_t width;
1386313913
int pos;
13864
- char *arg;
13865
- char *prefix;
13914
+ char type;
13915
+ char modifier;
1386613916
} ScanFmtPartDescr;
1386713917
1386813918
1386913919
typedef struct ScanFmtStringObj
1387013920
{
@@ -14871,12 +14921,12 @@
1487114921
}
1487214922
1487314923
if (retcode == JIM_OK && argc) {
1487414924
1487514925
retcode = JimInvokeCommand(interp, argc, argv);
14876
- if (interp->signal_level && interp->sigmask) {
14877
-
14926
+
14927
+ if (Jim_CheckSignal(interp)) {
1487814928
retcode = JIM_SIGNAL;
1487914929
}
1488014930
}
1488114931
1488214932
@@ -15446,17 +15496,17 @@
1544615496
if (he) {
1544715497
callback(interp, listObjPtr, he, type);
1544815498
}
1544915499
}
1545015500
else {
15451
- Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
15452
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
15501
+ Jim_HashTableIterator htiter;
15502
+ JimInitHashTableIterator(ht, &htiter);
15503
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1545315504
if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
1545415505
callback(interp, listObjPtr, he, type);
1545515506
}
1545615507
}
15457
- Jim_FreeHashTableIterator(htiter);
1545815508
}
1545915509
return listObjPtr;
1546015510
}
1546115511
1546215512
@@ -17795,11 +17845,11 @@
1779517845
if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
1779617846
sig++;
1779717847
}
1779817848
1779917849
interp->signal_level += sig;
17800
- if (interp->signal_level && interp->sigmask) {
17850
+ if (Jim_CheckSignal(interp)) {
1780117851
1780217852
exitCode = JIM_SIGNAL;
1780317853
}
1780417854
else {
1780517855
exitCode = Jim_EvalObj(interp, argv[0]);
@@ -17951,25 +18001,24 @@
1795118001
1795218002
1795318003
static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1795418004
{
1795518005
Jim_Obj *listObjPtr;
17956
- Jim_HashTableIterator *htiter;
18006
+ Jim_HashTableIterator htiter;
1795718007
Jim_HashEntry *he;
1795818008
1795918009
listObjPtr = Jim_NewListObj(interp, NULL, 0);
1796018010
17961
- htiter = Jim_GetHashTableIterator(&interp->references);
17962
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
18011
+ JimInitHashTableIterator(&interp->references, &htiter);
18012
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1796318013
char buf[JIM_REFERENCE_SPACE + 1];
1796418014
Jim_Reference *refPtr = he->u.val;
1796518015
const unsigned long *refId = he->key;
1796618016
1796718017
JimFormatReference(buf, refPtr, *refId);
1796818018
Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
1796918019
}
17970
- Jim_FreeHashTableIterator(htiter);
1797118020
Jim_SetResult(interp, listObjPtr);
1797218021
return JIM_OK;
1797318022
}
1797418023
#endif
1797518024
@@ -18005,17 +18054,17 @@
1800518054
{
1800618055
Jim_HashEntry *he;
1800718056
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
1800818057
1800918058
18010
- Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
18011
- while ((he = Jim_NextHashEntry(htiter)) != NULL) {
18059
+ Jim_HashTableIterator htiter;
18060
+ JimInitHashTableIterator(ht, &htiter);
18061
+ while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
1801218062
if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
1801318063
callback(interp, listObjPtr, he, type);
1801418064
}
1801518065
}
18016
- Jim_FreeHashTableIterator(htiter);
1801718066
1801818067
return listObjPtr;
1801918068
}
1802018069
1802118070
1802218071
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -185,11 +185,11 @@
185 #endif
186
187 #define UCHAR(c) ((unsigned char)(c))
188
189
190 #define JIM_VERSION 73
191
192 #define JIM_OK 0
193 #define JIM_ERR 1
194 #define JIM_RETURN 2
195 #define JIM_BREAK 3
@@ -321,14 +321,14 @@
321 #define Jim_GetHashTableSize(ht) ((ht)->size)
322 #define Jim_GetHashTableUsed(ht) ((ht)->used)
323
324
325 typedef struct Jim_Obj {
326 int refCount;
327 char *bytes;
328 int length;
329 const struct Jim_ObjType *typePtr;
 
 
330
331 union {
332
333 jim_wide wideValue;
334
@@ -665,12 +665,10 @@
665
666
667 JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
668 JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
669 JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
670 JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes,
671 int length);
672 JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
673 Jim_Obj *objPtr);
674 JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
675 int *lenPtr);
676 JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -877,10 +875,12 @@
877 JIM_EXPORT void Jim_HistoryShow(void);
878
879
880 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
881 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
 
 
882
883
884 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
885 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
886
@@ -5671,10 +5671,13 @@
5671 #ifdef JIM_MAINTAINER
5672 #define JIM_DEBUG_COMMAND
5673 #define JIM_DEBUG_PANIC
5674 #endif
5675
 
 
 
5676 const char *jim_tt_name(int type);
5677
5678 #ifdef JIM_DEBUG_PANIC
5679 static void JimPanicDump(int panic_condition, const char *fmt, ...);
5680 #define JimPanic(X) JimPanicDump X
@@ -5690,10 +5693,11 @@
5690 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5691 int flags);
5692 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5693 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5694 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
 
5695 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
5696 const char *prefix, const char *const *tablePtr, const char *name);
5697 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
5698 static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
5699 static int JimSign(jim_wide w);
@@ -5934,15 +5938,42 @@
5934 }
5935 return n;
5936 }
5937 #endif
5938
5939 int Jim_WideToString(char *buf, jim_wide wideValue)
5940 {
5941 const char *fmt = "%" JIM_WIDE_MODIFIER;
5942
5943 return sprintf(buf, fmt, wideValue);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5944 }
5945
5946 static int JimCheckConversion(const char *str, const char *endptr)
5947 {
5948 if (str[0] == '\0' || str == endptr) {
@@ -6229,10 +6260,18 @@
6229 ht->sizemask = 0;
6230 ht->used = 0;
6231 ht->collisions = 0;
6232 }
6233
 
 
 
 
 
 
 
 
6234
6235 int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
6236 {
6237 JimResetHashTable(ht);
6238 ht->type = type;
@@ -6408,15 +6447,11 @@
6408 }
6409
6410 Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
6411 {
6412 Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6413
6414 iter->ht = ht;
6415 iter->index = -1;
6416 iter->entry = NULL;
6417 iter->nextEntry = NULL;
6418 return iter;
6419 }
6420
6421 Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
6422 {
@@ -10500,12 +10535,10 @@
10500 int Jim_GetExitCode(Jim_Interp *interp)
10501 {
10502 return interp->exitCode;
10503 }
10504
10505 #define JIM_INTEGER_SPACE 24
10506
10507 static void UpdateStringOfInt(struct Jim_Obj *objPtr);
10508 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10509
10510 static const Jim_ObjType intObjType = {
10511 "int",
@@ -10522,16 +10555,16 @@
10522 UpdateStringOfInt,
10523 JIM_TYPE_NONE,
10524 };
10525
10526
10527 void UpdateStringOfInt(struct Jim_Obj *objPtr)
10528 {
10529 int len;
10530 char buf[JIM_INTEGER_SPACE + 1];
10531
10532 len = Jim_WideToString(buf, JimWideValue(objPtr));
10533 objPtr->bytes = Jim_Alloc(len + 1);
10534 memcpy(objPtr->bytes, buf, len + 1);
10535 objPtr->length = len;
10536 }
10537
@@ -10755,11 +10788,11 @@
10755 }
10756
10757 #define JIM_ELESTR_SIMPLE 0
10758 #define JIM_ELESTR_BRACE 1
10759 #define JIM_ELESTR_QUOTE 2
10760 static int ListElementQuotingType(const char *s, int len)
10761 {
10762 int i, level, blevel, trySimple = 1;
10763
10764
10765 if (len == 0)
@@ -10903,17 +10936,23 @@
10903 return p - q;
10904 }
10905
10906 static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
10907 {
 
10908 int i, bufLen, realLength;
10909 const char *strRep;
10910 char *p;
10911 int *quotingType;
10912
10913
10914 quotingType = Jim_Alloc(sizeof(int) * objc + 1);
 
 
 
 
 
10915 bufLen = 0;
10916 for (i = 0; i < objc; i++) {
10917 int len;
10918
10919 strRep = Jim_GetString(objv[i], &len);
@@ -10975,11 +11014,14 @@
10975 realLength++;
10976 }
10977 }
10978 *p = '\0';
10979 objPtr->length = realLength;
10980 Jim_Free(quotingType);
 
 
 
10981 }
10982
10983 static void UpdateStringOfList(struct Jim_Obj *objPtr)
10984 {
10985 JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -11000,11 +11042,11 @@
11000 if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11001 Jim_Obj **listObjPtrPtr;
11002 int len;
11003 int i;
11004
11005 Jim_DictPairs(interp, objPtr, &listObjPtrPtr, &len);
11006 for (i = 0; i < len; i++) {
11007 Jim_IncrRefCount(listObjPtrPtr[i]);
11008 }
11009
11010
@@ -11225,14 +11267,22 @@
11225 int requiredLen = currentLen + elemc;
11226 int i;
11227 Jim_Obj **point;
11228
11229 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11230 listPtr->internalRep.listValue.maxLen = requiredLen * 2;
 
 
 
 
 
 
11231
11232 listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11233 sizeof(Jim_Obj *) * listPtr->internalRep.listValue.maxLen);
 
 
11234 }
11235 if (idx < 0) {
11236 idx = currentLen;
11237 }
11238 point = listPtr->internalRep.listValue.ele + idx;
@@ -11523,55 +11573,53 @@
11523 }
11524
11525 void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
11526 {
11527 Jim_HashTable *ht, *dupHt;
11528 Jim_HashTableIterator *htiter;
11529 Jim_HashEntry *he;
11530
11531
11532 ht = srcPtr->internalRep.ptr;
11533 dupHt = Jim_Alloc(sizeof(*dupHt));
11534 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11535 if (ht->size != 0)
11536 Jim_ExpandHashTable(dupHt, ht->size);
11537
11538 htiter = Jim_GetHashTableIterator(ht);
11539 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11540 const Jim_Obj *keyObjPtr = he->key;
11541 Jim_Obj *valObjPtr = he->u.val;
11542
11543 Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11544 Jim_IncrRefCount(valObjPtr);
11545 Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11546 }
11547 Jim_FreeHashTableIterator(htiter);
11548
11549 dupPtr->internalRep.ptr = dupHt;
11550 dupPtr->typePtr = &dictObjType;
11551 }
11552
11553 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
11554 {
11555 Jim_HashTable *ht;
11556 Jim_HashTableIterator *htiter;
11557 Jim_HashEntry *he;
11558 Jim_Obj **objv;
11559 int i;
11560
11561 ht = dictPtr->internalRep.ptr;
11562
11563
11564 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11565 htiter = Jim_GetHashTableIterator(ht);
11566 i = 0;
11567 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
11568 objv[i++] = (Jim_Obj *)he->key;
11569 objv[i++] = he->u.val;
11570 }
11571 *len = i;
11572 Jim_FreeHashTableIterator(htiter);
11573 return objv;
11574 }
11575
11576 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11577 {
@@ -12089,14 +12137,15 @@
12089
12090
12091 typedef struct Jim_ExprOperator
12092 {
12093 const char *name;
12094 int precedence;
12095 int arity;
12096 int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12097 int lazy;
 
 
 
12098 } Jim_ExprOperator;
12099
12100 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12101 {
12102 Jim_IncrRefCount(obj);
@@ -12774,93 +12823,96 @@
12774 LAZY_OP,
12775 LAZY_LEFT,
12776 LAZY_RIGHT
12777 };
12778
 
 
12779 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12780 {"*", 200, 2, JimExprOpBin, LAZY_NONE},
12781 {"/", 200, 2, JimExprOpBin, LAZY_NONE},
12782 {"%", 200, 2, JimExprOpIntBin, LAZY_NONE},
12783
12784 {"-", 100, 2, JimExprOpBin, LAZY_NONE},
12785 {"+", 100, 2, JimExprOpBin, LAZY_NONE},
12786
12787 {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12788 {">>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12789
12790 {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE},
12791 {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE},
12792
12793 {"<", 80, 2, JimExprOpBin, LAZY_NONE},
12794 {">", 80, 2, JimExprOpBin, LAZY_NONE},
12795 {"<=", 80, 2, JimExprOpBin, LAZY_NONE},
12796 {">=", 80, 2, JimExprOpBin, LAZY_NONE},
12797
12798 {"==", 70, 2, JimExprOpBin, LAZY_NONE},
12799 {"!=", 70, 2, JimExprOpBin, LAZY_NONE},
12800
12801 {"&", 50, 2, JimExprOpIntBin, LAZY_NONE},
12802 {"^", 49, 2, JimExprOpIntBin, LAZY_NONE},
12803 {"|", 48, 2, JimExprOpIntBin, LAZY_NONE},
12804
12805 {"&&", 10, 2, NULL, LAZY_OP},
12806 {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT},
12807 {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12808
12809 {"||", 9, 2, NULL, LAZY_OP},
12810 {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT},
12811 {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT},
12812
12813 {"?", 5, 2, JimExprOpNull, LAZY_OP},
12814 {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT},
12815 {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12816
12817 {":", 5, 2, JimExprOpNull, LAZY_OP},
12818 {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT},
12819 {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT},
12820
12821 {"**", 250, 2, JimExprOpBin, LAZY_NONE},
12822
12823 {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE},
12824 {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE},
12825
12826 {"in", 55, 2, JimExprOpStrBin, LAZY_NONE},
12827 {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE},
12828
12829 {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE},
12830 {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE},
12831 {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12832 {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE},
12833
12834
12835
12836 {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12837 {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12838 {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12839 {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE},
12840 {"rand", 400, 0, JimExprOpNone, LAZY_NONE},
12841 {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE},
12842
12843 #ifdef JIM_MATH_FUNCTIONS
12844 {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12845 {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12846 {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12847 {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12848 {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12849 {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12850 {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12851 {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12852 {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12853 {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12854 {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12855 {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12856 {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12857 {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12858 {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE},
12859 {"pow", 400, 2, JimExprOpBin, LAZY_NONE},
12860 #endif
12861 };
 
12862
12863 #define JIM_EXPR_OPERATORS_NUM \
12864 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
12865
12866 static int JimParseExpression(struct JimParserCtx *pc)
@@ -13026,20 +13078,18 @@
13026 int i;
13027 int bestIdx = -1, bestLen = 0;
13028
13029
13030 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13031 const char *opname;
13032 int oplen;
13033
13034 opname = Jim_ExprOperators[i].name;
13035 if (opname == NULL) {
13036 continue;
13037 }
13038 oplen = strlen(opname);
13039
13040 if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) {
13041 bestIdx = i + JIM_TT_EXPR_OP;
13042 bestLen = oplen;
13043 }
13044 }
13045 if (bestIdx == -1) {
@@ -13111,12 +13161,12 @@
13111 };
13112
13113
13114 typedef struct ExprByteCode
13115 {
13116 int len;
13117 ScriptToken *token;
 
13118 int inUse;
13119 } ExprByteCode;
13120
13121 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13122 {
@@ -13855,16 +13905,16 @@
13855
13856
13857
13858 typedef struct ScanFmtPartDescr
13859 {
13860 char type;
13861 char modifier;
13862 size_t width;
13863 int pos;
13864 char *arg;
13865 char *prefix;
13866 } ScanFmtPartDescr;
13867
13868
13869 typedef struct ScanFmtStringObj
13870 {
@@ -14871,12 +14921,12 @@
14871 }
14872
14873 if (retcode == JIM_OK && argc) {
14874
14875 retcode = JimInvokeCommand(interp, argc, argv);
14876 if (interp->signal_level && interp->sigmask) {
14877
14878 retcode = JIM_SIGNAL;
14879 }
14880 }
14881
14882
@@ -15446,17 +15496,17 @@
15446 if (he) {
15447 callback(interp, listObjPtr, he, type);
15448 }
15449 }
15450 else {
15451 Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
15452 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
 
15453 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
15454 callback(interp, listObjPtr, he, type);
15455 }
15456 }
15457 Jim_FreeHashTableIterator(htiter);
15458 }
15459 return listObjPtr;
15460 }
15461
15462
@@ -17795,11 +17845,11 @@
17795 if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
17796 sig++;
17797 }
17798
17799 interp->signal_level += sig;
17800 if (interp->signal_level && interp->sigmask) {
17801
17802 exitCode = JIM_SIGNAL;
17803 }
17804 else {
17805 exitCode = Jim_EvalObj(interp, argv[0]);
@@ -17951,25 +18001,24 @@
17951
17952
17953 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
17954 {
17955 Jim_Obj *listObjPtr;
17956 Jim_HashTableIterator *htiter;
17957 Jim_HashEntry *he;
17958
17959 listObjPtr = Jim_NewListObj(interp, NULL, 0);
17960
17961 htiter = Jim_GetHashTableIterator(&interp->references);
17962 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
17963 char buf[JIM_REFERENCE_SPACE + 1];
17964 Jim_Reference *refPtr = he->u.val;
17965 const unsigned long *refId = he->key;
17966
17967 JimFormatReference(buf, refPtr, *refId);
17968 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
17969 }
17970 Jim_FreeHashTableIterator(htiter);
17971 Jim_SetResult(interp, listObjPtr);
17972 return JIM_OK;
17973 }
17974 #endif
17975
@@ -18005,17 +18054,17 @@
18005 {
18006 Jim_HashEntry *he;
18007 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18008
18009
18010 Jim_HashTableIterator *htiter = Jim_GetHashTableIterator(ht);
18011 while ((he = Jim_NextHashEntry(htiter)) != NULL) {
 
18012 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18013 callback(interp, listObjPtr, he, type);
18014 }
18015 }
18016 Jim_FreeHashTableIterator(htiter);
18017
18018 return listObjPtr;
18019 }
18020
18021
18022
--- autosetup/jimsh0.c
+++ autosetup/jimsh0.c
@@ -185,11 +185,11 @@
185 #endif
186
187 #define UCHAR(c) ((unsigned char)(c))
188
189
190 #define JIM_VERSION 74
191
192 #define JIM_OK 0
193 #define JIM_ERR 1
194 #define JIM_RETURN 2
195 #define JIM_BREAK 3
@@ -321,14 +321,14 @@
321 #define Jim_GetHashTableSize(ht) ((ht)->size)
322 #define Jim_GetHashTableUsed(ht) ((ht)->used)
323
324
325 typedef struct Jim_Obj {
 
326 char *bytes;
 
327 const struct Jim_ObjType *typePtr;
328 int refCount;
329 int length;
330
331 union {
332
333 jim_wide wideValue;
334
@@ -665,12 +665,10 @@
665
666
667 JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp);
668 JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr);
669 JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr);
 
 
670 JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp,
671 Jim_Obj *objPtr);
672 JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr,
673 int *lenPtr);
674 JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr);
@@ -877,10 +875,12 @@
875 JIM_EXPORT void Jim_HistoryShow(void);
876
877
878 JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp);
879 JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base);
880 JIM_EXPORT int Jim_CheckSignal(Jim_Interp *interp);
881 #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask)
882
883
884 JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName);
885 JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp);
886
@@ -5671,10 +5671,13 @@
5671 #ifdef JIM_MAINTAINER
5672 #define JIM_DEBUG_COMMAND
5673 #define JIM_DEBUG_PANIC
5674 #endif
5675
5676
5677 #define JIM_INTEGER_SPACE 24
5678
5679 const char *jim_tt_name(int type);
5680
5681 #ifdef JIM_DEBUG_PANIC
5682 static void JimPanicDump(int panic_condition, const char *fmt, ...);
5683 #define JimPanic(X) JimPanicDump X
@@ -5690,10 +5693,11 @@
5693 static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr,
5694 int flags);
5695 static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands);
5696 static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr);
5697 static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr);
5698 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len);
5699 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype,
5700 const char *prefix, const char *const *tablePtr, const char *name);
5701 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
5702 static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr);
5703 static int JimSign(jim_wide w);
@@ -5934,15 +5938,42 @@
5938 }
5939 return n;
5940 }
5941 #endif
5942
5943 static int JimWideToString(char *buf, jim_wide wideValue)
5944 {
5945 int pos = 0;
5946
5947 if (wideValue == 0) {
5948 buf[pos++] = '0';
5949 }
5950 else {
5951 char tmp[JIM_INTEGER_SPACE];
5952 int num = 0;
5953 int i;
5954
5955 if (wideValue < 0) {
5956 buf[pos++] = '-';
5957
5958 i = wideValue % 10;
5959 tmp[num++] = (i > 0) ? (10 - i) : -i;
5960 wideValue /= -10;
5961 }
5962
5963 while (wideValue) {
5964 tmp[num++] = wideValue % 10;
5965 wideValue /= 10;
5966 }
5967
5968 for (i = 0; i < num; i++) {
5969 buf[pos++] = '0' + tmp[num - i - 1];
5970 }
5971 }
5972 buf[pos] = 0;
5973
5974 return pos;
5975 }
5976
5977 static int JimCheckConversion(const char *str, const char *endptr)
5978 {
5979 if (str[0] == '\0' || str == endptr) {
@@ -6229,10 +6260,18 @@
6260 ht->sizemask = 0;
6261 ht->used = 0;
6262 ht->collisions = 0;
6263 }
6264
6265 static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter)
6266 {
6267 iter->ht = ht;
6268 iter->index = -1;
6269 iter->entry = NULL;
6270 iter->nextEntry = NULL;
6271 }
6272
6273
6274 int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr)
6275 {
6276 JimResetHashTable(ht);
6277 ht->type = type;
@@ -6408,15 +6447,11 @@
6447 }
6448
6449 Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht)
6450 {
6451 Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter));
6452 JimInitHashTableIterator(ht, iter);
 
 
 
 
6453 return iter;
6454 }
6455
6456 Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter)
6457 {
@@ -10500,12 +10535,10 @@
10535 int Jim_GetExitCode(Jim_Interp *interp)
10536 {
10537 return interp->exitCode;
10538 }
10539
 
 
10540 static void UpdateStringOfInt(struct Jim_Obj *objPtr);
10541 static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
10542
10543 static const Jim_ObjType intObjType = {
10544 "int",
@@ -10522,16 +10555,16 @@
10555 UpdateStringOfInt,
10556 JIM_TYPE_NONE,
10557 };
10558
10559
10560 static void UpdateStringOfInt(struct Jim_Obj *objPtr)
10561 {
10562 int len;
10563 char buf[JIM_INTEGER_SPACE + 1];
10564
10565 len = JimWideToString(buf, JimWideValue(objPtr));
10566 objPtr->bytes = Jim_Alloc(len + 1);
10567 memcpy(objPtr->bytes, buf, len + 1);
10568 objPtr->length = len;
10569 }
10570
@@ -10755,11 +10788,11 @@
10788 }
10789
10790 #define JIM_ELESTR_SIMPLE 0
10791 #define JIM_ELESTR_BRACE 1
10792 #define JIM_ELESTR_QUOTE 2
10793 static unsigned char ListElementQuotingType(const char *s, int len)
10794 {
10795 int i, level, blevel, trySimple = 1;
10796
10797
10798 if (len == 0)
@@ -10903,17 +10936,23 @@
10936 return p - q;
10937 }
10938
10939 static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc)
10940 {
10941 #define STATIC_QUOTING_LEN 32
10942 int i, bufLen, realLength;
10943 const char *strRep;
10944 char *p;
10945 unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN];
10946
10947
10948 if (objc > STATIC_QUOTING_LEN) {
10949 quotingType = Jim_Alloc(objc);
10950 }
10951 else {
10952 quotingType = staticQuoting;
10953 }
10954 bufLen = 0;
10955 for (i = 0; i < objc; i++) {
10956 int len;
10957
10958 strRep = Jim_GetString(objv[i], &len);
@@ -10975,11 +11014,14 @@
11014 realLength++;
11015 }
11016 }
11017 *p = '\0';
11018 objPtr->length = realLength;
11019
11020 if (quotingType != staticQuoting) {
11021 Jim_Free(quotingType);
11022 }
11023 }
11024
11025 static void UpdateStringOfList(struct Jim_Obj *objPtr)
11026 {
11027 JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len);
@@ -11000,11 +11042,11 @@
11042 if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) {
11043 Jim_Obj **listObjPtrPtr;
11044 int len;
11045 int i;
11046
11047 listObjPtrPtr = JimDictPairs(objPtr, &len);
11048 for (i = 0; i < len; i++) {
11049 Jim_IncrRefCount(listObjPtrPtr[i]);
11050 }
11051
11052
@@ -11225,14 +11267,22 @@
11267 int requiredLen = currentLen + elemc;
11268 int i;
11269 Jim_Obj **point;
11270
11271 if (requiredLen > listPtr->internalRep.listValue.maxLen) {
11272 if (requiredLen < 2) {
11273
11274 requiredLen = 4;
11275 }
11276 else {
11277 requiredLen *= 2;
11278 }
11279
11280 listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele,
11281 sizeof(Jim_Obj *) * requiredLen);
11282
11283 listPtr->internalRep.listValue.maxLen = requiredLen;
11284 }
11285 if (idx < 0) {
11286 idx = currentLen;
11287 }
11288 point = listPtr->internalRep.listValue.ele + idx;
@@ -11523,55 +11573,53 @@
11573 }
11574
11575 void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
11576 {
11577 Jim_HashTable *ht, *dupHt;
11578 Jim_HashTableIterator htiter;
11579 Jim_HashEntry *he;
11580
11581
11582 ht = srcPtr->internalRep.ptr;
11583 dupHt = Jim_Alloc(sizeof(*dupHt));
11584 Jim_InitHashTable(dupHt, &JimDictHashTableType, interp);
11585 if (ht->size != 0)
11586 Jim_ExpandHashTable(dupHt, ht->size);
11587
11588 JimInitHashTableIterator(ht, &htiter);
11589 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11590 const Jim_Obj *keyObjPtr = he->key;
11591 Jim_Obj *valObjPtr = he->u.val;
11592
11593 Jim_IncrRefCount((Jim_Obj *)keyObjPtr);
11594 Jim_IncrRefCount(valObjPtr);
11595 Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr);
11596 }
 
11597
11598 dupPtr->internalRep.ptr = dupHt;
11599 dupPtr->typePtr = &dictObjType;
11600 }
11601
11602 static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len)
11603 {
11604 Jim_HashTable *ht;
11605 Jim_HashTableIterator htiter;
11606 Jim_HashEntry *he;
11607 Jim_Obj **objv;
11608 int i;
11609
11610 ht = dictPtr->internalRep.ptr;
11611
11612
11613 objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *));
11614 JimInitHashTableIterator(ht, &htiter);
11615 i = 0;
11616 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
11617 objv[i++] = (Jim_Obj *)he->key;
11618 objv[i++] = he->u.val;
11619 }
11620 *len = i;
 
11621 return objv;
11622 }
11623
11624 static void UpdateStringOfDict(struct Jim_Obj *objPtr)
11625 {
@@ -12089,14 +12137,15 @@
12137
12138
12139 typedef struct Jim_ExprOperator
12140 {
12141 const char *name;
 
 
12142 int (*funcop) (Jim_Interp *interp, struct JimExprState * e);
12143 unsigned char precedence;
12144 unsigned char arity;
12145 unsigned char lazy;
12146 unsigned char namelen;
12147 } Jim_ExprOperator;
12148
12149 static void ExprPush(struct JimExprState *e, Jim_Obj *obj)
12150 {
12151 Jim_IncrRefCount(obj);
@@ -12774,93 +12823,96 @@
12823 LAZY_OP,
12824 LAZY_LEFT,
12825 LAZY_RIGHT
12826 };
12827
12828 #define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1}
12829
12830 static const struct Jim_ExprOperator Jim_ExprOperators[] = {
12831 OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE),
12832 OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE),
12833 OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE),
12834
12835 OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE),
12836 OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE),
12837
12838 OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12839 OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12840
12841 OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE),
12842 OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE),
12843
12844 OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE),
12845 OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE),
12846 OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE),
12847 OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE),
12848
12849 OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE),
12850 OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE),
12851
12852 OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE),
12853 OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE),
12854 OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE),
12855
12856 OPRINIT("&&", 10, 2, NULL, LAZY_OP),
12857 OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT),
12858 OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12859
12860 OPRINIT("||", 9, 2, NULL, LAZY_OP),
12861 OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT),
12862 OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT),
12863
12864 OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP),
12865 OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT),
12866 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12867
12868 OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP),
12869 OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT),
12870 OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT),
12871
12872 OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE),
12873
12874 OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE),
12875 OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE),
12876
12877 OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE),
12878 OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE),
12879
12880 OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE),
12881 OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE),
12882 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12883 OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE),
12884
12885
12886
12887 OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12888 OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12889 OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12890 OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE),
12891 OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE),
12892 OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE),
12893
12894 #ifdef JIM_MATH_FUNCTIONS
12895 OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12896 OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12897 OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12898 OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12899 OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12900 OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12901 OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12902 OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12903 OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12904 OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12905 OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12906 OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12907 OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12908 OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12909 OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE),
12910 OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE),
12911 #endif
12912 };
12913 #undef OPRINIT
12914
12915 #define JIM_EXPR_OPERATORS_NUM \
12916 (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator))
12917
12918 static int JimParseExpression(struct JimParserCtx *pc)
@@ -13026,20 +13078,18 @@
13078 int i;
13079 int bestIdx = -1, bestLen = 0;
13080
13081
13082 for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) {
13083 const char * const opname = Jim_ExprOperators[i].name;
13084 const int oplen = Jim_ExprOperators[i].namelen;
13085
13086 if (opname == NULL || opname[0] != pc->p[0]) {
 
13087 continue;
13088 }
 
13089
13090 if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) {
13091 bestIdx = i + JIM_TT_EXPR_OP;
13092 bestLen = oplen;
13093 }
13094 }
13095 if (bestIdx == -1) {
@@ -13111,12 +13161,12 @@
13161 };
13162
13163
13164 typedef struct ExprByteCode
13165 {
 
13166 ScriptToken *token;
13167 int len;
13168 int inUse;
13169 } ExprByteCode;
13170
13171 static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr)
13172 {
@@ -13855,16 +13905,16 @@
13905
13906
13907
13908 typedef struct ScanFmtPartDescr
13909 {
13910 char *arg;
13911 char *prefix;
13912 size_t width;
13913 int pos;
13914 char type;
13915 char modifier;
13916 } ScanFmtPartDescr;
13917
13918
13919 typedef struct ScanFmtStringObj
13920 {
@@ -14871,12 +14921,12 @@
14921 }
14922
14923 if (retcode == JIM_OK && argc) {
14924
14925 retcode = JimInvokeCommand(interp, argc, argv);
14926
14927 if (Jim_CheckSignal(interp)) {
14928 retcode = JIM_SIGNAL;
14929 }
14930 }
14931
14932
@@ -15446,17 +15496,17 @@
15496 if (he) {
15497 callback(interp, listObjPtr, he, type);
15498 }
15499 }
15500 else {
15501 Jim_HashTableIterator htiter;
15502 JimInitHashTableIterator(ht, &htiter);
15503 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
15504 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) {
15505 callback(interp, listObjPtr, he, type);
15506 }
15507 }
 
15508 }
15509 return listObjPtr;
15510 }
15511
15512
@@ -17795,11 +17845,11 @@
17845 if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
17846 sig++;
17847 }
17848
17849 interp->signal_level += sig;
17850 if (Jim_CheckSignal(interp)) {
17851
17852 exitCode = JIM_SIGNAL;
17853 }
17854 else {
17855 exitCode = Jim_EvalObj(interp, argv[0]);
@@ -17951,25 +18001,24 @@
18001
18002
18003 static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
18004 {
18005 Jim_Obj *listObjPtr;
18006 Jim_HashTableIterator htiter;
18007 Jim_HashEntry *he;
18008
18009 listObjPtr = Jim_NewListObj(interp, NULL, 0);
18010
18011 JimInitHashTableIterator(&interp->references, &htiter);
18012 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18013 char buf[JIM_REFERENCE_SPACE + 1];
18014 Jim_Reference *refPtr = he->u.val;
18015 const unsigned long *refId = he->key;
18016
18017 JimFormatReference(buf, refPtr, *refId);
18018 Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1));
18019 }
 
18020 Jim_SetResult(interp, listObjPtr);
18021 return JIM_OK;
18022 }
18023 #endif
18024
@@ -18005,17 +18054,17 @@
18054 {
18055 Jim_HashEntry *he;
18056 Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
18057
18058
18059 Jim_HashTableIterator htiter;
18060 JimInitHashTableIterator(ht, &htiter);
18061 while ((he = Jim_NextHashEntry(&htiter)) != NULL) {
18062 if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) {
18063 callback(interp, listObjPtr, he, type);
18064 }
18065 }
 
18066
18067 return listObjPtr;
18068 }
18069
18070
18071
+1 -12
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
2020
*/
2121
#include "config.h"
2222
#include "add.h"
2323
#include <assert.h>
2424
#include <dirent.h>
25
-#ifdef __CYGWIN__
26
- __declspec(dllimport) extern __stdcall int RegOpenKeyExW(void *, void *,
27
- int, int, void *);
28
- __declspec(dllimport) extern __stdcall int RegQueryValueExW(void *, void *,
29
- int, void *, void *, void *);
30
-#endif
25
+#include "cygsup.h"
3126
3227
/*
3328
** This routine returns the names of files in a working checkout that
3429
** are created by Fossil itself, and hence should not be added, deleted,
3530
** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
255250
db_must_be_within_tree();
256251
if( zIgnoreFlag==0 ){
257252
zIgnoreFlag = db_get("ignore-glob", 0);
258253
}
259254
vid = db_lget_int("checkout",0);
260
- if( vid==0 ){
261
- fossil_fatal("no checkout to add to");
262
- }
263255
db_begin_transaction();
264256
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
265257
filename_collation());
266258
pIgnore = glob_create(zIgnoreFlag);
267259
nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
488480
db_must_be_within_tree();
489481
if( zIgnoreFlag==0 ){
490482
zIgnoreFlag = db_get("ignore-glob", 0);
491483
}
492484
vid = db_lget_int("checkout",0);
493
- if( vid==0 ){
494
- fossil_fatal("no checkout to add to");
495
- }
496485
db_begin_transaction();
497486
498487
/* step 1:
499488
** Populate the temp table "sfile" with the names of all unmanaged
500489
** files currently in the check-out, except for files that match the
501490
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
20 */
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25 #ifdef __CYGWIN__
26 __declspec(dllimport) extern __stdcall int RegOpenKeyExW(void *, void *,
27 int, int, void *);
28 __declspec(dllimport) extern __stdcall int RegQueryValueExW(void *, void *,
29 int, void *, void *, void *);
30 #endif
31
32 /*
33 ** This routine returns the names of files in a working checkout that
34 ** are created by Fossil itself, and hence should not be added, deleted,
35 ** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
255 db_must_be_within_tree();
256 if( zIgnoreFlag==0 ){
257 zIgnoreFlag = db_get("ignore-glob", 0);
258 }
259 vid = db_lget_int("checkout",0);
260 if( vid==0 ){
261 fossil_fatal("no checkout to add to");
262 }
263 db_begin_transaction();
264 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
265 filename_collation());
266 pIgnore = glob_create(zIgnoreFlag);
267 nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
488 db_must_be_within_tree();
489 if( zIgnoreFlag==0 ){
490 zIgnoreFlag = db_get("ignore-glob", 0);
491 }
492 vid = db_lget_int("checkout",0);
493 if( vid==0 ){
494 fossil_fatal("no checkout to add to");
495 }
496 db_begin_transaction();
497
498 /* step 1:
499 ** Populate the temp table "sfile" with the names of all unmanaged
500 ** files currently in the check-out, except for files that match the
501
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
20 */
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25 #include "cygsup.h"
 
 
 
 
 
26
27 /*
28 ** This routine returns the names of files in a working checkout that
29 ** are created by Fossil itself, and hence should not be added, deleted,
30 ** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
250 db_must_be_within_tree();
251 if( zIgnoreFlag==0 ){
252 zIgnoreFlag = db_get("ignore-glob", 0);
253 }
254 vid = db_lget_int("checkout",0);
 
 
 
255 db_begin_transaction();
256 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
257 filename_collation());
258 pIgnore = glob_create(zIgnoreFlag);
259 nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
480 db_must_be_within_tree();
481 if( zIgnoreFlag==0 ){
482 zIgnoreFlag = db_get("ignore-glob", 0);
483 }
484 vid = db_lget_int("checkout",0);
 
 
 
485 db_begin_transaction();
486
487 /* step 1:
488 ** Populate the temp table "sfile" with the names of all unmanaged
489 ** files currently in the check-out, except for files that match the
490
+1 -12
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
2020
*/
2121
#include "config.h"
2222
#include "add.h"
2323
#include <assert.h>
2424
#include <dirent.h>
25
-#ifdef __CYGWIN__
26
- __declspec(dllimport) extern __stdcall int RegOpenKeyExW(void *, void *,
27
- int, int, void *);
28
- __declspec(dllimport) extern __stdcall int RegQueryValueExW(void *, void *,
29
- int, void *, void *, void *);
30
-#endif
25
+#include "cygsup.h"
3126
3227
/*
3328
** This routine returns the names of files in a working checkout that
3429
** are created by Fossil itself, and hence should not be added, deleted,
3530
** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
255250
db_must_be_within_tree();
256251
if( zIgnoreFlag==0 ){
257252
zIgnoreFlag = db_get("ignore-glob", 0);
258253
}
259254
vid = db_lget_int("checkout",0);
260
- if( vid==0 ){
261
- fossil_fatal("no checkout to add to");
262
- }
263255
db_begin_transaction();
264256
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
265257
filename_collation());
266258
pIgnore = glob_create(zIgnoreFlag);
267259
nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
488480
db_must_be_within_tree();
489481
if( zIgnoreFlag==0 ){
490482
zIgnoreFlag = db_get("ignore-glob", 0);
491483
}
492484
vid = db_lget_int("checkout",0);
493
- if( vid==0 ){
494
- fossil_fatal("no checkout to add to");
495
- }
496485
db_begin_transaction();
497486
498487
/* step 1:
499488
** Populate the temp table "sfile" with the names of all unmanaged
500489
** files currently in the check-out, except for files that match the
501490
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
20 */
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25 #ifdef __CYGWIN__
26 __declspec(dllimport) extern __stdcall int RegOpenKeyExW(void *, void *,
27 int, int, void *);
28 __declspec(dllimport) extern __stdcall int RegQueryValueExW(void *, void *,
29 int, void *, void *, void *);
30 #endif
31
32 /*
33 ** This routine returns the names of files in a working checkout that
34 ** are created by Fossil itself, and hence should not be added, deleted,
35 ** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
255 db_must_be_within_tree();
256 if( zIgnoreFlag==0 ){
257 zIgnoreFlag = db_get("ignore-glob", 0);
258 }
259 vid = db_lget_int("checkout",0);
260 if( vid==0 ){
261 fossil_fatal("no checkout to add to");
262 }
263 db_begin_transaction();
264 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
265 filename_collation());
266 pIgnore = glob_create(zIgnoreFlag);
267 nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
488 db_must_be_within_tree();
489 if( zIgnoreFlag==0 ){
490 zIgnoreFlag = db_get("ignore-glob", 0);
491 }
492 vid = db_lget_int("checkout",0);
493 if( vid==0 ){
494 fossil_fatal("no checkout to add to");
495 }
496 db_begin_transaction();
497
498 /* step 1:
499 ** Populate the temp table "sfile" with the names of all unmanaged
500 ** files currently in the check-out, except for files that match the
501
--- src/add.c
+++ src/add.c
@@ -20,16 +20,11 @@
20 */
21 #include "config.h"
22 #include "add.h"
23 #include <assert.h>
24 #include <dirent.h>
25 #include "cygsup.h"
 
 
 
 
 
26
27 /*
28 ** This routine returns the names of files in a working checkout that
29 ** are created by Fossil itself, and hence should not be added, deleted,
30 ** or merge, and should be omitted from "clean" and "extra" lists.
@@ -255,13 +250,10 @@
250 db_must_be_within_tree();
251 if( zIgnoreFlag==0 ){
252 zIgnoreFlag = db_get("ignore-glob", 0);
253 }
254 vid = db_lget_int("checkout",0);
 
 
 
255 db_begin_transaction();
256 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
257 filename_collation());
258 pIgnore = glob_create(zIgnoreFlag);
259 nRoot = strlen(g.zLocalRoot);
@@ -488,13 +480,10 @@
480 db_must_be_within_tree();
481 if( zIgnoreFlag==0 ){
482 zIgnoreFlag = db_get("ignore-glob", 0);
483 }
484 vid = db_lget_int("checkout",0);
 
 
 
485 db_begin_transaction();
486
487 /* step 1:
488 ** Populate the temp table "sfile" with the names of all unmanaged
489 ** files currently in the check-out, except for files that match the
490
+77 -25
--- src/allrepo.c
+++ src/allrepo.c
@@ -58,19 +58,23 @@
5858
}
5959
}
6060
static void collect_argument_value(Blob *pExtra, const char *zArg){
6161
const char *zValue = find_option(zArg, 0, 1);
6262
if( zValue ){
63
- blob_appendf(pExtra, " --%s %s", zArg, zValue);
63
+ if( zValue[0] ){
64
+ blob_appendf(pExtra, " --%s %s", zArg, zValue);
65
+ }else{
66
+ blob_appendf(pExtra, " --%s \"\"", zArg);
67
+ }
6468
}
6569
}
6670
6771
6872
/*
6973
** COMMAND: all
7074
**
71
-** Usage: %fossil all (changes|ignore|list|ls|pull|push|rebuild|sync)
75
+** Usage: %fossil all (changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync)
7276
**
7377
** The ~/.fossil file records the location of all repositories for a
7478
** user. This command performs certain operations on all repositories
7579
** that can be useful before or after a period of disconnected operation.
7680
**
@@ -77,33 +81,56 @@
7781
** On Win32 systems, the file is named "_fossil" and is located in
7882
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
7983
**
8084
** Available operations are:
8185
**
82
-** changes Shows all local checkouts that have uncommitted changes
83
-**
84
-** ignore Arguments are repositories that should be ignored
85
-** by subsequent list, pull, push, rebuild, and sync.
86
-** The -c|--ckout option causes the listed local checkouts
87
-** to be ignored instead.
88
-**
89
-** list | ls Display the location of all repositories.
90
-** The -c|--ckout option causes all local checkouts to be
91
-** list instead.
92
-**
93
-** pull Run a "pull" operation on all repositories
94
-**
95
-** push Run a "push" on all repositories
96
-**
97
-** rebuild Rebuild on all repositories
98
-**
99
-** sync Run a "sync" on all repositories
86
+** changes Shows all local checkouts that have uncommitted changes.
87
+** This operation has no additional options.
88
+**
89
+** clean Delete all "extra" files in all local checkouts. Extreme
90
+** caution should be exercised with this command because its
91
+** effects cannot be undone. Use of the --dry-run option to
92
+** carefully review the local checkouts to be operated upon
93
+** and the --whatif option to carefully review the files to
94
+** be deleted beforehand is highly recommended. The command
95
+** line options supported by the clean command itself, if any
96
+** are present, are passed along verbatim.
97
+**
98
+** extra Shows extra files from all local checkouts. The command
99
+** line options supported by the extra command itself, if any
100
+** are present, are passed along verbatim.
101
+**
102
+** ignore Arguments are repositories that should be ignored by
103
+** subsequent clean, extra, list, pull, push, rebuild, and
104
+** sync operations. The -c|--ckout option causes the listed
105
+** local checkouts to be ignored instead.
106
+**
107
+** list | ls Display the location of all repositories. The -c|--ckout
108
+** option causes all local checkouts to be listed instead.
109
+**
110
+** pull Run a "pull" operation on all repositories. Only the
111
+** --verbose option is supported.
112
+**
113
+** push Run a "push" on all repositories. Only the --verbose
114
+** option is supported.
115
+**
116
+** rebuild Rebuild on all repositories. The command line options
117
+** supported by the rebuild command itself, if any are
118
+** present, are passed along verbatim. The --force and
119
+** --randomize options are not supported.
120
+**
121
+** sync Run a "sync" on all repositories. Only the --verbose
122
+** option is supported.
100123
**
101124
** Repositories are automatically added to the set of known repositories
102
-** when one of the following commands are run against the repository: clone,
103
-** info, pull, push, or sync. Even previously ignored repositories are
104
-** added back to the list of repositories by these commands.
125
+** when one of the following commands are run against the repository:
126
+** clone, info, pull, push, or sync. Even previously ignored repositories
127
+** are added back to the list of repositories by these commands.
128
+**
129
+** Options:
130
+** --dontstop Continue with other repositories even after an error.
131
+** --dry-run If given, display instead of run actions.
105132
*/
106133
void all_cmd(void){
107134
int n;
108135
Stmt q;
109136
const char *zCmd;
@@ -122,20 +149,45 @@
122149
if( !dryRunFlag ){
123150
dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
124151
}
125152
126153
if( g.argc<3 ){
127
- usage("changes|ignore|list|ls|pull|push|rebuild|sync");
154
+ usage("changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync");
128155
}
129156
n = strlen(g.argv[2]);
130157
db_open_config(1);
131158
blob_zero(&extra);
132159
zCmd = g.argv[2];
133160
if( g.zLogin ) blob_appendf(&extra, " -U %s", g.zLogin);
134161
if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
135162
zCmd = "list";
136163
useCheckouts = find_option("ckout","c",0)!=0;
164
+ }else if( strncmp(zCmd, "clean", n)==0 ){
165
+ zCmd = "clean --chdir";
166
+ collect_argument(&extra, "allckouts",0);
167
+ collect_argument_value(&extra, "case-sensitive");
168
+ collect_argument_value(&extra, "clean");
169
+ collect_argument(&extra, "dirsonly",0);
170
+ collect_argument(&extra, "dotfiles",0);
171
+ collect_argument(&extra, "emptydirs",0);
172
+ collect_argument(&extra, "force","f");
173
+ collect_argument_value(&extra, "ignore");
174
+ collect_argument_value(&extra, "keep");
175
+ collect_argument(&extra, "temp",0);
176
+ collect_argument(&extra, "verbose","v");
177
+ collect_argument(&extra, "whatif",0);
178
+ useCheckouts = 1;
179
+ }else if( strncmp(zCmd, "extra", n)==0 ){
180
+ zCmd = "extra --chdir";
181
+ collect_argument(&extra, "abs-paths",0);
182
+ collect_argument_value(&extra, "case-sensitive");
183
+ collect_argument(&extra, "dotfiles",0);
184
+ collect_argument_value(&extra, "ignore");
185
+ collect_argument(&extra, "rel-paths",0);
186
+ useCheckouts = 1;
187
+ stopOnError = 0;
188
+ quiet = 1;
137189
}else if( strncmp(zCmd, "push", n)==0 ){
138190
zCmd = "push -autourl -R";
139191
collect_argument(&extra, "verbose","v");
140192
}else if( strncmp(zCmd, "pull", n)==0 ){
141193
zCmd = "pull -autourl -R";
@@ -185,11 +237,11 @@
185237
}
186238
db_end_transaction(0);
187239
return;
188240
}else{
189241
fossil_fatal("\"all\" subcommand should be one of: "
190
- "changes ignore list ls push pull rebuild sync");
242
+ "changes clean extra ignore list ls push pull rebuild sync");
191243
}
192244
verify_all_options();
193245
zFossil = quoteFilename(g.nameOfExe);
194246
if( useCheckouts ){
195247
db_prepare(&q,
196248
--- src/allrepo.c
+++ src/allrepo.c
@@ -58,19 +58,23 @@
58 }
59 }
60 static void collect_argument_value(Blob *pExtra, const char *zArg){
61 const char *zValue = find_option(zArg, 0, 1);
62 if( zValue ){
63 blob_appendf(pExtra, " --%s %s", zArg, zValue);
 
 
 
 
64 }
65 }
66
67
68 /*
69 ** COMMAND: all
70 **
71 ** Usage: %fossil all (changes|ignore|list|ls|pull|push|rebuild|sync)
72 **
73 ** The ~/.fossil file records the location of all repositories for a
74 ** user. This command performs certain operations on all repositories
75 ** that can be useful before or after a period of disconnected operation.
76 **
@@ -77,33 +81,56 @@
77 ** On Win32 systems, the file is named "_fossil" and is located in
78 ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
79 **
80 ** Available operations are:
81 **
82 ** changes Shows all local checkouts that have uncommitted changes
83 **
84 ** ignore Arguments are repositories that should be ignored
85 ** by subsequent list, pull, push, rebuild, and sync.
86 ** The -c|--ckout option causes the listed local checkouts
87 ** to be ignored instead.
88 **
89 ** list | ls Display the location of all repositories.
90 ** The -c|--ckout option causes all local checkouts to be
91 ** list instead.
92 **
93 ** pull Run a "pull" operation on all repositories
94 **
95 ** push Run a "push" on all repositories
96 **
97 ** rebuild Rebuild on all repositories
98 **
99 ** sync Run a "sync" on all repositories
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100 **
101 ** Repositories are automatically added to the set of known repositories
102 ** when one of the following commands are run against the repository: clone,
103 ** info, pull, push, or sync. Even previously ignored repositories are
104 ** added back to the list of repositories by these commands.
 
 
 
 
105 */
106 void all_cmd(void){
107 int n;
108 Stmt q;
109 const char *zCmd;
@@ -122,20 +149,45 @@
122 if( !dryRunFlag ){
123 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
124 }
125
126 if( g.argc<3 ){
127 usage("changes|ignore|list|ls|pull|push|rebuild|sync");
128 }
129 n = strlen(g.argv[2]);
130 db_open_config(1);
131 blob_zero(&extra);
132 zCmd = g.argv[2];
133 if( g.zLogin ) blob_appendf(&extra, " -U %s", g.zLogin);
134 if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
135 zCmd = "list";
136 useCheckouts = find_option("ckout","c",0)!=0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137 }else if( strncmp(zCmd, "push", n)==0 ){
138 zCmd = "push -autourl -R";
139 collect_argument(&extra, "verbose","v");
140 }else if( strncmp(zCmd, "pull", n)==0 ){
141 zCmd = "pull -autourl -R";
@@ -185,11 +237,11 @@
185 }
186 db_end_transaction(0);
187 return;
188 }else{
189 fossil_fatal("\"all\" subcommand should be one of: "
190 "changes ignore list ls push pull rebuild sync");
191 }
192 verify_all_options();
193 zFossil = quoteFilename(g.nameOfExe);
194 if( useCheckouts ){
195 db_prepare(&q,
196
--- src/allrepo.c
+++ src/allrepo.c
@@ -58,19 +58,23 @@
58 }
59 }
60 static void collect_argument_value(Blob *pExtra, const char *zArg){
61 const char *zValue = find_option(zArg, 0, 1);
62 if( zValue ){
63 if( zValue[0] ){
64 blob_appendf(pExtra, " --%s %s", zArg, zValue);
65 }else{
66 blob_appendf(pExtra, " --%s \"\"", zArg);
67 }
68 }
69 }
70
71
72 /*
73 ** COMMAND: all
74 **
75 ** Usage: %fossil all (changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync)
76 **
77 ** The ~/.fossil file records the location of all repositories for a
78 ** user. This command performs certain operations on all repositories
79 ** that can be useful before or after a period of disconnected operation.
80 **
@@ -77,33 +81,56 @@
81 ** On Win32 systems, the file is named "_fossil" and is located in
82 ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
83 **
84 ** Available operations are:
85 **
86 ** changes Shows all local checkouts that have uncommitted changes.
87 ** This operation has no additional options.
88 **
89 ** clean Delete all "extra" files in all local checkouts. Extreme
90 ** caution should be exercised with this command because its
91 ** effects cannot be undone. Use of the --dry-run option to
92 ** carefully review the local checkouts to be operated upon
93 ** and the --whatif option to carefully review the files to
94 ** be deleted beforehand is highly recommended. The command
95 ** line options supported by the clean command itself, if any
96 ** are present, are passed along verbatim.
97 **
98 ** extra Shows extra files from all local checkouts. The command
99 ** line options supported by the extra command itself, if any
100 ** are present, are passed along verbatim.
101 **
102 ** ignore Arguments are repositories that should be ignored by
103 ** subsequent clean, extra, list, pull, push, rebuild, and
104 ** sync operations. The -c|--ckout option causes the listed
105 ** local checkouts to be ignored instead.
106 **
107 ** list | ls Display the location of all repositories. The -c|--ckout
108 ** option causes all local checkouts to be listed instead.
109 **
110 ** pull Run a "pull" operation on all repositories. Only the
111 ** --verbose option is supported.
112 **
113 ** push Run a "push" on all repositories. Only the --verbose
114 ** option is supported.
115 **
116 ** rebuild Rebuild on all repositories. The command line options
117 ** supported by the rebuild command itself, if any are
118 ** present, are passed along verbatim. The --force and
119 ** --randomize options are not supported.
120 **
121 ** sync Run a "sync" on all repositories. Only the --verbose
122 ** option is supported.
123 **
124 ** Repositories are automatically added to the set of known repositories
125 ** when one of the following commands are run against the repository:
126 ** clone, info, pull, push, or sync. Even previously ignored repositories
127 ** are added back to the list of repositories by these commands.
128 **
129 ** Options:
130 ** --dontstop Continue with other repositories even after an error.
131 ** --dry-run If given, display instead of run actions.
132 */
133 void all_cmd(void){
134 int n;
135 Stmt q;
136 const char *zCmd;
@@ -122,20 +149,45 @@
149 if( !dryRunFlag ){
150 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
151 }
152
153 if( g.argc<3 ){
154 usage("changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync");
155 }
156 n = strlen(g.argv[2]);
157 db_open_config(1);
158 blob_zero(&extra);
159 zCmd = g.argv[2];
160 if( g.zLogin ) blob_appendf(&extra, " -U %s", g.zLogin);
161 if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
162 zCmd = "list";
163 useCheckouts = find_option("ckout","c",0)!=0;
164 }else if( strncmp(zCmd, "clean", n)==0 ){
165 zCmd = "clean --chdir";
166 collect_argument(&extra, "allckouts",0);
167 collect_argument_value(&extra, "case-sensitive");
168 collect_argument_value(&extra, "clean");
169 collect_argument(&extra, "dirsonly",0);
170 collect_argument(&extra, "dotfiles",0);
171 collect_argument(&extra, "emptydirs",0);
172 collect_argument(&extra, "force","f");
173 collect_argument_value(&extra, "ignore");
174 collect_argument_value(&extra, "keep");
175 collect_argument(&extra, "temp",0);
176 collect_argument(&extra, "verbose","v");
177 collect_argument(&extra, "whatif",0);
178 useCheckouts = 1;
179 }else if( strncmp(zCmd, "extra", n)==0 ){
180 zCmd = "extra --chdir";
181 collect_argument(&extra, "abs-paths",0);
182 collect_argument_value(&extra, "case-sensitive");
183 collect_argument(&extra, "dotfiles",0);
184 collect_argument_value(&extra, "ignore");
185 collect_argument(&extra, "rel-paths",0);
186 useCheckouts = 1;
187 stopOnError = 0;
188 quiet = 1;
189 }else if( strncmp(zCmd, "push", n)==0 ){
190 zCmd = "push -autourl -R";
191 collect_argument(&extra, "verbose","v");
192 }else if( strncmp(zCmd, "pull", n)==0 ){
193 zCmd = "pull -autourl -R";
@@ -185,11 +237,11 @@
237 }
238 db_end_transaction(0);
239 return;
240 }else{
241 fossil_fatal("\"all\" subcommand should be one of: "
242 "changes clean extra ignore list ls push pull rebuild sync");
243 }
244 verify_all_options();
245 zFossil = quoteFilename(g.nameOfExe);
246 if( useCheckouts ){
247 db_prepare(&q,
248
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -384,11 +384,11 @@
384384
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
385385
g.zTop, zUuid);
386386
}
387387
}
388388
#endif
389
- pAttach = manifest_get(rid, CFTYPE_ATTACHMENT);
389
+ pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
390390
if( pAttach==0 ) fossil_redirect_home();
391391
zTarget = pAttach->zAttachTarget;
392392
zSrc = pAttach->zAttachSrc;
393393
ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc);
394394
zName = pAttach->zAttachName;
395395
--- src/attach.c
+++ src/attach.c
@@ -384,11 +384,11 @@
384 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
385 g.zTop, zUuid);
386 }
387 }
388 #endif
389 pAttach = manifest_get(rid, CFTYPE_ATTACHMENT);
390 if( pAttach==0 ) fossil_redirect_home();
391 zTarget = pAttach->zAttachTarget;
392 zSrc = pAttach->zAttachSrc;
393 ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc);
394 zName = pAttach->zAttachName;
395
--- src/attach.c
+++ src/attach.c
@@ -384,11 +384,11 @@
384 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
385 g.zTop, zUuid);
386 }
387 }
388 #endif
389 pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
390 if( pAttach==0 ) fossil_redirect_home();
391 zTarget = pAttach->zAttachTarget;
392 zSrc = pAttach->zAttachSrc;
393 ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc);
394 zName = pAttach->zAttachName;
395
+1 -1
--- src/branch.c
+++ src/branch.c
@@ -73,11 +73,11 @@
7373
rootid = name_to_typed_rid(g.argv[4], "ci");
7474
if( rootid==0 ){
7575
fossil_fatal("unable to locate check-in off of which to branch");
7676
}
7777
78
- pParent = manifest_get(rootid, CFTYPE_MANIFEST);
78
+ pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0);
7979
if( pParent==0 ){
8080
fossil_fatal("%s is not a valid check-in", g.argv[4]);
8181
}
8282
8383
/* Create a manifest for the new branch */
8484
--- src/branch.c
+++ src/branch.c
@@ -73,11 +73,11 @@
73 rootid = name_to_typed_rid(g.argv[4], "ci");
74 if( rootid==0 ){
75 fossil_fatal("unable to locate check-in off of which to branch");
76 }
77
78 pParent = manifest_get(rootid, CFTYPE_MANIFEST);
79 if( pParent==0 ){
80 fossil_fatal("%s is not a valid check-in", g.argv[4]);
81 }
82
83 /* Create a manifest for the new branch */
84
--- src/branch.c
+++ src/branch.c
@@ -73,11 +73,11 @@
73 rootid = name_to_typed_rid(g.argv[4], "ci");
74 if( rootid==0 ){
75 fossil_fatal("unable to locate check-in off of which to branch");
76 }
77
78 pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0);
79 if( pParent==0 ){
80 fossil_fatal("%s is not a valid check-in", g.argv[4]);
81 }
82
83 /* Create a manifest for the new branch */
84
+1 -1
--- src/browse.c
+++ src/browse.c
@@ -331,11 +331,11 @@
331331
" mtime DATETIME,"
332332
" pathname TEXT"
333333
");"
334334
"CREATE INDEX fileage_fid ON fileage(fid);"
335335
);
336
- pManifest = manifest_get(vid, CFTYPE_MANIFEST);
336
+ pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
337337
if( pManifest==0 ) return 1;
338338
manifest_file_rewind(pManifest);
339339
db_prepare(&ins,
340340
"INSERT INTO temp.fileage(fid, pathname)"
341341
" SELECT rid, :path FROM blob WHERE uuid=:uuid"
342342
--- src/browse.c
+++ src/browse.c
@@ -331,11 +331,11 @@
331 " mtime DATETIME,"
332 " pathname TEXT"
333 ");"
334 "CREATE INDEX fileage_fid ON fileage(fid);"
335 );
336 pManifest = manifest_get(vid, CFTYPE_MANIFEST);
337 if( pManifest==0 ) return 1;
338 manifest_file_rewind(pManifest);
339 db_prepare(&ins,
340 "INSERT INTO temp.fileage(fid, pathname)"
341 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
342
--- src/browse.c
+++ src/browse.c
@@ -331,11 +331,11 @@
331 " mtime DATETIME,"
332 " pathname TEXT"
333 ");"
334 "CREATE INDEX fileage_fid ON fileage(fid);"
335 );
336 pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
337 if( pManifest==0 ) return 1;
338 manifest_file_rewind(pManifest);
339 db_prepare(&ins,
340 "INSERT INTO temp.fileage(fid, pathname)"
341 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
342
+1 -1
--- src/captcha.c
+++ src/captcha.c
@@ -17,12 +17,12 @@
1717
**
1818
** This file contains code to a simple text-based CAPTCHA. Though easily
1919
** defeated by a sophisticated attacker, this CAPTCHA does at least make
2020
** scripting attacks more difficult.
2121
*/
22
-#include <assert.h>
2322
#include "config.h"
23
+#include <assert.h>
2424
#include "captcha.h"
2525
2626
#if INTERFACE
2727
#define CAPTCHA 3 /* Which captcha rendering to use */
2828
#endif
2929
--- src/captcha.c
+++ src/captcha.c
@@ -17,12 +17,12 @@
17 **
18 ** This file contains code to a simple text-based CAPTCHA. Though easily
19 ** defeated by a sophisticated attacker, this CAPTCHA does at least make
20 ** scripting attacks more difficult.
21 */
22 #include <assert.h>
23 #include "config.h"
 
24 #include "captcha.h"
25
26 #if INTERFACE
27 #define CAPTCHA 3 /* Which captcha rendering to use */
28 #endif
29
--- src/captcha.c
+++ src/captcha.c
@@ -17,12 +17,12 @@
17 **
18 ** This file contains code to a simple text-based CAPTCHA. Though easily
19 ** defeated by a sophisticated attacker, this CAPTCHA does at least make
20 ** scripting attacks more difficult.
21 */
 
22 #include "config.h"
23 #include <assert.h>
24 #include "captcha.h"
25
26 #if INTERFACE
27 #define CAPTCHA 3 /* Which captcha rendering to use */
28 #endif
29
+277 -8
--- src/cgi.c
+++ src/cgi.c
@@ -40,15 +40,11 @@
4040
#include <time.h>
4141
#include <stdio.h>
4242
#include <stdlib.h>
4343
#include <unistd.h>
4444
#include "cgi.h"
45
-#ifdef __CYGWIN__
46
- __declspec(dllimport) extern __stdcall int ShellExecuteW(void *, void *,
47
- void *, void *, void *, int);
48
- __declspec(dllimport) extern __stdcall size_t wcslen(const wchar_t *);
49
-#endif
45
+#include "cygsup.h"
5046
5147
#if INTERFACE
5248
/*
5349
** Shortcuts for cgi_parameter. P("x") returns the value of query parameter
5450
** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
@@ -64,10 +60,17 @@
6460
** Destinations for output text.
6561
*/
6662
#define CGI_HEADER 0
6763
#define CGI_BODY 1
6864
65
+/*
66
+** Flags for SSH HTTP clients
67
+*/
68
+#define CGI_SSH_CLIENT 0x0001 /* Client is SSH */
69
+#define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */
70
+#define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */
71
+
6972
#endif /* INTERFACE */
7073
7174
/*
7275
** The HTTP reply is generated in two pieces: the header and the body.
7376
** These pieces are generated separately because they are not necessary
@@ -827,26 +830,50 @@
827830
828831
/*
829832
** Initialize the query parameter database. Information is pulled from
830833
** the QUERY_STRING environment variable (if it exists), from standard
831834
** input if there is POST data, and from HTTP_COOKIE.
835
+**
836
+** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows:
837
+**
838
+** REQUEST_URI == SCRIPT_NAME + PATH_INFO
839
+**
840
+** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If
841
+** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is
842
+** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided
843
+** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and
844
+** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then
845
+** assume that PATH_INFO is an empty string and set REQUEST_URI equal
846
+** to PATH_INFO.
847
+**
848
+** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and
849
+** PATH_INFO when it is empty.
832850
*/
833851
void cgi_init(void){
834852
char *z;
835853
const char *zType;
836854
int len;
837855
const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
838856
const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
857
+ const char *zPathInfo = cgi_parameter("PATH_INFO","");
839858
840859
#ifdef FOSSIL_ENABLE_JSON
841860
json_main_bootstrap();
842861
#endif
843862
g.isHTTP = 1;
844863
cgi_destination(CGI_BODY);
845
- if( zRequestUri==0 ) malformed_request("missing REQUEST_URI");
846864
if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
847
- if( cgi_parameter("PATH_INFO",0)==0 ){
865
+ if( zRequestUri==0 ){
866
+ const char *z = zPathInfo;
867
+ if( zPathInfo==0 ){
868
+ malformed_request("missing PATH_INFO and/or REQUEST_URI");
869
+ }
870
+ if( z[0]=='/' ) z++;
871
+ zRequestUri = mprintf("%s/%s", zScriptName, z);
872
+ cgi_set_parameter("REQUEST_URI", zRequestUri);
873
+ }
874
+ if( zPathInfo==0 ){
848875
int i, j;
849876
for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){}
850877
for(j=i; zRequestUri[j] && zRequestUri[j]!='?'; j++){}
851878
cgi_set_parameter("PATH_INFO", mprintf("%.*s", j-i, zRequestUri+i));
852879
}
@@ -1306,10 +1333,234 @@
13061333
}
13071334
}
13081335
cgi_init();
13091336
cgi_trace(0);
13101337
}
1338
+
1339
+/*
1340
+** This routine handles a single HTTP request from an SSH client which is
1341
+** coming in on g.httpIn and which replies on g.httpOut
1342
+**
1343
+** Once all the setup is finished, this procedure returns
1344
+** and subsequent code handles the actual generation of the webpage.
1345
+**
1346
+** It is called in a loop so some variables will need to be replaced
1347
+*/
1348
+void cgi_handle_ssh_http_request(const char *zIpAddr){
1349
+ static int nCycles = 0;
1350
+ static char *zCmd = 0;
1351
+ char *z, *zToken;
1352
+ const char *zType = 0;
1353
+ int i, content_length = 0;
1354
+ char zLine[2000]; /* A single line of input. */
1355
+
1356
+ if( zIpAddr ){
1357
+ if( nCycles==0 ){
1358
+ cgi_setenv("REMOTE_ADDR", zIpAddr);
1359
+ g.zIpAddr = mprintf("%s", zIpAddr);
1360
+ }
1361
+ }else{
1362
+ fossil_panic("missing SSH IP address");
1363
+ }
1364
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1365
+ malformed_request("missing HTTP header");
1366
+ }
1367
+ cgi_trace(zLine);
1368
+ zToken = extract_token(zLine, &z);
1369
+ if( zToken==0 ){
1370
+ malformed_request("malformed HTTP header");
1371
+ }
1372
+
1373
+ if( fossil_strcmp(zToken, "echo")==0 ){
1374
+ /* start looking for probes to complete transport_open */
1375
+ zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken);
1376
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1377
+ malformed_request("missing HTTP header");
1378
+ }
1379
+ cgi_trace(zLine);
1380
+ zToken = extract_token(zLine, &z);
1381
+ if( zToken==0 ){
1382
+ malformed_request("malformed HTTP header");
1383
+ }
1384
+ }else if( zToken && strlen(zToken)==0 && zCmd ){
1385
+ /* transport_flip request and continued transport_open */
1386
+ cgi_handle_ssh_transport(zCmd);
1387
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1388
+ malformed_request("missing HTTP header");
1389
+ }
1390
+ cgi_trace(zLine);
1391
+ zToken = extract_token(zLine, &z);
1392
+ if( zToken==0 ){
1393
+ malformed_request("malformed HTTP header");
1394
+ }
1395
+ }
1396
+
1397
+ if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
1398
+ && fossil_strcmp(zToken,"HEAD")!=0 ){
1399
+ malformed_request("unsupported HTTP method");
1400
+ }
1401
+
1402
+ if( nCycles==0 ){
1403
+ cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
1404
+ cgi_setenv("REQUEST_METHOD",zToken);
1405
+ }
1406
+
1407
+ zToken = extract_token(z, &z);
1408
+ if( zToken==0 ){
1409
+ malformed_request("malformed URL in HTTP header");
1410
+ }
1411
+ if( nCycles==0 ){
1412
+ cgi_setenv("REQUEST_URI", zToken);
1413
+ cgi_setenv("SCRIPT_NAME", "");
1414
+ }
1415
+
1416
+ for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1417
+ if( zToken[i] ) zToken[i++] = 0;
1418
+ if( nCycles==0 ){
1419
+ cgi_setenv("PATH_INFO", zToken);
1420
+ }else{
1421
+ cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1422
+ }
1423
+
1424
+ /* Get all the optional fields that follow the first line.
1425
+ */
1426
+ while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1427
+ char *zFieldName;
1428
+ char *zVal;
1429
+
1430
+ cgi_trace(zLine);
1431
+ zFieldName = extract_token(zLine,&zVal);
1432
+ if( zFieldName==0 || *zFieldName==0 ) break;
1433
+ while( fossil_isspace(*zVal) ){ zVal++; }
1434
+ i = strlen(zVal);
1435
+ while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; }
1436
+ zVal[i] = 0;
1437
+ for(i=0; zFieldName[i]; i++){
1438
+ zFieldName[i] = fossil_tolower(zFieldName[i]);
1439
+ }
1440
+ if( fossil_strcmp(zFieldName,"content-length:")==0 ){
1441
+ content_length = atoi(zVal);
1442
+ }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){
1443
+ g.zContentType = zType = mprintf("%s", zVal);
1444
+ }else if( fossil_strcmp(zFieldName,"host:")==0 ){
1445
+ if( nCycles==0 ){
1446
+ cgi_setenv("HTTP_HOST", zVal);
1447
+ }
1448
+ }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1449
+ if( nCycles==0 ){
1450
+ cgi_setenv("HTTP_USER_AGENT", zVal);
1451
+ }
1452
+ }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){
1453
+ if( fossil_strnicmp(zVal, "ssh", 3)==0 ){
1454
+ if( nCycles==0 ){
1455
+ g.fSshClient |= CGI_SSH_FOSSIL;
1456
+ g.fullHttpReply = 0;
1457
+ }
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ if( nCycles==0 ){
1463
+ if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){
1464
+ /* did not find new fossil ssh transport */
1465
+ g.fSshClient &= ~CGI_SSH_CLIENT;
1466
+ g.fullHttpReply = 1;
1467
+ cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1");
1468
+ }
1469
+ }
1470
+
1471
+ cgi_reset_content();
1472
+ cgi_destination(CGI_BODY);
1473
+
1474
+ if( content_length>0 && zType ){
1475
+ blob_zero(&g.cgiIn);
1476
+ if( fossil_strcmp(zType, "application/x-fossil")==0 ){
1477
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1478
+ blob_uncompress(&g.cgiIn, &g.cgiIn);
1479
+ }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1480
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1481
+ }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1482
+ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1483
+ }
1484
+ }
1485
+ cgi_trace(0);
1486
+ nCycles++;
1487
+}
1488
+
1489
+/*
1490
+** This routine handles the old fossil SSH probes
1491
+*/
1492
+char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
1493
+ /* Start looking for probes */
1494
+ while( fossil_strcmp(zToken, "echo")==0 ){
1495
+ zToken = extract_token(z, &z);
1496
+ if( zToken==0 ){
1497
+ malformed_request("malformed probe");
1498
+ }
1499
+ if( fossil_strncmp(zToken, "test", 4)==0 ||
1500
+ fossil_strncmp(zToken, "probe-", 6)==0 ){
1501
+ fprintf(g.httpOut, "%s\n", zToken);
1502
+ fflush(g.httpOut);
1503
+ }else{
1504
+ malformed_request("malformed probe");
1505
+ }
1506
+ if( fgets(zLine, zSize, g.httpIn)==0 ){
1507
+ malformed_request("malformed probe");
1508
+ }
1509
+ cgi_trace(zLine);
1510
+ zToken = extract_token(zLine, &z);
1511
+ if( zToken==0 ){
1512
+ malformed_request("malformed probe");
1513
+ }
1514
+ }
1515
+
1516
+ /* Got all probes now first transport_open is completed
1517
+ ** so return the command that was requested
1518
+ */
1519
+ g.fSshClient |= CGI_SSH_COMPAT;
1520
+ return mprintf("%s", zToken);
1521
+}
1522
+
1523
+/*
1524
+** This routine handles the old fossil SSH transport_flip
1525
+** and transport_open communications if detected.
1526
+*/
1527
+void cgi_handle_ssh_transport(const char *zCmd){
1528
+ char *z, *zToken;
1529
+ char zLine[2000]; /* A single line of input. */
1530
+
1531
+ /* look for second newline of transport_flip */
1532
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1533
+ malformed_request("incorrect transport_flip");
1534
+ }
1535
+ cgi_trace(zLine);
1536
+ zToken = extract_token(zLine, &z);
1537
+ if( zToken && strlen(zToken)==0 ){
1538
+ /* look for path to fossil */
1539
+ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1540
+ if ( zCmd==0 ){
1541
+ malformed_request("missing fossil command");
1542
+ }else{
1543
+ /* no new command so exit */
1544
+ fossil_exit(0);
1545
+ }
1546
+ }
1547
+ cgi_trace(zLine);
1548
+ zToken = extract_token(zLine, &z);
1549
+ if( zToken==0 ){
1550
+ malformed_request("malformed fossil command");
1551
+ }
1552
+ /* see if we've seen the command */
1553
+ if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){
1554
+ return;
1555
+ }else{
1556
+ malformed_request("transport_open failed");
1557
+ }
1558
+ }else{
1559
+ malformed_request("transport_flip failed");
1560
+ }
1561
+}
13111562
13121563
/*
13131564
** This routine handles a single SCGI request which is coming in on
13141565
** g.httpIn and which replies on g.httpOut
13151566
**
@@ -1445,11 +1696,11 @@
14451696
#if defined(__CYGWIN__)
14461697
/* On Cygwin, we can do better than "echo" */
14471698
if( memcmp(zBrowser, "echo ", 5)==0 ){
14481699
wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
14491700
wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
1450
- if( ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
1701
+ if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
14511702
fossil_warning("cannot start browser\n");
14521703
}
14531704
}else
14541705
#endif
14551706
if( system(zBrowser)<0 ){
@@ -1604,5 +1855,23 @@
16041855
cgi_set_status(304,"Not Modified");
16051856
cgi_reset_content();
16061857
cgi_reply();
16071858
fossil_exit(0);
16081859
}
1860
+
1861
+/*
1862
+** Check to see if the remote client is SSH and return
1863
+** its IP or return default
1864
+*/
1865
+const char *cgi_ssh_remote_addr(const char *zDefault){
1866
+ char *zIndex;
1867
+ const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1868
+
1869
+ if( zSshConn && zSshConn[0] ){
1870
+ char *zSshClient = mprintf("%s",zSshConn);
1871
+ if( (zIndex = strchr(zSshClient,' '))!=0 ){
1872
+ zSshClient[zIndex-zSshClient] = '\0';
1873
+ return zSshClient;
1874
+ }
1875
+ }
1876
+ return zDefault;
1877
+}
16091878
--- src/cgi.c
+++ src/cgi.c
@@ -40,15 +40,11 @@
40 #include <time.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include "cgi.h"
45 #ifdef __CYGWIN__
46 __declspec(dllimport) extern __stdcall int ShellExecuteW(void *, void *,
47 void *, void *, void *, int);
48 __declspec(dllimport) extern __stdcall size_t wcslen(const wchar_t *);
49 #endif
50
51 #if INTERFACE
52 /*
53 ** Shortcuts for cgi_parameter. P("x") returns the value of query parameter
54 ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
@@ -64,10 +60,17 @@
64 ** Destinations for output text.
65 */
66 #define CGI_HEADER 0
67 #define CGI_BODY 1
68
 
 
 
 
 
 
 
69 #endif /* INTERFACE */
70
71 /*
72 ** The HTTP reply is generated in two pieces: the header and the body.
73 ** These pieces are generated separately because they are not necessary
@@ -827,26 +830,50 @@
827
828 /*
829 ** Initialize the query parameter database. Information is pulled from
830 ** the QUERY_STRING environment variable (if it exists), from standard
831 ** input if there is POST data, and from HTTP_COOKIE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
832 */
833 void cgi_init(void){
834 char *z;
835 const char *zType;
836 int len;
837 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
838 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
 
839
840 #ifdef FOSSIL_ENABLE_JSON
841 json_main_bootstrap();
842 #endif
843 g.isHTTP = 1;
844 cgi_destination(CGI_BODY);
845 if( zRequestUri==0 ) malformed_request("missing REQUEST_URI");
846 if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
847 if( cgi_parameter("PATH_INFO",0)==0 ){
 
 
 
 
 
 
 
 
 
848 int i, j;
849 for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){}
850 for(j=i; zRequestUri[j] && zRequestUri[j]!='?'; j++){}
851 cgi_set_parameter("PATH_INFO", mprintf("%.*s", j-i, zRequestUri+i));
852 }
@@ -1306,10 +1333,234 @@
1306 }
1307 }
1308 cgi_init();
1309 cgi_trace(0);
1310 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1311
1312 /*
1313 ** This routine handles a single SCGI request which is coming in on
1314 ** g.httpIn and which replies on g.httpOut
1315 **
@@ -1445,11 +1696,11 @@
1445 #if defined(__CYGWIN__)
1446 /* On Cygwin, we can do better than "echo" */
1447 if( memcmp(zBrowser, "echo ", 5)==0 ){
1448 wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
1449 wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
1450 if( ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
1451 fossil_warning("cannot start browser\n");
1452 }
1453 }else
1454 #endif
1455 if( system(zBrowser)<0 ){
@@ -1604,5 +1855,23 @@
1604 cgi_set_status(304,"Not Modified");
1605 cgi_reset_content();
1606 cgi_reply();
1607 fossil_exit(0);
1608 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1609
--- src/cgi.c
+++ src/cgi.c
@@ -40,15 +40,11 @@
40 #include <time.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include "cgi.h"
45 #include "cygsup.h"
 
 
 
 
46
47 #if INTERFACE
48 /*
49 ** Shortcuts for cgi_parameter. P("x") returns the value of query parameter
50 ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
@@ -64,10 +60,17 @@
60 ** Destinations for output text.
61 */
62 #define CGI_HEADER 0
63 #define CGI_BODY 1
64
65 /*
66 ** Flags for SSH HTTP clients
67 */
68 #define CGI_SSH_CLIENT 0x0001 /* Client is SSH */
69 #define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */
70 #define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */
71
72 #endif /* INTERFACE */
73
74 /*
75 ** The HTTP reply is generated in two pieces: the header and the body.
76 ** These pieces are generated separately because they are not necessary
@@ -827,26 +830,50 @@
830
831 /*
832 ** Initialize the query parameter database. Information is pulled from
833 ** the QUERY_STRING environment variable (if it exists), from standard
834 ** input if there is POST data, and from HTTP_COOKIE.
835 **
836 ** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows:
837 **
838 ** REQUEST_URI == SCRIPT_NAME + PATH_INFO
839 **
840 ** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If
841 ** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is
842 ** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided
843 ** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and
844 ** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then
845 ** assume that PATH_INFO is an empty string and set REQUEST_URI equal
846 ** to PATH_INFO.
847 **
848 ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and
849 ** PATH_INFO when it is empty.
850 */
851 void cgi_init(void){
852 char *z;
853 const char *zType;
854 int len;
855 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
856 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
857 const char *zPathInfo = cgi_parameter("PATH_INFO","");
858
859 #ifdef FOSSIL_ENABLE_JSON
860 json_main_bootstrap();
861 #endif
862 g.isHTTP = 1;
863 cgi_destination(CGI_BODY);
 
864 if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
865 if( zRequestUri==0 ){
866 const char *z = zPathInfo;
867 if( zPathInfo==0 ){
868 malformed_request("missing PATH_INFO and/or REQUEST_URI");
869 }
870 if( z[0]=='/' ) z++;
871 zRequestUri = mprintf("%s/%s", zScriptName, z);
872 cgi_set_parameter("REQUEST_URI", zRequestUri);
873 }
874 if( zPathInfo==0 ){
875 int i, j;
876 for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){}
877 for(j=i; zRequestUri[j] && zRequestUri[j]!='?'; j++){}
878 cgi_set_parameter("PATH_INFO", mprintf("%.*s", j-i, zRequestUri+i));
879 }
@@ -1306,10 +1333,234 @@
1333 }
1334 }
1335 cgi_init();
1336 cgi_trace(0);
1337 }
1338
1339 /*
1340 ** This routine handles a single HTTP request from an SSH client which is
1341 ** coming in on g.httpIn and which replies on g.httpOut
1342 **
1343 ** Once all the setup is finished, this procedure returns
1344 ** and subsequent code handles the actual generation of the webpage.
1345 **
1346 ** It is called in a loop so some variables will need to be replaced
1347 */
1348 void cgi_handle_ssh_http_request(const char *zIpAddr){
1349 static int nCycles = 0;
1350 static char *zCmd = 0;
1351 char *z, *zToken;
1352 const char *zType = 0;
1353 int i, content_length = 0;
1354 char zLine[2000]; /* A single line of input. */
1355
1356 if( zIpAddr ){
1357 if( nCycles==0 ){
1358 cgi_setenv("REMOTE_ADDR", zIpAddr);
1359 g.zIpAddr = mprintf("%s", zIpAddr);
1360 }
1361 }else{
1362 fossil_panic("missing SSH IP address");
1363 }
1364 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1365 malformed_request("missing HTTP header");
1366 }
1367 cgi_trace(zLine);
1368 zToken = extract_token(zLine, &z);
1369 if( zToken==0 ){
1370 malformed_request("malformed HTTP header");
1371 }
1372
1373 if( fossil_strcmp(zToken, "echo")==0 ){
1374 /* start looking for probes to complete transport_open */
1375 zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken);
1376 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1377 malformed_request("missing HTTP header");
1378 }
1379 cgi_trace(zLine);
1380 zToken = extract_token(zLine, &z);
1381 if( zToken==0 ){
1382 malformed_request("malformed HTTP header");
1383 }
1384 }else if( zToken && strlen(zToken)==0 && zCmd ){
1385 /* transport_flip request and continued transport_open */
1386 cgi_handle_ssh_transport(zCmd);
1387 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1388 malformed_request("missing HTTP header");
1389 }
1390 cgi_trace(zLine);
1391 zToken = extract_token(zLine, &z);
1392 if( zToken==0 ){
1393 malformed_request("malformed HTTP header");
1394 }
1395 }
1396
1397 if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
1398 && fossil_strcmp(zToken,"HEAD")!=0 ){
1399 malformed_request("unsupported HTTP method");
1400 }
1401
1402 if( nCycles==0 ){
1403 cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
1404 cgi_setenv("REQUEST_METHOD",zToken);
1405 }
1406
1407 zToken = extract_token(z, &z);
1408 if( zToken==0 ){
1409 malformed_request("malformed URL in HTTP header");
1410 }
1411 if( nCycles==0 ){
1412 cgi_setenv("REQUEST_URI", zToken);
1413 cgi_setenv("SCRIPT_NAME", "");
1414 }
1415
1416 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1417 if( zToken[i] ) zToken[i++] = 0;
1418 if( nCycles==0 ){
1419 cgi_setenv("PATH_INFO", zToken);
1420 }else{
1421 cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1422 }
1423
1424 /* Get all the optional fields that follow the first line.
1425 */
1426 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1427 char *zFieldName;
1428 char *zVal;
1429
1430 cgi_trace(zLine);
1431 zFieldName = extract_token(zLine,&zVal);
1432 if( zFieldName==0 || *zFieldName==0 ) break;
1433 while( fossil_isspace(*zVal) ){ zVal++; }
1434 i = strlen(zVal);
1435 while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; }
1436 zVal[i] = 0;
1437 for(i=0; zFieldName[i]; i++){
1438 zFieldName[i] = fossil_tolower(zFieldName[i]);
1439 }
1440 if( fossil_strcmp(zFieldName,"content-length:")==0 ){
1441 content_length = atoi(zVal);
1442 }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){
1443 g.zContentType = zType = mprintf("%s", zVal);
1444 }else if( fossil_strcmp(zFieldName,"host:")==0 ){
1445 if( nCycles==0 ){
1446 cgi_setenv("HTTP_HOST", zVal);
1447 }
1448 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1449 if( nCycles==0 ){
1450 cgi_setenv("HTTP_USER_AGENT", zVal);
1451 }
1452 }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){
1453 if( fossil_strnicmp(zVal, "ssh", 3)==0 ){
1454 if( nCycles==0 ){
1455 g.fSshClient |= CGI_SSH_FOSSIL;
1456 g.fullHttpReply = 0;
1457 }
1458 }
1459 }
1460 }
1461
1462 if( nCycles==0 ){
1463 if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){
1464 /* did not find new fossil ssh transport */
1465 g.fSshClient &= ~CGI_SSH_CLIENT;
1466 g.fullHttpReply = 1;
1467 cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1");
1468 }
1469 }
1470
1471 cgi_reset_content();
1472 cgi_destination(CGI_BODY);
1473
1474 if( content_length>0 && zType ){
1475 blob_zero(&g.cgiIn);
1476 if( fossil_strcmp(zType, "application/x-fossil")==0 ){
1477 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1478 blob_uncompress(&g.cgiIn, &g.cgiIn);
1479 }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1480 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1481 }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1482 blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
1483 }
1484 }
1485 cgi_trace(0);
1486 nCycles++;
1487 }
1488
1489 /*
1490 ** This routine handles the old fossil SSH probes
1491 */
1492 char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
1493 /* Start looking for probes */
1494 while( fossil_strcmp(zToken, "echo")==0 ){
1495 zToken = extract_token(z, &z);
1496 if( zToken==0 ){
1497 malformed_request("malformed probe");
1498 }
1499 if( fossil_strncmp(zToken, "test", 4)==0 ||
1500 fossil_strncmp(zToken, "probe-", 6)==0 ){
1501 fprintf(g.httpOut, "%s\n", zToken);
1502 fflush(g.httpOut);
1503 }else{
1504 malformed_request("malformed probe");
1505 }
1506 if( fgets(zLine, zSize, g.httpIn)==0 ){
1507 malformed_request("malformed probe");
1508 }
1509 cgi_trace(zLine);
1510 zToken = extract_token(zLine, &z);
1511 if( zToken==0 ){
1512 malformed_request("malformed probe");
1513 }
1514 }
1515
1516 /* Got all probes now first transport_open is completed
1517 ** so return the command that was requested
1518 */
1519 g.fSshClient |= CGI_SSH_COMPAT;
1520 return mprintf("%s", zToken);
1521 }
1522
1523 /*
1524 ** This routine handles the old fossil SSH transport_flip
1525 ** and transport_open communications if detected.
1526 */
1527 void cgi_handle_ssh_transport(const char *zCmd){
1528 char *z, *zToken;
1529 char zLine[2000]; /* A single line of input. */
1530
1531 /* look for second newline of transport_flip */
1532 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1533 malformed_request("incorrect transport_flip");
1534 }
1535 cgi_trace(zLine);
1536 zToken = extract_token(zLine, &z);
1537 if( zToken && strlen(zToken)==0 ){
1538 /* look for path to fossil */
1539 if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
1540 if ( zCmd==0 ){
1541 malformed_request("missing fossil command");
1542 }else{
1543 /* no new command so exit */
1544 fossil_exit(0);
1545 }
1546 }
1547 cgi_trace(zLine);
1548 zToken = extract_token(zLine, &z);
1549 if( zToken==0 ){
1550 malformed_request("malformed fossil command");
1551 }
1552 /* see if we've seen the command */
1553 if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){
1554 return;
1555 }else{
1556 malformed_request("transport_open failed");
1557 }
1558 }else{
1559 malformed_request("transport_flip failed");
1560 }
1561 }
1562
1563 /*
1564 ** This routine handles a single SCGI request which is coming in on
1565 ** g.httpIn and which replies on g.httpOut
1566 **
@@ -1445,11 +1696,11 @@
1696 #if defined(__CYGWIN__)
1697 /* On Cygwin, we can do better than "echo" */
1698 if( memcmp(zBrowser, "echo ", 5)==0 ){
1699 wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
1700 wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
1701 if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
1702 fossil_warning("cannot start browser\n");
1703 }
1704 }else
1705 #endif
1706 if( system(zBrowser)<0 ){
@@ -1604,5 +1855,23 @@
1855 cgi_set_status(304,"Not Modified");
1856 cgi_reset_content();
1857 cgi_reply();
1858 fossil_exit(0);
1859 }
1860
1861 /*
1862 ** Check to see if the remote client is SSH and return
1863 ** its IP or return default
1864 */
1865 const char *cgi_ssh_remote_addr(const char *zDefault){
1866 char *zIndex;
1867 const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1868
1869 if( zSshConn && zSshConn[0] ){
1870 char *zSshClient = mprintf("%s",zSshConn);
1871 if( (zIndex = strchr(zSshClient,' '))!=0 ){
1872 zSshClient[zIndex-zSshClient] = '\0';
1873 return zSshClient;
1874 }
1875 }
1876 return zDefault;
1877 }
1878
+38 -23
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827827
#else
828828
blob_init(&prompt, zInit, -1);
829829
#endif
830830
blob_append(&prompt,
831831
"\n"
832
- "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
832
+ "# Enter commit message for this check-in. Lines beginning with # are ignored.\n"
833833
"#\n", -1
834834
);
835835
blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836836
if( p->zBranch && p->zBranch[0] ){
837837
blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
10041004
int vid, /* BLOB.id for the parent check-in */
10051005
CheckinInfo *p, /* Information about the check-in */
10061006
int *pnFBcard /* OUT: Number of generated B- and F-cards */
10071007
){
10081008
char *zDate; /* Date of the check-in */
1009
- char *zParentUuid; /* UUID of parent check-in */
1009
+ char *zParentUuid = 0; /* UUID of parent check-in */
10101010
Blob filename; /* A single filename */
10111011
int nBasename; /* Size of base filename */
10121012
Stmt q; /* Various queries */
10131013
Blob mcksum; /* Manifest checksum */
10141014
ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
10171017
const char *zColor; /* Modified value of p->zColor */
10181018
10191019
assert( pBaseline==0 || pBaseline->zBaseline==0 );
10201020
assert( pBaseline==0 || zBaselineUuid!=0 );
10211021
blob_zero(pOut);
1022
- zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1022
+ if( vid ){
1023
+ zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
1024
+ "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
1025
+ vid, vid);
1026
+ if( !zParentUuid ){
1027
+ fossil_fatal("Could not find a valid check-in for RID %d. "
1028
+ "Possible checkout/repo mismatch.", vid);
1029
+ }
1030
+ }
10231031
if( pBaseline ){
10241032
blob_appendf(pOut, "B %s\n", zBaselineUuid);
10251033
manifest_file_rewind(pBaseline);
10261034
pFile = manifest_file_next(pBaseline, 0);
10271035
nFBcard++;
@@ -1112,28 +1120,30 @@
11121120
nFBcard++;
11131121
}
11141122
if( p->zMimetype && p->zMimetype[0] ){
11151123
blob_appendf(pOut, "N %F\n", p->zMimetype);
11161124
}
1117
- blob_appendf(pOut, "P %s", zParentUuid);
1118
- if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1119
- free(zParentUuid);
1120
- db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1121
- while( db_step(&q)==SQLITE_ROW ){
1122
- char *zMergeUuid;
1123
- int mid = db_column_int(&q, 0);
1124
- if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1125
- zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1126
- if( zMergeUuid ){
1127
- blob_appendf(pOut, " %s", zMergeUuid);
1128
- if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1129
- free(zMergeUuid);
1130
- }
1131
- }
1132
- db_finalize(&q);
1133
- free(zDate);
1134
- blob_appendf(pOut, "\n");
1125
+ if( vid ){
1126
+ blob_appendf(pOut, "P %s", zParentUuid);
1127
+ if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1128
+ free(zParentUuid);
1129
+ db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1130
+ while( db_step(&q)==SQLITE_ROW ){
1131
+ char *zMergeUuid;
1132
+ int mid = db_column_int(&q, 0);
1133
+ if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1134
+ zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1135
+ if( zMergeUuid ){
1136
+ blob_appendf(pOut, " %s", zMergeUuid);
1137
+ if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1138
+ free(zMergeUuid);
1139
+ }
1140
+ }
1141
+ db_finalize(&q);
1142
+ blob_appendf(pOut, "\n");
1143
+ }
1144
+ free(zDate);
11351145
11361146
db_prepare(&q,
11371147
"SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
11381148
" FROM vmerge, blob"
11391149
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
16291639
}
16301640
16311641
/*
16321642
** Do not allow a commit that will cause a fork unless the --allow-fork
16331643
** or --force flags is used, or unless this is a private check-in.
1644
+ ** The initial commit MUST have tags "trunk" and "sym-trunk".
16341645
*/
1635
- if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
1646
+ if( !vid ){
1647
+ if( sCiInfo.zBranch==0 ){
1648
+ sCiInfo.zBranch = db_get("main-branch", "trunk");
1649
+ }
1650
+ }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
16361651
&& g.markPrivate==0 && !is_a_leaf(vid)
16371652
){
16381653
fossil_fatal("would fork. \"update\" first or use --allow-fork.");
16391654
}
16401655
@@ -1760,11 +1775,11 @@
17601775
/* See if a delta-manifest would be more appropriate */
17611776
if( !forceBaseline ){
17621777
const char *zBaselineUuid;
17631778
Manifest *pParent;
17641779
Manifest *pBaseline;
1765
- pParent = manifest_get(vid, CFTYPE_MANIFEST);
1780
+ pParent = manifest_get(vid, CFTYPE_MANIFEST, 0);
17661781
if( pParent && pParent->zBaseline ){
17671782
zBaselineUuid = pParent->zBaseline;
17681783
pBaseline = manifest_get_by_name(zBaselineUuid, 0);
17691784
}else{
17701785
zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
17711786
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827 #else
828 blob_init(&prompt, zInit, -1);
829 #endif
830 blob_append(&prompt,
831 "\n"
832 "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
833 "#\n", -1
834 );
835 blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836 if( p->zBranch && p->zBranch[0] ){
837 blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
1004 int vid, /* BLOB.id for the parent check-in */
1005 CheckinInfo *p, /* Information about the check-in */
1006 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1007 ){
1008 char *zDate; /* Date of the check-in */
1009 char *zParentUuid; /* UUID of parent check-in */
1010 Blob filename; /* A single filename */
1011 int nBasename; /* Size of base filename */
1012 Stmt q; /* Various queries */
1013 Blob mcksum; /* Manifest checksum */
1014 ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
1017 const char *zColor; /* Modified value of p->zColor */
1018
1019 assert( pBaseline==0 || pBaseline->zBaseline==0 );
1020 assert( pBaseline==0 || zBaselineUuid!=0 );
1021 blob_zero(pOut);
1022 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
 
 
 
 
 
 
 
 
1023 if( pBaseline ){
1024 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1025 manifest_file_rewind(pBaseline);
1026 pFile = manifest_file_next(pBaseline, 0);
1027 nFBcard++;
@@ -1112,28 +1120,30 @@
1112 nFBcard++;
1113 }
1114 if( p->zMimetype && p->zMimetype[0] ){
1115 blob_appendf(pOut, "N %F\n", p->zMimetype);
1116 }
1117 blob_appendf(pOut, "P %s", zParentUuid);
1118 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1119 free(zParentUuid);
1120 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1121 while( db_step(&q)==SQLITE_ROW ){
1122 char *zMergeUuid;
1123 int mid = db_column_int(&q, 0);
1124 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1125 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1126 if( zMergeUuid ){
1127 blob_appendf(pOut, " %s", zMergeUuid);
1128 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1129 free(zMergeUuid);
1130 }
1131 }
1132 db_finalize(&q);
1133 free(zDate);
1134 blob_appendf(pOut, "\n");
 
 
1135
1136 db_prepare(&q,
1137 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1138 " FROM vmerge, blob"
1139 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
1629 }
1630
1631 /*
1632 ** Do not allow a commit that will cause a fork unless the --allow-fork
1633 ** or --force flags is used, or unless this is a private check-in.
 
1634 */
1635 if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
 
 
 
 
1636 && g.markPrivate==0 && !is_a_leaf(vid)
1637 ){
1638 fossil_fatal("would fork. \"update\" first or use --allow-fork.");
1639 }
1640
@@ -1760,11 +1775,11 @@
1760 /* See if a delta-manifest would be more appropriate */
1761 if( !forceBaseline ){
1762 const char *zBaselineUuid;
1763 Manifest *pParent;
1764 Manifest *pBaseline;
1765 pParent = manifest_get(vid, CFTYPE_MANIFEST);
1766 if( pParent && pParent->zBaseline ){
1767 zBaselineUuid = pParent->zBaseline;
1768 pBaseline = manifest_get_by_name(zBaselineUuid, 0);
1769 }else{
1770 zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1771
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827 #else
828 blob_init(&prompt, zInit, -1);
829 #endif
830 blob_append(&prompt,
831 "\n"
832 "# Enter commit message for this check-in. Lines beginning with # are ignored.\n"
833 "#\n", -1
834 );
835 blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836 if( p->zBranch && p->zBranch[0] ){
837 blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
1004 int vid, /* BLOB.id for the parent check-in */
1005 CheckinInfo *p, /* Information about the check-in */
1006 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1007 ){
1008 char *zDate; /* Date of the check-in */
1009 char *zParentUuid = 0; /* UUID of parent check-in */
1010 Blob filename; /* A single filename */
1011 int nBasename; /* Size of base filename */
1012 Stmt q; /* Various queries */
1013 Blob mcksum; /* Manifest checksum */
1014 ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
1017 const char *zColor; /* Modified value of p->zColor */
1018
1019 assert( pBaseline==0 || pBaseline->zBaseline==0 );
1020 assert( pBaseline==0 || zBaselineUuid!=0 );
1021 blob_zero(pOut);
1022 if( vid ){
1023 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
1024 "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
1025 vid, vid);
1026 if( !zParentUuid ){
1027 fossil_fatal("Could not find a valid check-in for RID %d. "
1028 "Possible checkout/repo mismatch.", vid);
1029 }
1030 }
1031 if( pBaseline ){
1032 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1033 manifest_file_rewind(pBaseline);
1034 pFile = manifest_file_next(pBaseline, 0);
1035 nFBcard++;
@@ -1112,28 +1120,30 @@
1120 nFBcard++;
1121 }
1122 if( p->zMimetype && p->zMimetype[0] ){
1123 blob_appendf(pOut, "N %F\n", p->zMimetype);
1124 }
1125 if( vid ){
1126 blob_appendf(pOut, "P %s", zParentUuid);
1127 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1128 free(zParentUuid);
1129 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1130 while( db_step(&q)==SQLITE_ROW ){
1131 char *zMergeUuid;
1132 int mid = db_column_int(&q, 0);
1133 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1134 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1135 if( zMergeUuid ){
1136 blob_appendf(pOut, " %s", zMergeUuid);
1137 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1138 free(zMergeUuid);
1139 }
1140 }
1141 db_finalize(&q);
1142 blob_appendf(pOut, "\n");
1143 }
1144 free(zDate);
1145
1146 db_prepare(&q,
1147 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1148 " FROM vmerge, blob"
1149 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
1639 }
1640
1641 /*
1642 ** Do not allow a commit that will cause a fork unless the --allow-fork
1643 ** or --force flags is used, or unless this is a private check-in.
1644 ** The initial commit MUST have tags "trunk" and "sym-trunk".
1645 */
1646 if( !vid ){
1647 if( sCiInfo.zBranch==0 ){
1648 sCiInfo.zBranch = db_get("main-branch", "trunk");
1649 }
1650 }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
1651 && g.markPrivate==0 && !is_a_leaf(vid)
1652 ){
1653 fossil_fatal("would fork. \"update\" first or use --allow-fork.");
1654 }
1655
@@ -1760,11 +1775,11 @@
1775 /* See if a delta-manifest would be more appropriate */
1776 if( !forceBaseline ){
1777 const char *zBaselineUuid;
1778 Manifest *pParent;
1779 Manifest *pBaseline;
1780 pParent = manifest_get(vid, CFTYPE_MANIFEST, 0);
1781 if( pParent && pParent->zBaseline ){
1782 zBaselineUuid = pParent->zBaseline;
1783 pBaseline = manifest_get_by_name(zBaselineUuid, 0);
1784 }else{
1785 zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1786
+38 -23
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827827
#else
828828
blob_init(&prompt, zInit, -1);
829829
#endif
830830
blob_append(&prompt,
831831
"\n"
832
- "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
832
+ "# Enter commit message for this check-in. Lines beginning with # are ignored.\n"
833833
"#\n", -1
834834
);
835835
blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836836
if( p->zBranch && p->zBranch[0] ){
837837
blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
10041004
int vid, /* BLOB.id for the parent check-in */
10051005
CheckinInfo *p, /* Information about the check-in */
10061006
int *pnFBcard /* OUT: Number of generated B- and F-cards */
10071007
){
10081008
char *zDate; /* Date of the check-in */
1009
- char *zParentUuid; /* UUID of parent check-in */
1009
+ char *zParentUuid = 0; /* UUID of parent check-in */
10101010
Blob filename; /* A single filename */
10111011
int nBasename; /* Size of base filename */
10121012
Stmt q; /* Various queries */
10131013
Blob mcksum; /* Manifest checksum */
10141014
ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
10171017
const char *zColor; /* Modified value of p->zColor */
10181018
10191019
assert( pBaseline==0 || pBaseline->zBaseline==0 );
10201020
assert( pBaseline==0 || zBaselineUuid!=0 );
10211021
blob_zero(pOut);
1022
- zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1022
+ if( vid ){
1023
+ zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
1024
+ "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
1025
+ vid, vid);
1026
+ if( !zParentUuid ){
1027
+ fossil_fatal("Could not find a valid check-in for RID %d. "
1028
+ "Possible checkout/repo mismatch.", vid);
1029
+ }
1030
+ }
10231031
if( pBaseline ){
10241032
blob_appendf(pOut, "B %s\n", zBaselineUuid);
10251033
manifest_file_rewind(pBaseline);
10261034
pFile = manifest_file_next(pBaseline, 0);
10271035
nFBcard++;
@@ -1112,28 +1120,30 @@
11121120
nFBcard++;
11131121
}
11141122
if( p->zMimetype && p->zMimetype[0] ){
11151123
blob_appendf(pOut, "N %F\n", p->zMimetype);
11161124
}
1117
- blob_appendf(pOut, "P %s", zParentUuid);
1118
- if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1119
- free(zParentUuid);
1120
- db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1121
- while( db_step(&q)==SQLITE_ROW ){
1122
- char *zMergeUuid;
1123
- int mid = db_column_int(&q, 0);
1124
- if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1125
- zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1126
- if( zMergeUuid ){
1127
- blob_appendf(pOut, " %s", zMergeUuid);
1128
- if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1129
- free(zMergeUuid);
1130
- }
1131
- }
1132
- db_finalize(&q);
1133
- free(zDate);
1134
- blob_appendf(pOut, "\n");
1125
+ if( vid ){
1126
+ blob_appendf(pOut, "P %s", zParentUuid);
1127
+ if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1128
+ free(zParentUuid);
1129
+ db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1130
+ while( db_step(&q)==SQLITE_ROW ){
1131
+ char *zMergeUuid;
1132
+ int mid = db_column_int(&q, 0);
1133
+ if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1134
+ zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1135
+ if( zMergeUuid ){
1136
+ blob_appendf(pOut, " %s", zMergeUuid);
1137
+ if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1138
+ free(zMergeUuid);
1139
+ }
1140
+ }
1141
+ db_finalize(&q);
1142
+ blob_appendf(pOut, "\n");
1143
+ }
1144
+ free(zDate);
11351145
11361146
db_prepare(&q,
11371147
"SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
11381148
" FROM vmerge, blob"
11391149
" WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
16291639
}
16301640
16311641
/*
16321642
** Do not allow a commit that will cause a fork unless the --allow-fork
16331643
** or --force flags is used, or unless this is a private check-in.
1644
+ ** The initial commit MUST have tags "trunk" and "sym-trunk".
16341645
*/
1635
- if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
1646
+ if( !vid ){
1647
+ if( sCiInfo.zBranch==0 ){
1648
+ sCiInfo.zBranch = db_get("main-branch", "trunk");
1649
+ }
1650
+ }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
16361651
&& g.markPrivate==0 && !is_a_leaf(vid)
16371652
){
16381653
fossil_fatal("would fork. \"update\" first or use --allow-fork.");
16391654
}
16401655
@@ -1760,11 +1775,11 @@
17601775
/* See if a delta-manifest would be more appropriate */
17611776
if( !forceBaseline ){
17621777
const char *zBaselineUuid;
17631778
Manifest *pParent;
17641779
Manifest *pBaseline;
1765
- pParent = manifest_get(vid, CFTYPE_MANIFEST);
1780
+ pParent = manifest_get(vid, CFTYPE_MANIFEST, 0);
17661781
if( pParent && pParent->zBaseline ){
17671782
zBaselineUuid = pParent->zBaseline;
17681783
pBaseline = manifest_get_by_name(zBaselineUuid, 0);
17691784
}else{
17701785
zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
17711786
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827 #else
828 blob_init(&prompt, zInit, -1);
829 #endif
830 blob_append(&prompt,
831 "\n"
832 "# Enter comments on this check-in. Lines beginning with # are ignored.\n"
833 "#\n", -1
834 );
835 blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836 if( p->zBranch && p->zBranch[0] ){
837 blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
1004 int vid, /* BLOB.id for the parent check-in */
1005 CheckinInfo *p, /* Information about the check-in */
1006 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1007 ){
1008 char *zDate; /* Date of the check-in */
1009 char *zParentUuid; /* UUID of parent check-in */
1010 Blob filename; /* A single filename */
1011 int nBasename; /* Size of base filename */
1012 Stmt q; /* Various queries */
1013 Blob mcksum; /* Manifest checksum */
1014 ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
1017 const char *zColor; /* Modified value of p->zColor */
1018
1019 assert( pBaseline==0 || pBaseline->zBaseline==0 );
1020 assert( pBaseline==0 || zBaselineUuid!=0 );
1021 blob_zero(pOut);
1022 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
 
 
 
 
 
 
 
 
1023 if( pBaseline ){
1024 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1025 manifest_file_rewind(pBaseline);
1026 pFile = manifest_file_next(pBaseline, 0);
1027 nFBcard++;
@@ -1112,28 +1120,30 @@
1112 nFBcard++;
1113 }
1114 if( p->zMimetype && p->zMimetype[0] ){
1115 blob_appendf(pOut, "N %F\n", p->zMimetype);
1116 }
1117 blob_appendf(pOut, "P %s", zParentUuid);
1118 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1119 free(zParentUuid);
1120 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1121 while( db_step(&q)==SQLITE_ROW ){
1122 char *zMergeUuid;
1123 int mid = db_column_int(&q, 0);
1124 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1125 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1126 if( zMergeUuid ){
1127 blob_appendf(pOut, " %s", zMergeUuid);
1128 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1129 free(zMergeUuid);
1130 }
1131 }
1132 db_finalize(&q);
1133 free(zDate);
1134 blob_appendf(pOut, "\n");
 
 
1135
1136 db_prepare(&q,
1137 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1138 " FROM vmerge, blob"
1139 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
1629 }
1630
1631 /*
1632 ** Do not allow a commit that will cause a fork unless the --allow-fork
1633 ** or --force flags is used, or unless this is a private check-in.
 
1634 */
1635 if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
 
 
 
 
1636 && g.markPrivate==0 && !is_a_leaf(vid)
1637 ){
1638 fossil_fatal("would fork. \"update\" first or use --allow-fork.");
1639 }
1640
@@ -1760,11 +1775,11 @@
1760 /* See if a delta-manifest would be more appropriate */
1761 if( !forceBaseline ){
1762 const char *zBaselineUuid;
1763 Manifest *pParent;
1764 Manifest *pBaseline;
1765 pParent = manifest_get(vid, CFTYPE_MANIFEST);
1766 if( pParent && pParent->zBaseline ){
1767 zBaselineUuid = pParent->zBaseline;
1768 pBaseline = manifest_get_by_name(zBaselineUuid, 0);
1769 }else{
1770 zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1771
--- src/checkin.c
+++ src/checkin.c
@@ -827,11 +827,11 @@
827 #else
828 blob_init(&prompt, zInit, -1);
829 #endif
830 blob_append(&prompt,
831 "\n"
832 "# Enter commit message for this check-in. Lines beginning with # are ignored.\n"
833 "#\n", -1
834 );
835 blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin);
836 if( p->zBranch && p->zBranch[0] ){
837 blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
@@ -1004,11 +1004,11 @@
1004 int vid, /* BLOB.id for the parent check-in */
1005 CheckinInfo *p, /* Information about the check-in */
1006 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1007 ){
1008 char *zDate; /* Date of the check-in */
1009 char *zParentUuid = 0; /* UUID of parent check-in */
1010 Blob filename; /* A single filename */
1011 int nBasename; /* Size of base filename */
1012 Stmt q; /* Various queries */
1013 Blob mcksum; /* Manifest checksum */
1014 ManifestFile *pFile; /* File from the baseline */
@@ -1017,11 +1017,19 @@
1017 const char *zColor; /* Modified value of p->zColor */
1018
1019 assert( pBaseline==0 || pBaseline->zBaseline==0 );
1020 assert( pBaseline==0 || zBaselineUuid!=0 );
1021 blob_zero(pOut);
1022 if( vid ){
1023 zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
1024 "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
1025 vid, vid);
1026 if( !zParentUuid ){
1027 fossil_fatal("Could not find a valid check-in for RID %d. "
1028 "Possible checkout/repo mismatch.", vid);
1029 }
1030 }
1031 if( pBaseline ){
1032 blob_appendf(pOut, "B %s\n", zBaselineUuid);
1033 manifest_file_rewind(pBaseline);
1034 pFile = manifest_file_next(pBaseline, 0);
1035 nFBcard++;
@@ -1112,28 +1120,30 @@
1120 nFBcard++;
1121 }
1122 if( p->zMimetype && p->zMimetype[0] ){
1123 blob_appendf(pOut, "N %F\n", p->zMimetype);
1124 }
1125 if( vid ){
1126 blob_appendf(pOut, "P %s", zParentUuid);
1127 if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
1128 free(zParentUuid);
1129 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
1130 while( db_step(&q)==SQLITE_ROW ){
1131 char *zMergeUuid;
1132 int mid = db_column_int(&q, 0);
1133 if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
1134 zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
1135 if( zMergeUuid ){
1136 blob_appendf(pOut, " %s", zMergeUuid);
1137 if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
1138 free(zMergeUuid);
1139 }
1140 }
1141 db_finalize(&q);
1142 blob_appendf(pOut, "\n");
1143 }
1144 free(zDate);
1145
1146 db_prepare(&q,
1147 "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
1148 " FROM vmerge, blob"
1149 " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
@@ -1629,12 +1639,17 @@
1639 }
1640
1641 /*
1642 ** Do not allow a commit that will cause a fork unless the --allow-fork
1643 ** or --force flags is used, or unless this is a private check-in.
1644 ** The initial commit MUST have tags "trunk" and "sym-trunk".
1645 */
1646 if( !vid ){
1647 if( sCiInfo.zBranch==0 ){
1648 sCiInfo.zBranch = db_get("main-branch", "trunk");
1649 }
1650 }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
1651 && g.markPrivate==0 && !is_a_leaf(vid)
1652 ){
1653 fossil_fatal("would fork. \"update\" first or use --allow-fork.");
1654 }
1655
@@ -1760,11 +1775,11 @@
1775 /* See if a delta-manifest would be more appropriate */
1776 if( !forceBaseline ){
1777 const char *zBaselineUuid;
1778 Manifest *pParent;
1779 Manifest *pBaseline;
1780 pParent = manifest_get(vid, CFTYPE_MANIFEST, 0);
1781 if( pParent && pParent->zBaseline ){
1782 zBaselineUuid = pParent->zBaseline;
1783 pBaseline = manifest_get_by_name(zBaselineUuid, 0);
1784 }else{
1785 zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
1786
+2 -2
--- src/checkout.c
+++ src/checkout.c
@@ -103,11 +103,11 @@
103103
Manifest *pManifest;
104104
ManifestFile *pFile;
105105
106106
/* Check the EXE permission status of all files
107107
*/
108
- pManifest = manifest_get(vid, CFTYPE_MANIFEST);
108
+ pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
109109
if( pManifest==0 ) return;
110110
blob_zero(&filename);
111111
blob_appendf(&filename, "%s", g.zLocalRoot);
112112
baseLen = blob_size(&filename);
113113
manifest_file_rewind(pManifest);
@@ -220,11 +220,11 @@
220220
zVers = db_text(0, "SELECT uuid FROM event, blob"
221221
" WHERE event.objid=blob.rid AND event.type='ci'"
222222
" ORDER BY event.mtime DESC");
223223
}
224224
if( zVers==0 ){
225
- fossil_fatal("cannot locate \"latest\" checkout");
225
+ return;
226226
}
227227
}else{
228228
zVers = g.argv[2];
229229
}
230230
vid = load_vfile(zVers);
231231
--- src/checkout.c
+++ src/checkout.c
@@ -103,11 +103,11 @@
103 Manifest *pManifest;
104 ManifestFile *pFile;
105
106 /* Check the EXE permission status of all files
107 */
108 pManifest = manifest_get(vid, CFTYPE_MANIFEST);
109 if( pManifest==0 ) return;
110 blob_zero(&filename);
111 blob_appendf(&filename, "%s", g.zLocalRoot);
112 baseLen = blob_size(&filename);
113 manifest_file_rewind(pManifest);
@@ -220,11 +220,11 @@
220 zVers = db_text(0, "SELECT uuid FROM event, blob"
221 " WHERE event.objid=blob.rid AND event.type='ci'"
222 " ORDER BY event.mtime DESC");
223 }
224 if( zVers==0 ){
225 fossil_fatal("cannot locate \"latest\" checkout");
226 }
227 }else{
228 zVers = g.argv[2];
229 }
230 vid = load_vfile(zVers);
231
--- src/checkout.c
+++ src/checkout.c
@@ -103,11 +103,11 @@
103 Manifest *pManifest;
104 ManifestFile *pFile;
105
106 /* Check the EXE permission status of all files
107 */
108 pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
109 if( pManifest==0 ) return;
110 blob_zero(&filename);
111 blob_appendf(&filename, "%s", g.zLocalRoot);
112 baseLen = blob_size(&filename);
113 manifest_file_rewind(pManifest);
@@ -220,11 +220,11 @@
220 zVers = db_text(0, "SELECT uuid FROM event, blob"
221 " WHERE event.objid=blob.rid AND event.type='ci'"
222 " ORDER BY event.mtime DESC");
223 }
224 if( zVers==0 ){
225 return;
226 }
227 }else{
228 zVers = g.argv[2];
229 }
230 vid = load_vfile(zVers);
231
+26
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107107
**
108108
** Options:
109109
** --admin-user|-A USERNAME Make USERNAME the administrator
110110
** --private Also clone private branches
111111
** --ssl-identity=filename Use the SSL identity if requested by the server
112
+** --ssh-command|-c 'command' Use this SSH command
112113
**
113114
** See also: init
114115
*/
115116
void clone_cmd(void){
116117
char *zPassword;
@@ -117,10 +118,11 @@
117118
const char *zDefaultUser; /* Optional name of the default user */
118119
int nErr = 0;
119120
int bPrivate = 0; /* Also clone private branches */
120121
121122
if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
123
+ clone_ssh_find_options();
122124
url_proxy_options();
123125
if( g.argc < 4 ){
124126
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
125127
}
126128
db_open_config(0);
@@ -129,10 +131,11 @@
129131
}
130132
131133
zDefaultUser = find_option("admin-user","A",1);
132134
133135
url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
136
+ if( zDefaultUser==0 && g.urlUser!=0 ) zDefaultUser = g.urlUser;
134137
if( g.urlIsFile ){
135138
file_copy(g.urlName, g.argv[3]);
136139
db_close(1);
137140
db_open_repository(g.argv[3]);
138141
db_record_repository_filename(g.argv[3]);
@@ -167,10 +170,11 @@
167170
db_multi_exec(
168171
"REPLACE INTO config(name,value,mtime)"
169172
" VALUES('server-code', lower(hex(randomblob(20))), now());"
170173
);
171174
url_enable_proxy(0);
175
+ clone_ssh_db_set_options();
172176
url_get_password_if_needed();
173177
g.xlinkClusterOnly = 1;
174178
nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
175179
g.xlinkClusterOnly = 0;
176180
verify_cancel();
@@ -188,5 +192,27 @@
188192
fossil_print("project-id: %s\n", db_get("project-code", 0));
189193
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
190194
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
191195
db_end_transaction(0);
192196
}
197
+
198
+/*
199
+** Look for SSH clone command line options and setup in globals.
200
+*/
201
+void clone_ssh_find_options(void){
202
+ const char *zSshCmd; /* SSH command string */
203
+
204
+ zSshCmd = find_option("ssh-command","c",1);
205
+ if( zSshCmd && zSshCmd[0] ){
206
+ g.zSshCmd = mprintf("%s", zSshCmd);
207
+ }
208
+}
209
+
210
+/*
211
+** Set SSH options discovered in global variables (set from command line
212
+** options).
213
+*/
214
+void clone_ssh_db_set_options(void){
215
+ if( g.zSshCmd && g.zSshCmd[0] ){
216
+ db_set("ssh-command", g.zSshCmd, 0);
217
+ }
218
+}
193219
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107 **
108 ** Options:
109 ** --admin-user|-A USERNAME Make USERNAME the administrator
110 ** --private Also clone private branches
111 ** --ssl-identity=filename Use the SSL identity if requested by the server
 
112 **
113 ** See also: init
114 */
115 void clone_cmd(void){
116 char *zPassword;
@@ -117,10 +118,11 @@
117 const char *zDefaultUser; /* Optional name of the default user */
118 int nErr = 0;
119 int bPrivate = 0; /* Also clone private branches */
120
121 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
 
122 url_proxy_options();
123 if( g.argc < 4 ){
124 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
125 }
126 db_open_config(0);
@@ -129,10 +131,11 @@
129 }
130
131 zDefaultUser = find_option("admin-user","A",1);
132
133 url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
 
134 if( g.urlIsFile ){
135 file_copy(g.urlName, g.argv[3]);
136 db_close(1);
137 db_open_repository(g.argv[3]);
138 db_record_repository_filename(g.argv[3]);
@@ -167,10 +170,11 @@
167 db_multi_exec(
168 "REPLACE INTO config(name,value,mtime)"
169 " VALUES('server-code', lower(hex(randomblob(20))), now());"
170 );
171 url_enable_proxy(0);
 
172 url_get_password_if_needed();
173 g.xlinkClusterOnly = 1;
174 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
175 g.xlinkClusterOnly = 0;
176 verify_cancel();
@@ -188,5 +192,27 @@
188 fossil_print("project-id: %s\n", db_get("project-code", 0));
189 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
190 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
191 db_end_transaction(0);
192 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
--- src/clone.c
+++ src/clone.c
@@ -107,10 +107,11 @@
107 **
108 ** Options:
109 ** --admin-user|-A USERNAME Make USERNAME the administrator
110 ** --private Also clone private branches
111 ** --ssl-identity=filename Use the SSL identity if requested by the server
112 ** --ssh-command|-c 'command' Use this SSH command
113 **
114 ** See also: init
115 */
116 void clone_cmd(void){
117 char *zPassword;
@@ -117,10 +118,11 @@
118 const char *zDefaultUser; /* Optional name of the default user */
119 int nErr = 0;
120 int bPrivate = 0; /* Also clone private branches */
121
122 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
123 clone_ssh_find_options();
124 url_proxy_options();
125 if( g.argc < 4 ){
126 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
127 }
128 db_open_config(0);
@@ -129,10 +131,11 @@
131 }
132
133 zDefaultUser = find_option("admin-user","A",1);
134
135 url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
136 if( zDefaultUser==0 && g.urlUser!=0 ) zDefaultUser = g.urlUser;
137 if( g.urlIsFile ){
138 file_copy(g.urlName, g.argv[3]);
139 db_close(1);
140 db_open_repository(g.argv[3]);
141 db_record_repository_filename(g.argv[3]);
@@ -167,10 +170,11 @@
170 db_multi_exec(
171 "REPLACE INTO config(name,value,mtime)"
172 " VALUES('server-code', lower(hex(randomblob(20))), now());"
173 );
174 url_enable_proxy(0);
175 clone_ssh_db_set_options();
176 url_get_password_if_needed();
177 g.xlinkClusterOnly = 1;
178 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
179 g.xlinkClusterOnly = 0;
180 verify_cancel();
@@ -188,5 +192,27 @@
192 fossil_print("project-id: %s\n", db_get("project-code", 0));
193 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
194 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
195 db_end_transaction(0);
196 }
197
198 /*
199 ** Look for SSH clone command line options and setup in globals.
200 */
201 void clone_ssh_find_options(void){
202 const char *zSshCmd; /* SSH command string */
203
204 zSshCmd = find_option("ssh-command","c",1);
205 if( zSshCmd && zSshCmd[0] ){
206 g.zSshCmd = mprintf("%s", zSshCmd);
207 }
208 }
209
210 /*
211 ** Set SSH options discovered in global variables (set from command line
212 ** options).
213 */
214 void clone_ssh_db_set_options(void){
215 if( g.zSshCmd && g.zSshCmd[0] ){
216 db_set("ssh-command", g.zSshCmd, 0);
217 }
218 }
219
+12 -7
--- src/comformat.c
+++ src/comformat.c
@@ -26,28 +26,36 @@
2626
** Given a comment string zText, format that string for printing
2727
** on a TTY. Assume that the output cursors is indent spaces from
2828
** the left margin and that a single line can contain no more than
2929
** lineLength characters. Indent all subsequent lines by indent.
3030
**
31
-** lineLength must be less than 400.
32
-**
3331
** Return the number of newlines that are output.
3432
*/
3533
int comment_print(const char *zText, int indent, int lineLength){
3634
int tlen = lineLength - indent;
3735
int si, sk, i, k;
3836
int doIndent = 0;
39
- char zBuf[400];
37
+ char *zBuf;
38
+ char zBuffer[400];
4039
int lineCnt = 0;
4140
41
+ if( tlen<=0 ){
42
+ tlen = strlen(zText);
43
+ }
44
+ if( tlen >= (sizeof(zBuffer)) ){
45
+ zBuf = fossil_malloc(tlen+1);
46
+ }else{
47
+ zBuf = zBuffer;
48
+ }
4249
for(;;){
4350
while( fossil_isspace(zText[0]) ){ zText++; }
4451
if( zText[0]==0 ){
4552
if( doIndent==0 ){
4653
fossil_print("\n");
4754
lineCnt = 1;
4855
}
56
+ if( zBuf!=zBuffer) fossil_free(zBuf);
4957
return lineCnt;
5058
}
5159
for(sk=si=i=k=0; zText[i] && k<tlen; i++){
5260
char c = zText[i];
5361
if( fossil_isspace(c) ){
@@ -69,19 +77,16 @@
6977
fossil_print("%*s", indent, "");
7078
}
7179
doIndent = 1;
7280
if( sk>0 && zText[i] ){
7381
zText += si;
74
- zBuf[sk++] = '\n';
7582
zBuf[sk] = 0;
76
- fossil_print("%s", zBuf);
7783
}else{
7884
zText += i;
79
- zBuf[k++] = '\n';
8085
zBuf[k] = 0;
81
- fossil_print("%s", zBuf);
8286
}
87
+ fossil_print("%s\n", zBuf);
8388
lineCnt++;
8489
}
8590
}
8691
8792
/*
8893
--- src/comformat.c
+++ src/comformat.c
@@ -26,28 +26,36 @@
26 ** Given a comment string zText, format that string for printing
27 ** on a TTY. Assume that the output cursors is indent spaces from
28 ** the left margin and that a single line can contain no more than
29 ** lineLength characters. Indent all subsequent lines by indent.
30 **
31 ** lineLength must be less than 400.
32 **
33 ** Return the number of newlines that are output.
34 */
35 int comment_print(const char *zText, int indent, int lineLength){
36 int tlen = lineLength - indent;
37 int si, sk, i, k;
38 int doIndent = 0;
39 char zBuf[400];
 
40 int lineCnt = 0;
41
 
 
 
 
 
 
 
 
42 for(;;){
43 while( fossil_isspace(zText[0]) ){ zText++; }
44 if( zText[0]==0 ){
45 if( doIndent==0 ){
46 fossil_print("\n");
47 lineCnt = 1;
48 }
 
49 return lineCnt;
50 }
51 for(sk=si=i=k=0; zText[i] && k<tlen; i++){
52 char c = zText[i];
53 if( fossil_isspace(c) ){
@@ -69,19 +77,16 @@
69 fossil_print("%*s", indent, "");
70 }
71 doIndent = 1;
72 if( sk>0 && zText[i] ){
73 zText += si;
74 zBuf[sk++] = '\n';
75 zBuf[sk] = 0;
76 fossil_print("%s", zBuf);
77 }else{
78 zText += i;
79 zBuf[k++] = '\n';
80 zBuf[k] = 0;
81 fossil_print("%s", zBuf);
82 }
 
83 lineCnt++;
84 }
85 }
86
87 /*
88
--- src/comformat.c
+++ src/comformat.c
@@ -26,28 +26,36 @@
26 ** Given a comment string zText, format that string for printing
27 ** on a TTY. Assume that the output cursors is indent spaces from
28 ** the left margin and that a single line can contain no more than
29 ** lineLength characters. Indent all subsequent lines by indent.
30 **
 
 
31 ** Return the number of newlines that are output.
32 */
33 int comment_print(const char *zText, int indent, int lineLength){
34 int tlen = lineLength - indent;
35 int si, sk, i, k;
36 int doIndent = 0;
37 char *zBuf;
38 char zBuffer[400];
39 int lineCnt = 0;
40
41 if( tlen<=0 ){
42 tlen = strlen(zText);
43 }
44 if( tlen >= (sizeof(zBuffer)) ){
45 zBuf = fossil_malloc(tlen+1);
46 }else{
47 zBuf = zBuffer;
48 }
49 for(;;){
50 while( fossil_isspace(zText[0]) ){ zText++; }
51 if( zText[0]==0 ){
52 if( doIndent==0 ){
53 fossil_print("\n");
54 lineCnt = 1;
55 }
56 if( zBuf!=zBuffer) fossil_free(zBuf);
57 return lineCnt;
58 }
59 for(sk=si=i=k=0; zText[i] && k<tlen; i++){
60 char c = zText[i];
61 if( fossil_isspace(c) ){
@@ -69,19 +77,16 @@
77 fossil_print("%*s", indent, "");
78 }
79 doIndent = 1;
80 if( sk>0 && zText[i] ){
81 zText += si;
 
82 zBuf[sk] = 0;
 
83 }else{
84 zText += i;
 
85 zBuf[k] = 0;
 
86 }
87 fossil_print("%s\n", zBuf);
88 lineCnt++;
89 }
90 }
91
92 /*
93
+6 -1
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
2424
#define _LARGE_FILE 1
2525
#ifndef _FILE_OFFSET_BITS
2626
# define _FILE_OFFSET_BITS 64
2727
#endif
2828
#define _LARGEFILE_SOURCE 1
29
+
30
+/* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */
31
+#if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T)
32
+# define _USE_32BIT_TIME_T
33
+#endif
2934
3035
#ifdef HAVE_AUTOCONFIG_H
3136
#include "autoconfig.h"
3237
#endif
3338
@@ -82,11 +87,11 @@
8287
# else
8388
# define COMPILER_NAME "unknown"
8489
# endif
8590
#endif
8691
87
-#ifndef _RC_COMPILE_
92
+#if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION)
8893
8994
#include "sqlite3.h"
9095
9196
/*
9297
** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
9398
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
 
 
 
 
 
29
30 #ifdef HAVE_AUTOCONFIG_H
31 #include "autoconfig.h"
32 #endif
33
@@ -82,11 +87,11 @@
82 # else
83 # define COMPILER_NAME "unknown"
84 # endif
85 #endif
86
87 #ifndef _RC_COMPILE_
88
89 #include "sqlite3.h"
90
91 /*
92 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
93
--- src/config.h
+++ src/config.h
@@ -24,10 +24,15 @@
24 #define _LARGE_FILE 1
25 #ifndef _FILE_OFFSET_BITS
26 # define _FILE_OFFSET_BITS 64
27 #endif
28 #define _LARGEFILE_SOURCE 1
29
30 /* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */
31 #if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T)
32 # define _USE_32BIT_TIME_T
33 #endif
34
35 #ifdef HAVE_AUTOCONFIG_H
36 #include "autoconfig.h"
37 #endif
38
@@ -82,11 +87,11 @@
87 # else
88 # define COMPILER_NAME "unknown"
89 # endif
90 #endif
91
92 #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION)
93
94 #include "sqlite3.h"
95
96 /*
97 ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257.
98
+11 -3
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
4141
#define CONFIGSET_ALL 0x0000ff /* Everything */
4242
4343
#define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
4444
#define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
4545
46
+/*
47
+** This mask is used for the common TH1 configuration settings (i.e. those
48
+** that are not specific to one particular subsystem, such as the transfer
49
+** subsystem).
50
+*/
51
+#define CONFIGSET_TH1 (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER)
52
+
4653
#endif /* INTERFACE */
4754
4855
/*
4956
** Names of the configuration sets
5057
*/
@@ -90,18 +97,19 @@
9097
{ "timeline-max-comment", CONFIGSET_SKIN },
9198
{ "timeline-plaintext", CONFIGSET_SKIN },
9299
{ "adunit", CONFIGSET_SKIN },
93100
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
94101
{ "adunit-omit-if-user", CONFIGSET_SKIN },
95
- { "th1-setup", CONFIGSET_ALL },
102
+ { "th1-setup", CONFIGSET_TH1 },
96103
97104
#ifdef FOSSIL_ENABLE_TCL
98
- { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99
- { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
105
+ { "tcl", CONFIGSET_TH1 },
106
+ { "tcl-setup", CONFIGSET_TH1 },
100107
#endif
101108
102109
{ "project-name", CONFIGSET_PROJ },
110
+ { "short-project-name", CONFIGSET_PROJ },
103111
{ "project-description", CONFIGSET_PROJ },
104112
{ "manifest", CONFIGSET_PROJ },
105113
{ "binary-glob", CONFIGSET_PROJ },
106114
{ "ignore-glob", CONFIGSET_PROJ },
107115
{ "keep-glob", CONFIGSET_PROJ },
108116
109117
ADDED src/cygsup.h
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
41 #define CONFIGSET_ALL 0x0000ff /* Everything */
42
43 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
44 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
45
 
 
 
 
 
 
 
46 #endif /* INTERFACE */
47
48 /*
49 ** Names of the configuration sets
50 */
@@ -90,18 +97,19 @@
90 { "timeline-max-comment", CONFIGSET_SKIN },
91 { "timeline-plaintext", CONFIGSET_SKIN },
92 { "adunit", CONFIGSET_SKIN },
93 { "adunit-omit-if-admin", CONFIGSET_SKIN },
94 { "adunit-omit-if-user", CONFIGSET_SKIN },
95 { "th1-setup", CONFIGSET_ALL },
96
97 #ifdef FOSSIL_ENABLE_TCL
98 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99 { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
100 #endif
101
102 { "project-name", CONFIGSET_PROJ },
 
103 { "project-description", CONFIGSET_PROJ },
104 { "manifest", CONFIGSET_PROJ },
105 { "binary-glob", CONFIGSET_PROJ },
106 { "ignore-glob", CONFIGSET_PROJ },
107 { "keep-glob", CONFIGSET_PROJ },
108
109 DDED src/cygsup.h
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
41 #define CONFIGSET_ALL 0x0000ff /* Everything */
42
43 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
44 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
45
46 /*
47 ** This mask is used for the common TH1 configuration settings (i.e. those
48 ** that are not specific to one particular subsystem, such as the transfer
49 ** subsystem).
50 */
51 #define CONFIGSET_TH1 (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER)
52
53 #endif /* INTERFACE */
54
55 /*
56 ** Names of the configuration sets
57 */
@@ -90,18 +97,19 @@
97 { "timeline-max-comment", CONFIGSET_SKIN },
98 { "timeline-plaintext", CONFIGSET_SKIN },
99 { "adunit", CONFIGSET_SKIN },
100 { "adunit-omit-if-admin", CONFIGSET_SKIN },
101 { "adunit-omit-if-user", CONFIGSET_SKIN },
102 { "th1-setup", CONFIGSET_TH1 },
103
104 #ifdef FOSSIL_ENABLE_TCL
105 { "tcl", CONFIGSET_TH1 },
106 { "tcl-setup", CONFIGSET_TH1 },
107 #endif
108
109 { "project-name", CONFIGSET_PROJ },
110 { "short-project-name", CONFIGSET_PROJ },
111 { "project-description", CONFIGSET_PROJ },
112 { "manifest", CONFIGSET_PROJ },
113 { "binary-glob", CONFIGSET_PROJ },
114 { "ignore-glob", CONFIGSET_PROJ },
115 { "keep-glob", CONFIGSET_PROJ },
116
117 DDED src/cygsup.h
+11 -3
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
4141
#define CONFIGSET_ALL 0x0000ff /* Everything */
4242
4343
#define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
4444
#define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
4545
46
+/*
47
+** This mask is used for the common TH1 configuration settings (i.e. those
48
+** that are not specific to one particular subsystem, such as the transfer
49
+** subsystem).
50
+*/
51
+#define CONFIGSET_TH1 (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER)
52
+
4653
#endif /* INTERFACE */
4754
4855
/*
4956
** Names of the configuration sets
5057
*/
@@ -90,18 +97,19 @@
9097
{ "timeline-max-comment", CONFIGSET_SKIN },
9198
{ "timeline-plaintext", CONFIGSET_SKIN },
9299
{ "adunit", CONFIGSET_SKIN },
93100
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
94101
{ "adunit-omit-if-user", CONFIGSET_SKIN },
95
- { "th1-setup", CONFIGSET_ALL },
102
+ { "th1-setup", CONFIGSET_TH1 },
96103
97104
#ifdef FOSSIL_ENABLE_TCL
98
- { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99
- { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
105
+ { "tcl", CONFIGSET_TH1 },
106
+ { "tcl-setup", CONFIGSET_TH1 },
100107
#endif
101108
102109
{ "project-name", CONFIGSET_PROJ },
110
+ { "short-project-name", CONFIGSET_PROJ },
103111
{ "project-description", CONFIGSET_PROJ },
104112
{ "manifest", CONFIGSET_PROJ },
105113
{ "binary-glob", CONFIGSET_PROJ },
106114
{ "ignore-glob", CONFIGSET_PROJ },
107115
{ "keep-glob", CONFIGSET_PROJ },
108116
109117
ADDED src/cygsup.h
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
41 #define CONFIGSET_ALL 0x0000ff /* Everything */
42
43 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
44 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
45
 
 
 
 
 
 
 
46 #endif /* INTERFACE */
47
48 /*
49 ** Names of the configuration sets
50 */
@@ -90,18 +97,19 @@
90 { "timeline-max-comment", CONFIGSET_SKIN },
91 { "timeline-plaintext", CONFIGSET_SKIN },
92 { "adunit", CONFIGSET_SKIN },
93 { "adunit-omit-if-admin", CONFIGSET_SKIN },
94 { "adunit-omit-if-user", CONFIGSET_SKIN },
95 { "th1-setup", CONFIGSET_ALL },
96
97 #ifdef FOSSIL_ENABLE_TCL
98 { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
99 { "tcl-setup", CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
100 #endif
101
102 { "project-name", CONFIGSET_PROJ },
 
103 { "project-description", CONFIGSET_PROJ },
104 { "manifest", CONFIGSET_PROJ },
105 { "binary-glob", CONFIGSET_PROJ },
106 { "ignore-glob", CONFIGSET_PROJ },
107 { "keep-glob", CONFIGSET_PROJ },
108
109 DDED src/cygsup.h
--- src/configure.c
+++ src/configure.c
@@ -41,10 +41,17 @@
41 #define CONFIGSET_ALL 0x0000ff /* Everything */
42
43 #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */
44 #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */
45
46 /*
47 ** This mask is used for the common TH1 configuration settings (i.e. those
48 ** that are not specific to one particular subsystem, such as the transfer
49 ** subsystem).
50 */
51 #define CONFIGSET_TH1 (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER)
52
53 #endif /* INTERFACE */
54
55 /*
56 ** Names of the configuration sets
57 */
@@ -90,18 +97,19 @@
97 { "timeline-max-comment", CONFIGSET_SKIN },
98 { "timeline-plaintext", CONFIGSET_SKIN },
99 { "adunit", CONFIGSET_SKIN },
100 { "adunit-omit-if-admin", CONFIGSET_SKIN },
101 { "adunit-omit-if-user", CONFIGSET_SKIN },
102 { "th1-setup", CONFIGSET_TH1 },
103
104 #ifdef FOSSIL_ENABLE_TCL
105 { "tcl", CONFIGSET_TH1 },
106 { "tcl-setup", CONFIGSET_TH1 },
107 #endif
108
109 { "project-name", CONFIGSET_PROJ },
110 { "short-project-name", CONFIGSET_PROJ },
111 { "project-description", CONFIGSET_PROJ },
112 { "manifest", CONFIGSET_PROJ },
113 { "binary-glob", CONFIGSET_PROJ },
114 { "ignore-glob", CONFIGSET_PROJ },
115 { "keep-glob", CONFIGSET_PROJ },
116
117 DDED src/cygsup.h
+124
--- a/src/cygsup.h
+++ b/src/cygsup.h
@@ -0,0 +1,124 @@
1
+/*
2
+** Copyright (c) 2007 D. Richard Hipp
3
+**
4
+** This program is free software; you can redistribute it and/or
5
+** modify it under the terms of the Simplified BSD License (also
6
+** known as the "2-Clause License" or "FreeBSD License".)
7
+
8
+** This program is distributed in the hope that it will be useful,
9
+** but without any warranty; without even the implied warranty of
10
+** merchantability or fitness for a particular purpose.
11
+**
12
+** Author contact information:
13
+** [email protected]
14
+** http://www.hwaci.com/drh/
15
+**
16
+*******************************************************************************
17
+**
18
+** This file contains preprocessor directives used to help integrate with the
19
+** Cygwin runtime and build environment. The intent of this file is to keep
20
+** the Cygwin-specific preprocessor directives together.
21
+*/
22
+
23
+#if defined(__CYGWIN__) && !defined(CYGSUP_H)
24
+#define CYGSUP_H
25
+
26
+/*
27
+*******************************************************************************
28
+** Include any Cygwin-specific headers here. **
29
+*******************************************************************************
30
+*/
31
+
32
+#include <wchar.h>
33
+#include <sys/cygwin.h>
34
+
35
+/*
36
+*******************************************************************************
37
+** Define any Cygwin-specific preprocessor macros here. All macros defined in
38
+** this section should be wrapped with #ifndef, in order to allow them to be
39
+** externally overridden.
40
+*******************************************************************************
41
+*/
42
+
43
+#ifndef CP_UTF8
44
+# define CP_UTF8 65001
45
+#endif
46
+
47
+#ifndef WINBASEAPI
48
+# define WINBASEAPI __declspec(dllimport)
49
+#endif
50
+
51
+#ifndef WINADVAPI
52
+# define WINADVAPI __declspec(dllimport)
53
+#endif
54
+
55
+#ifndef SHSTDAPI
56
+# define SHSTDAPI __declspec(dllimport)
57
+#endif
58
+
59
+#ifndef STDAPI
60
+# define STDAPI __stdcall
61
+#endif
62
+
63
+#ifndef WINAPI
64
+# define WINAPI __stdcall
65
+#endif
66
+
67
+/*
68
+*******************************************************************************
69
+** Declare any Cygwin-specific Win32 or other APIs here. Functions declared in
70
+** this section should use the built-in ANSI C types in order to make sure this
71
+** header file continues to work as a self-contained unit.
72
+**
73
+** On Cygwin64, "long" is 64-bit but in Win64 it's 32-bit. That's why in the
74
+** signatures below "long" should not be used. They now use "int" instead.
75
+*******************************************************************************
76
+*/
77
+
78
+WINADVAPI extern WINAPI int RegOpenKeyExW(
79
+ void *, /* HKEY */
80
+ const wchar_t *, /* LPCWSTR */
81
+ unsigned int, /* DWORD */
82
+ unsigned int, /* REGSAM */
83
+ void * /* PHKEY */
84
+ );
85
+
86
+WINADVAPI extern WINAPI int RegQueryValueExW(
87
+ void *, /* HKEY */
88
+ const wchar_t *, /* LPCWSTR */
89
+ unsigned int *, /* LPDWORD */
90
+ unsigned int *, /* LPDWORD */
91
+ unsigned char *, /* LPBYTE */
92
+ unsigned int * /* LPDWORD */
93
+ );
94
+
95
+SHSTDAPI extern STDAPI void *ShellExecuteW(
96
+ void *, /* HWND */
97
+ const wchar_t *, /* LPCWSTR */
98
+ const wchar_t *, /* LPCWSTR */
99
+ const wchar_t *, /* LPCWSTR */
100
+ const wchar_t *, /* LPCWSTR */
101
+ int /* INT */
102
+ );
103
+
104
+WINBASEAPI extern WINAPI int WideCharToMultiByte(
105
+ unsigned int, /* UINT */
106
+ unsigned int, /* DWORD */
107
+ const wchar_t *, /* LPCWSTR */
108
+ int, /* int */
109
+ char *, /* LPSTR */
110
+ int, /* int */
111
+ const char *, /* LPCSTR */
112
+ int * /* LPBOOL */
113
+ );
114
+
115
+WINBASEAPI extern WINAPI int MultiByteToWideChar(
116
+ unsigned int, /* UINT */
117
+ unsigned int, /* DWORD */
118
+ const char *, /* LPCSTR */
119
+ int, /* int */
120
+ wchar_t *, /* LPWSTR */
121
+ int /* int */
122
+ );
123
+
124
+#endif /* defined(__CYGWIN__) && !defined(CYGSUP_H) */
--- a/src/cygsup.h
+++ b/src/cygsup.h
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/cygsup.h
+++ b/src/cygsup.h
@@ -0,0 +1,124 @@
1 /*
2 ** Copyright (c) 2007 D. Richard Hipp
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 **
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains preprocessor directives used to help integrate with the
19 ** Cygwin runtime and build environment. The intent of this file is to keep
20 ** the Cygwin-specific preprocessor directives together.
21 */
22
23 #if defined(__CYGWIN__) && !defined(CYGSUP_H)
24 #define CYGSUP_H
25
26 /*
27 *******************************************************************************
28 ** Include any Cygwin-specific headers here. **
29 *******************************************************************************
30 */
31
32 #include <wchar.h>
33 #include <sys/cygwin.h>
34
35 /*
36 *******************************************************************************
37 ** Define any Cygwin-specific preprocessor macros here. All macros defined in
38 ** this section should be wrapped with #ifndef, in order to allow them to be
39 ** externally overridden.
40 *******************************************************************************
41 */
42
43 #ifndef CP_UTF8
44 # define CP_UTF8 65001
45 #endif
46
47 #ifndef WINBASEAPI
48 # define WINBASEAPI __declspec(dllimport)
49 #endif
50
51 #ifndef WINADVAPI
52 # define WINADVAPI __declspec(dllimport)
53 #endif
54
55 #ifndef SHSTDAPI
56 # define SHSTDAPI __declspec(dllimport)
57 #endif
58
59 #ifndef STDAPI
60 # define STDAPI __stdcall
61 #endif
62
63 #ifndef WINAPI
64 # define WINAPI __stdcall
65 #endif
66
67 /*
68 *******************************************************************************
69 ** Declare any Cygwin-specific Win32 or other APIs here. Functions declared in
70 ** this section should use the built-in ANSI C types in order to make sure this
71 ** header file continues to work as a self-contained unit.
72 **
73 ** On Cygwin64, "long" is 64-bit but in Win64 it's 32-bit. That's why in the
74 ** signatures below "long" should not be used. They now use "int" instead.
75 *******************************************************************************
76 */
77
78 WINADVAPI extern WINAPI int RegOpenKeyExW(
79 void *, /* HKEY */
80 const wchar_t *, /* LPCWSTR */
81 unsigned int, /* DWORD */
82 unsigned int, /* REGSAM */
83 void * /* PHKEY */
84 );
85
86 WINADVAPI extern WINAPI int RegQueryValueExW(
87 void *, /* HKEY */
88 const wchar_t *, /* LPCWSTR */
89 unsigned int *, /* LPDWORD */
90 unsigned int *, /* LPDWORD */
91 unsigned char *, /* LPBYTE */
92 unsigned int * /* LPDWORD */
93 );
94
95 SHSTDAPI extern STDAPI void *ShellExecuteW(
96 void *, /* HWND */
97 const wchar_t *, /* LPCWSTR */
98 const wchar_t *, /* LPCWSTR */
99 const wchar_t *, /* LPCWSTR */
100 const wchar_t *, /* LPCWSTR */
101 int /* INT */
102 );
103
104 WINBASEAPI extern WINAPI int WideCharToMultiByte(
105 unsigned int, /* UINT */
106 unsigned int, /* DWORD */
107 const wchar_t *, /* LPCWSTR */
108 int, /* int */
109 char *, /* LPSTR */
110 int, /* int */
111 const char *, /* LPCSTR */
112 int * /* LPBOOL */
113 );
114
115 WINBASEAPI extern WINAPI int MultiByteToWideChar(
116 unsigned int, /* UINT */
117 unsigned int, /* DWORD */
118 const char *, /* LPCSTR */
119 int, /* int */
120 wchar_t *, /* LPWSTR */
121 int /* int */
122 );
123
124 #endif /* defined(__CYGWIN__) && !defined(CYGSUP_H) */
--- src/delta.c
+++ src/delta.c
@@ -20,10 +20,11 @@
2020
** Though developed specifically for fossil, the code in this file
2121
** is generally applicable and is thus easily separated from the
2222
** fossil source code base. Nothing in this file depends on anything
2323
** else in fossil.
2424
*/
25
+#include "config.h"
2526
#include <stdio.h>
2627
#include <assert.h>
2728
#include <stdlib.h>
2829
#include <string.h>
2930
#include "delta.h"
3031
--- src/delta.c
+++ src/delta.c
@@ -20,10 +20,11 @@
20 ** Though developed specifically for fossil, the code in this file
21 ** is generally applicable and is thus easily separated from the
22 ** fossil source code base. Nothing in this file depends on anything
23 ** else in fossil.
24 */
 
25 #include <stdio.h>
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "delta.h"
30
--- src/delta.c
+++ src/delta.c
@@ -20,10 +20,11 @@
20 ** Though developed specifically for fossil, the code in this file
21 ** is generally applicable and is thus easily separated from the
22 ** fossil source code base. Nothing in this file depends on anything
23 ** else in fossil.
24 */
25 #include "config.h"
26 #include <stdio.h>
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "delta.h"
31
--- src/descendants.c
+++ src/descendants.c
@@ -329,11 +329,11 @@
329329
"%s"
330330
" AND event.objid IN (SELECT rid FROM leaves)"
331331
" ORDER BY event.mtime DESC",
332332
timeline_query_for_tty()
333333
);
334
- print_timeline(&q, 20, 0);
334
+ print_timeline(&q, -20, 79, 0);
335335
db_finalize(&q);
336336
}
337337
338338
/*
339339
** COMMAND: leaves*
340340
--- src/descendants.c
+++ src/descendants.c
@@ -329,11 +329,11 @@
329 "%s"
330 " AND event.objid IN (SELECT rid FROM leaves)"
331 " ORDER BY event.mtime DESC",
332 timeline_query_for_tty()
333 );
334 print_timeline(&q, 20, 0);
335 db_finalize(&q);
336 }
337
338 /*
339 ** COMMAND: leaves*
340
--- src/descendants.c
+++ src/descendants.c
@@ -329,11 +329,11 @@
329 "%s"
330 " AND event.objid IN (SELECT rid FROM leaves)"
331 " ORDER BY event.mtime DESC",
332 timeline_query_for_tty()
333 );
334 print_timeline(&q, -20, 79, 0);
335 db_finalize(&q);
336 }
337
338 /*
339 ** COMMAND: leaves*
340
+27 -11
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
19391939
struct AnnVers {
19401940
const char *zFUuid; /* File being analyzed */
19411941
const char *zMUuid; /* Check-in containing the file */
19421942
const char *zDate; /* Date of the check-in */
19431943
const char *zBgColor; /* Suggested background color */
1944
+ const char *zUser; /* Name of user who did the check-in */
19441945
unsigned cnt; /* Number of lines contributed by this check-in */
19451946
} *aVers; /* For each check-in analyzed */
19461947
char **azVers; /* Names of versions analyzed */
19471948
};
19481949
@@ -2061,10 +2062,11 @@
20612062
db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
20622063
db_prepare(&q,
20632064
"SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
20642065
" (SELECT uuid FROM blob WHERE rid=mlink.mid),"
20652066
" date(event.mtime),"
2067
+ " coalesce(event.euser,event.user),"
20662068
" mlink.pid"
20672069
" FROM mlink, event"
20682070
" WHERE mlink.fid=:rid"
20692071
" AND event.objid=mlink.mid"
20702072
" AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
20742076
);
20752077
20762078
db_bind_int(&q, ":rid", rid);
20772079
if( iLimit==0 ) iLimit = 1000000000;
20782080
while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2079
- int prevId = db_column_int(&q, 3);
2081
+ int prevId = db_column_int(&q, 4);
20802082
p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
20812083
p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
20822084
p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
20832085
p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2086
+ p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
20842087
if( p->nVers ){
20852088
content_get(rid, &step);
20862089
annotation_step(p, &step, p->nVers-1);
20872090
blob_reset(&step);
20882091
}
@@ -2268,15 +2271,18 @@
22682271
style_footer();
22692272
}
22702273
22712274
/*
22722275
** COMMAND: annotate
2276
+** COMMAND: blame
22732277
**
2274
-** %fossil annotate ?OPTIONS? FILENAME
2278
+** %fossil (annotate|blame) ?OPTIONS? FILENAME
22752279
**
22762280
** Output the text of a file with markings to show when each line of
2277
-** the file was last modified.
2281
+** the file was last modified. The "annotate" command shows line numbers
2282
+** and omits the username. The "blame" command shows the user who made each
2283
+** checkin and omits the line number.
22782284
**
22792285
** Options:
22802286
** --filevers Show file version numbers rather than check-in versions
22812287
** -l|--log List all versions analyzed
22822288
** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
22952301
const char *zLimit; /* The value to the -n|--limit option */
22962302
int iLimit; /* How far back in time to look */
22972303
int showLog; /* True to show the log */
22982304
int fileVers; /* Show file version instead of check-in versions */
22992305
int annFlags = 0; /* Flags to control annotation properties */
2306
+ int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
23002307
2308
+ bBlame = g.argv[1][0]=='b';
23012309
zLimit = find_option("limit","n",1);
23022310
if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
23032311
iLimit = atoi(zLimit);
23042312
showLog = find_option("log","l",0)!=0;
23052313
fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
23422350
}
23432351
for(i=0; i<ann.nOrig; i++){
23442352
int iVers = ann.aOrig[i].iVers;
23452353
char *z = (char*)ann.aOrig[i].z;
23462354
int n = ann.aOrig[i].n;
2347
- char zPrefix[200];
2348
- z[n] = 0;
2355
+ struct AnnVers *p;
23492356
if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2350
- if( iVers>=0 ){
2351
- struct AnnVers *p = ann.aVers+iVers;
2352
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%.10s %s",
2353
- fileVers ? p->zFUuid : p->zMUuid, p->zDate);
2357
+ p = ann.aVers + iVers;
2358
+ if( bBlame ){
2359
+ if( iVers>=0 ){
2360
+ fossil_print("%.10s %s %13.13s: %.*s\n",
2361
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2362
+ }else{
2363
+ fossil_print("%35s %.*s\n", "", n, z);
2364
+ }
23542365
}else{
2355
- zPrefix[0] = 0;
2366
+ if( iVers>=0 ){
2367
+ fossil_print("%.10s %s %5d: %.*s\n",
2368
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2369
+ }else{
2370
+ fossil_print("%21s %5d: %.*s\n",
2371
+ "", i+1, n, z);
2372
+ }
23562373
}
2357
- fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
23582374
}
23592375
}
23602376
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
1939 struct AnnVers {
1940 const char *zFUuid; /* File being analyzed */
1941 const char *zMUuid; /* Check-in containing the file */
1942 const char *zDate; /* Date of the check-in */
1943 const char *zBgColor; /* Suggested background color */
 
1944 unsigned cnt; /* Number of lines contributed by this check-in */
1945 } *aVers; /* For each check-in analyzed */
1946 char **azVers; /* Names of versions analyzed */
1947 };
1948
@@ -2061,10 +2062,11 @@
2061 db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
2062 db_prepare(&q,
2063 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2064 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2065 " date(event.mtime),"
 
2066 " mlink.pid"
2067 " FROM mlink, event"
2068 " WHERE mlink.fid=:rid"
2069 " AND event.objid=mlink.mid"
2070 " AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
2074 );
2075
2076 db_bind_int(&q, ":rid", rid);
2077 if( iLimit==0 ) iLimit = 1000000000;
2078 while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2079 int prevId = db_column_int(&q, 3);
2080 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2081 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2082 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2083 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
 
2084 if( p->nVers ){
2085 content_get(rid, &step);
2086 annotation_step(p, &step, p->nVers-1);
2087 blob_reset(&step);
2088 }
@@ -2268,15 +2271,18 @@
2268 style_footer();
2269 }
2270
2271 /*
2272 ** COMMAND: annotate
 
2273 **
2274 ** %fossil annotate ?OPTIONS? FILENAME
2275 **
2276 ** Output the text of a file with markings to show when each line of
2277 ** the file was last modified.
 
 
2278 **
2279 ** Options:
2280 ** --filevers Show file version numbers rather than check-in versions
2281 ** -l|--log List all versions analyzed
2282 ** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
2295 const char *zLimit; /* The value to the -n|--limit option */
2296 int iLimit; /* How far back in time to look */
2297 int showLog; /* True to show the log */
2298 int fileVers; /* Show file version instead of check-in versions */
2299 int annFlags = 0; /* Flags to control annotation properties */
 
2300
 
2301 zLimit = find_option("limit","n",1);
2302 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2303 iLimit = atoi(zLimit);
2304 showLog = find_option("log","l",0)!=0;
2305 fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
2342 }
2343 for(i=0; i<ann.nOrig; i++){
2344 int iVers = ann.aOrig[i].iVers;
2345 char *z = (char*)ann.aOrig[i].z;
2346 int n = ann.aOrig[i].n;
2347 char zPrefix[200];
2348 z[n] = 0;
2349 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2350 if( iVers>=0 ){
2351 struct AnnVers *p = ann.aVers+iVers;
2352 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%.10s %s",
2353 fileVers ? p->zFUuid : p->zMUuid, p->zDate);
 
 
 
 
2354 }else{
2355 zPrefix[0] = 0;
 
 
 
 
 
 
2356 }
2357 fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
2358 }
2359 }
2360
--- src/diff.c
+++ src/diff.c
@@ -1939,10 +1939,11 @@
1939 struct AnnVers {
1940 const char *zFUuid; /* File being analyzed */
1941 const char *zMUuid; /* Check-in containing the file */
1942 const char *zDate; /* Date of the check-in */
1943 const char *zBgColor; /* Suggested background color */
1944 const char *zUser; /* Name of user who did the check-in */
1945 unsigned cnt; /* Number of lines contributed by this check-in */
1946 } *aVers; /* For each check-in analyzed */
1947 char **azVers; /* Names of versions analyzed */
1948 };
1949
@@ -2061,10 +2062,11 @@
2062 db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
2063 db_prepare(&q,
2064 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2065 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2066 " date(event.mtime),"
2067 " coalesce(event.euser,event.user),"
2068 " mlink.pid"
2069 " FROM mlink, event"
2070 " WHERE mlink.fid=:rid"
2071 " AND event.objid=mlink.mid"
2072 " AND mlink.pid NOT IN vseen"
@@ -2074,15 +2076,16 @@
2076 );
2077
2078 db_bind_int(&q, ":rid", rid);
2079 if( iLimit==0 ) iLimit = 1000000000;
2080 while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
2081 int prevId = db_column_int(&q, 4);
2082 p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
2083 p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
2084 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2085 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2086 p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
2087 if( p->nVers ){
2088 content_get(rid, &step);
2089 annotation_step(p, &step, p->nVers-1);
2090 blob_reset(&step);
2091 }
@@ -2268,15 +2271,18 @@
2271 style_footer();
2272 }
2273
2274 /*
2275 ** COMMAND: annotate
2276 ** COMMAND: blame
2277 **
2278 ** %fossil (annotate|blame) ?OPTIONS? FILENAME
2279 **
2280 ** Output the text of a file with markings to show when each line of
2281 ** the file was last modified. The "annotate" command shows line numbers
2282 ** and omits the username. The "blame" command shows the user who made each
2283 ** checkin and omits the line number.
2284 **
2285 ** Options:
2286 ** --filevers Show file version numbers rather than check-in versions
2287 ** -l|--log List all versions analyzed
2288 ** -n|--limit N Only look backwards in time by N versions
@@ -2295,11 +2301,13 @@
2301 const char *zLimit; /* The value to the -n|--limit option */
2302 int iLimit; /* How far back in time to look */
2303 int showLog; /* True to show the log */
2304 int fileVers; /* Show file version instead of check-in versions */
2305 int annFlags = 0; /* Flags to control annotation properties */
2306 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2307
2308 bBlame = g.argv[1][0]=='b';
2309 zLimit = find_option("limit","n",1);
2310 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2311 iLimit = atoi(zLimit);
2312 showLog = find_option("log","l",0)!=0;
2313 fileVers = find_option("filevers",0,0)!=0;
@@ -2342,18 +2350,26 @@
2350 }
2351 for(i=0; i<ann.nOrig; i++){
2352 int iVers = ann.aOrig[i].iVers;
2353 char *z = (char*)ann.aOrig[i].z;
2354 int n = ann.aOrig[i].n;
2355 struct AnnVers *p;
 
2356 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2357 p = ann.aVers + iVers;
2358 if( bBlame ){
2359 if( iVers>=0 ){
2360 fossil_print("%.10s %s %13.13s: %.*s\n",
2361 fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2362 }else{
2363 fossil_print("%35s %.*s\n", "", n, z);
2364 }
2365 }else{
2366 if( iVers>=0 ){
2367 fossil_print("%.10s %s %5d: %.*s\n",
2368 fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2369 }else{
2370 fossil_print("%21s %5d: %.*s\n",
2371 "", i+1, n, z);
2372 }
2373 }
 
2374 }
2375 }
2376
+20 -6
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915915
** (3) Delete the temp file.
916916
*/
917917
void diff_tk(const char *zSubCmd, int firstArg){
918918
int i;
919919
Blob script;
920
- char *zTempFile;
920
+ char *zTempFile = 0;
921921
char *zCmd;
922922
blob_zero(&script);
923923
blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924924
g.nameOfExe, zSubCmd);
925925
for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926926
const char *z = g.argv[i];
927927
if( z[0]=='-' ){
928928
if( strglob("*-html",z) ) continue;
929929
if( strglob("*-y",z) ) continue;
930930
if( strglob("*-i",z) ) continue;
931
+ /* The undocumented --script FILENAME option causes the Tk script to
932
+ ** be written into the FILENAME instead of being run. This is used
933
+ ** for testing and debugging. */
934
+ if( strglob("*-script",z) && i<g.argc-1 ){
935
+ i++;
936
+ zTempFile = g.argv[i];
937
+ continue;
938
+ }
931939
}
932940
blob_append(&script, " ", 1);
933941
shell_escape(&script, z);
934942
}
935943
blob_appendf(&script, "}\n%s", zDiffScript);
936
- zTempFile = write_blob_to_temp_file(&script);
937
- zCmd = mprintf("tclsh \"%s\"", zTempFile);
938
- fossil_system(zCmd);
939
- file_delete(zTempFile);
940
- fossil_free(zCmd);
944
+ if( zTempFile ){
945
+ blob_write_to_file(&script, zTempFile);
946
+ fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947
+ }else{
948
+ zTempFile = write_blob_to_temp_file(&script);
949
+ zCmd = mprintf("tclsh \"%s\"", zTempFile);
950
+ fossil_system(zCmd);
951
+ file_delete(zTempFile);
952
+ fossil_free(zCmd);
953
+ }
954
+ blob_reset(&script);
941955
}
942956
943957
/*
944958
** Returns non-zero if files that may be binary should be used with external
945959
** diff programs.
946960
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915 ** (3) Delete the temp file.
916 */
917 void diff_tk(const char *zSubCmd, int firstArg){
918 int i;
919 Blob script;
920 char *zTempFile;
921 char *zCmd;
922 blob_zero(&script);
923 blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924 g.nameOfExe, zSubCmd);
925 for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926 const char *z = g.argv[i];
927 if( z[0]=='-' ){
928 if( strglob("*-html",z) ) continue;
929 if( strglob("*-y",z) ) continue;
930 if( strglob("*-i",z) ) continue;
 
 
 
 
 
 
 
 
931 }
932 blob_append(&script, " ", 1);
933 shell_escape(&script, z);
934 }
935 blob_appendf(&script, "}\n%s", zDiffScript);
936 zTempFile = write_blob_to_temp_file(&script);
937 zCmd = mprintf("tclsh \"%s\"", zTempFile);
938 fossil_system(zCmd);
939 file_delete(zTempFile);
940 fossil_free(zCmd);
 
 
 
 
 
 
941 }
942
943 /*
944 ** Returns non-zero if files that may be binary should be used with external
945 ** diff programs.
946
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -915,11 +915,11 @@
915 ** (3) Delete the temp file.
916 */
917 void diff_tk(const char *zSubCmd, int firstArg){
918 int i;
919 Blob script;
920 char *zTempFile = 0;
921 char *zCmd;
922 blob_zero(&script);
923 blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v",
924 g.nameOfExe, zSubCmd);
925 for(i=firstArg; i<g.argc; i++){
@@ -926,20 +926,34 @@
926 const char *z = g.argv[i];
927 if( z[0]=='-' ){
928 if( strglob("*-html",z) ) continue;
929 if( strglob("*-y",z) ) continue;
930 if( strglob("*-i",z) ) continue;
931 /* The undocumented --script FILENAME option causes the Tk script to
932 ** be written into the FILENAME instead of being run. This is used
933 ** for testing and debugging. */
934 if( strglob("*-script",z) && i<g.argc-1 ){
935 i++;
936 zTempFile = g.argv[i];
937 continue;
938 }
939 }
940 blob_append(&script, " ", 1);
941 shell_escape(&script, z);
942 }
943 blob_appendf(&script, "}\n%s", zDiffScript);
944 if( zTempFile ){
945 blob_write_to_file(&script, zTempFile);
946 fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947 }else{
948 zTempFile = write_blob_to_temp_file(&script);
949 zCmd = mprintf("tclsh \"%s\"", zTempFile);
950 fossil_system(zCmd);
951 file_delete(zTempFile);
952 fossil_free(zCmd);
953 }
954 blob_reset(&script);
955 }
956
957 /*
958 ** Returns non-zero if files that may be binary should be used with external
959 ** diff programs.
960
+1 -1
--- src/doc.c
+++ src/doc.c
@@ -449,11 +449,11 @@
449449
450450
/* Add the vid baseline to the cache */
451451
if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
452452
db_multi_exec("DELETE FROM vcache");
453453
}
454
- pM = manifest_get(vid, CFTYPE_MANIFEST);
454
+ pM = manifest_get(vid, CFTYPE_MANIFEST, 0);
455455
if( pM==0 ){
456456
goto doc_not_found;
457457
}
458458
db_prepare(&s,
459459
"INSERT INTO vcache(vid,fname,rid)"
460460
--- src/doc.c
+++ src/doc.c
@@ -449,11 +449,11 @@
449
450 /* Add the vid baseline to the cache */
451 if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
452 db_multi_exec("DELETE FROM vcache");
453 }
454 pM = manifest_get(vid, CFTYPE_MANIFEST);
455 if( pM==0 ){
456 goto doc_not_found;
457 }
458 db_prepare(&s,
459 "INSERT INTO vcache(vid,fname,rid)"
460
--- src/doc.c
+++ src/doc.c
@@ -449,11 +449,11 @@
449
450 /* Add the vid baseline to the cache */
451 if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
452 db_multi_exec("DELETE FROM vcache");
453 }
454 pM = manifest_get(vid, CFTYPE_MANIFEST, 0);
455 if( pM==0 ){
456 goto doc_not_found;
457 }
458 db_prepare(&s,
459 "INSERT INTO vcache(vid,fname,rid)"
460
+3 -3
--- src/event.c
+++ src/event.c
@@ -21,13 +21,13 @@
2121
** Blog posts
2222
** New articles
2323
** Process checkpoints
2424
** Announcements
2525
*/
26
+#include "config.h"
2627
#include <assert.h>
2728
#include <ctype.h>
28
-#include "config.h"
2929
#include "event.h"
3030
3131
/*
3232
** Output a hyperlink to an event given its tagid.
3333
*/
@@ -113,11 +113,11 @@
113113
}
114114
verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
115115
116116
/* Extract the event content.
117117
*/
118
- pEvent = manifest_get(rid, CFTYPE_EVENT);
118
+ pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
119119
if( pEvent==0 ){
120120
fossil_fatal("Object #%d is not an event", rid);
121121
}
122122
blob_init(&fullbody, pEvent->zWiki, -1);
123123
if( wiki_find_title(&fullbody, &title, &tail) ){
@@ -257,11 +257,11 @@
257257
/* If editing an existing event, extract the key fields to use as
258258
** a starting point for the edit.
259259
*/
260260
if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){
261261
Manifest *pEvent;
262
- pEvent = manifest_get(rid, CFTYPE_EVENT);
262
+ pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
263263
if( pEvent && pEvent->type==CFTYPE_EVENT ){
264264
if( zBody==0 ) zBody = pEvent->zWiki;
265265
if( zETime==0 ){
266266
zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
267267
}
268268
--- src/event.c
+++ src/event.c
@@ -21,13 +21,13 @@
21 ** Blog posts
22 ** New articles
23 ** Process checkpoints
24 ** Announcements
25 */
 
26 #include <assert.h>
27 #include <ctype.h>
28 #include "config.h"
29 #include "event.h"
30
31 /*
32 ** Output a hyperlink to an event given its tagid.
33 */
@@ -113,11 +113,11 @@
113 }
114 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
115
116 /* Extract the event content.
117 */
118 pEvent = manifest_get(rid, CFTYPE_EVENT);
119 if( pEvent==0 ){
120 fossil_fatal("Object #%d is not an event", rid);
121 }
122 blob_init(&fullbody, pEvent->zWiki, -1);
123 if( wiki_find_title(&fullbody, &title, &tail) ){
@@ -257,11 +257,11 @@
257 /* If editing an existing event, extract the key fields to use as
258 ** a starting point for the edit.
259 */
260 if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){
261 Manifest *pEvent;
262 pEvent = manifest_get(rid, CFTYPE_EVENT);
263 if( pEvent && pEvent->type==CFTYPE_EVENT ){
264 if( zBody==0 ) zBody = pEvent->zWiki;
265 if( zETime==0 ){
266 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
267 }
268
--- src/event.c
+++ src/event.c
@@ -21,13 +21,13 @@
21 ** Blog posts
22 ** New articles
23 ** Process checkpoints
24 ** Announcements
25 */
26 #include "config.h"
27 #include <assert.h>
28 #include <ctype.h>
 
29 #include "event.h"
30
31 /*
32 ** Output a hyperlink to an event given its tagid.
33 */
@@ -113,11 +113,11 @@
113 }
114 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
115
116 /* Extract the event content.
117 */
118 pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
119 if( pEvent==0 ){
120 fossil_fatal("Object #%d is not an event", rid);
121 }
122 blob_init(&fullbody, pEvent->zWiki, -1);
123 if( wiki_find_title(&fullbody, &title, &tail) ){
@@ -257,11 +257,11 @@
257 /* If editing an existing event, extract the key fields to use as
258 ** a starting point for the edit.
259 */
260 if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){
261 Manifest *pEvent;
262 pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
263 if( pEvent && pEvent->type==CFTYPE_EVENT ){
264 if( zBody==0 ) zBody = pEvent->zWiki;
265 if( zETime==0 ){
266 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
267 }
268
+10 -3
--- src/finfo.c
+++ src/finfo.c
@@ -43,16 +43,17 @@
4343
** Options:
4444
** -b|--brief display a brief (one line / revision) summary
4545
** --case-sensitive B Enable or disable case-sensitive filenames. B is a
4646
** boolean: "yes", "no", "true", "false", etc.
4747
** -l|--log select log mode (the default)
48
-** -n|--limit N display the first N changes
48
+** -n|--limit N display the first N changes. N=0 means no limit.
4949
** --offset P skip P changes
5050
** -p|--print select print mode
5151
** -r|--revision R print the given revision (or ckout, if none is given)
5252
** to stdout (only in print mode)
5353
** -s|--status select status mode (print a status indicator for FILE)
54
+** -W|--width <num> With of lines (default 79). Must be >22 or 0.
5455
**
5556
** See also: artifact, cat, descendants, info, leaves
5657
*/
5758
void finfo_cmd(void){
5859
capture_case_sensitive_option();
@@ -134,21 +135,27 @@
134135
Stmt q;
135136
Blob fname;
136137
int rid;
137138
const char *zFilename;
138139
const char *zLimit;
140
+ const char *zWidth;
139141
const char *zOffset;
140
- int iLimit, iOffset, iBrief;
142
+ int iLimit, iOffset, iBrief, iWidth;
141143
142144
if( find_option("log","l",0) ){
143145
/* this is the default, no-op */
144146
}
145147
zLimit = find_option("limit","n",1);
148
+ zWidth = find_option("width","W",1);
146149
iLimit = zLimit ? atoi(zLimit) : -1;
150
+ iWidth = zWidth ? atoi(zWidth) : 79;
147151
zOffset = find_option("offset",0,1);
148152
iOffset = zOffset ? atoi(zOffset) : 0;
149153
iBrief = (find_option("brief","b",0) == 0);
154
+ if( (iWidth!=0) && (iWidth<=22) ){
155
+ fossil_fatal("--width|-W value must be >22 or 0");
156
+ }
150157
if( g.argc!=3 ){
151158
usage("?-l|--log? ?-b|--brief? FILENAME");
152159
}
153160
file_tree_name(g.argv[2], &fname, 1);
154161
rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -188,11 +195,11 @@
188195
if( iBrief ){
189196
fossil_print("%s ", zDate);
190197
zOut = sqlite3_mprintf(
191198
"[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)",
192199
zCiUuid, zCom, zUser, zFileUuid, zBr);
193
- comment_print(zOut, 11, 79);
200
+ comment_print(zOut, 11, iWidth);
194201
sqlite3_free(zOut);
195202
}else{
196203
blob_reset(&line);
197204
blob_appendf(&line, "%.10s ", zCiUuid);
198205
blob_appendf(&line, "%.10s ", zDate);
199206
--- src/finfo.c
+++ src/finfo.c
@@ -43,16 +43,17 @@
43 ** Options:
44 ** -b|--brief display a brief (one line / revision) summary
45 ** --case-sensitive B Enable or disable case-sensitive filenames. B is a
46 ** boolean: "yes", "no", "true", "false", etc.
47 ** -l|--log select log mode (the default)
48 ** -n|--limit N display the first N changes
49 ** --offset P skip P changes
50 ** -p|--print select print mode
51 ** -r|--revision R print the given revision (or ckout, if none is given)
52 ** to stdout (only in print mode)
53 ** -s|--status select status mode (print a status indicator for FILE)
 
54 **
55 ** See also: artifact, cat, descendants, info, leaves
56 */
57 void finfo_cmd(void){
58 capture_case_sensitive_option();
@@ -134,21 +135,27 @@
134 Stmt q;
135 Blob fname;
136 int rid;
137 const char *zFilename;
138 const char *zLimit;
 
139 const char *zOffset;
140 int iLimit, iOffset, iBrief;
141
142 if( find_option("log","l",0) ){
143 /* this is the default, no-op */
144 }
145 zLimit = find_option("limit","n",1);
 
146 iLimit = zLimit ? atoi(zLimit) : -1;
 
147 zOffset = find_option("offset",0,1);
148 iOffset = zOffset ? atoi(zOffset) : 0;
149 iBrief = (find_option("brief","b",0) == 0);
 
 
 
150 if( g.argc!=3 ){
151 usage("?-l|--log? ?-b|--brief? FILENAME");
152 }
153 file_tree_name(g.argv[2], &fname, 1);
154 rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -188,11 +195,11 @@
188 if( iBrief ){
189 fossil_print("%s ", zDate);
190 zOut = sqlite3_mprintf(
191 "[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)",
192 zCiUuid, zCom, zUser, zFileUuid, zBr);
193 comment_print(zOut, 11, 79);
194 sqlite3_free(zOut);
195 }else{
196 blob_reset(&line);
197 blob_appendf(&line, "%.10s ", zCiUuid);
198 blob_appendf(&line, "%.10s ", zDate);
199
--- src/finfo.c
+++ src/finfo.c
@@ -43,16 +43,17 @@
43 ** Options:
44 ** -b|--brief display a brief (one line / revision) summary
45 ** --case-sensitive B Enable or disable case-sensitive filenames. B is a
46 ** boolean: "yes", "no", "true", "false", etc.
47 ** -l|--log select log mode (the default)
48 ** -n|--limit N display the first N changes. N=0 means no limit.
49 ** --offset P skip P changes
50 ** -p|--print select print mode
51 ** -r|--revision R print the given revision (or ckout, if none is given)
52 ** to stdout (only in print mode)
53 ** -s|--status select status mode (print a status indicator for FILE)
54 ** -W|--width <num> With of lines (default 79). Must be >22 or 0.
55 **
56 ** See also: artifact, cat, descendants, info, leaves
57 */
58 void finfo_cmd(void){
59 capture_case_sensitive_option();
@@ -134,21 +135,27 @@
135 Stmt q;
136 Blob fname;
137 int rid;
138 const char *zFilename;
139 const char *zLimit;
140 const char *zWidth;
141 const char *zOffset;
142 int iLimit, iOffset, iBrief, iWidth;
143
144 if( find_option("log","l",0) ){
145 /* this is the default, no-op */
146 }
147 zLimit = find_option("limit","n",1);
148 zWidth = find_option("width","W",1);
149 iLimit = zLimit ? atoi(zLimit) : -1;
150 iWidth = zWidth ? atoi(zWidth) : 79;
151 zOffset = find_option("offset",0,1);
152 iOffset = zOffset ? atoi(zOffset) : 0;
153 iBrief = (find_option("brief","b",0) == 0);
154 if( (iWidth!=0) && (iWidth<=22) ){
155 fossil_fatal("--width|-W value must be >22 or 0");
156 }
157 if( g.argc!=3 ){
158 usage("?-l|--log? ?-b|--brief? FILENAME");
159 }
160 file_tree_name(g.argv[2], &fname, 1);
161 rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
@@ -188,11 +195,11 @@
195 if( iBrief ){
196 fossil_print("%s ", zDate);
197 zOut = sqlite3_mprintf(
198 "[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)",
199 zCiUuid, zCom, zUser, zFileUuid, zBr);
200 comment_print(zOut, 11, iWidth);
201 sqlite3_free(zOut);
202 }else{
203 blob_reset(&line);
204 blob_appendf(&line, "%.10s ", zCiUuid);
205 blob_appendf(&line, "%.10s ", zDate);
206
+1 -1
--- src/gzip.c
+++ src/gzip.c
@@ -19,13 +19,13 @@
1919
** file. The GZIP format is described in RFC-1952.
2020
**
2121
** State information is stored in static variables, so this implementation
2222
** can only be building up a single GZIP file at a time.
2323
*/
24
+#include "config.h"
2425
#include <assert.h>
2526
#include <zlib.h>
26
-#include "config.h"
2727
#include "gzip.h"
2828
2929
/*
3030
** State information for the GZIP file under construction.
3131
*/
3232
--- src/gzip.c
+++ src/gzip.c
@@ -19,13 +19,13 @@
19 ** file. The GZIP format is described in RFC-1952.
20 **
21 ** State information is stored in static variables, so this implementation
22 ** can only be building up a single GZIP file at a time.
23 */
 
24 #include <assert.h>
25 #include <zlib.h>
26 #include "config.h"
27 #include "gzip.h"
28
29 /*
30 ** State information for the GZIP file under construction.
31 */
32
--- src/gzip.c
+++ src/gzip.c
@@ -19,13 +19,13 @@
19 ** file. The GZIP format is described in RFC-1952.
20 **
21 ** State information is stored in static variables, so this implementation
22 ** can only be building up a single GZIP file at a time.
23 */
24 #include "config.h"
25 #include <assert.h>
26 #include <zlib.h>
 
27 #include "gzip.h"
28
29 /*
30 ** State information for the GZIP file under construction.
31 */
32
+14 -1
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112112
fossil_free(zCredentials);
113113
}
114114
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115115
blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116116
" (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
117
+ if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
117118
if( g.fHttpTrace ){
118119
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119120
}else{
120121
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121122
}
@@ -217,10 +218,20 @@
217218
if( iHttpVersion==0 ){
218219
closeConnection = 1;
219220
}else{
220221
closeConnection = 0;
221222
}
223
+ }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
224
+ if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
225
+ if( rc!=200 && rc!=302 ){
226
+ int ii;
227
+ for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
228
+ while( zLine[ii]==' ' ) ii++;
229
+ fossil_warning("server says: %s", &zLine[ii]);
230
+ goto write_err;
231
+ }
232
+ closeConnection = 0;
222233
}else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
223234
for(i=15; fossil_isspace(zLine[i]); i++){}
224235
iLength = atoi(&zLine[i]);
225236
}else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
226237
char c;
@@ -295,12 +306,14 @@
295306
** Close the connection to the server if appropriate.
296307
**
297308
** FIXME: There is some bug in the lower layers that prevents the
298309
** connection from remaining open. The easiest fix for now is to
299310
** simply close and restart the connection for each round-trip.
311
+ **
312
+ ** For SSH we will leave the connection open.
300313
*/
301
- closeConnection = 1; /* FIX ME */
314
+ if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
302315
if( closeConnection ){
303316
transport_close();
304317
}else{
305318
transport_rewind();
306319
}
307320
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
 
117 if( g.fHttpTrace ){
118 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
119 }else{
120 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
121 }
@@ -217,10 +218,20 @@
217 if( iHttpVersion==0 ){
218 closeConnection = 1;
219 }else{
220 closeConnection = 0;
221 }
 
 
 
 
 
 
 
 
 
 
222 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
223 for(i=15; fossil_isspace(zLine[i]); i++){}
224 iLength = atoi(&zLine[i]);
225 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
226 char c;
@@ -295,12 +306,14 @@
295 ** Close the connection to the server if appropriate.
296 **
297 ** FIXME: There is some bug in the lower layers that prevents the
298 ** connection from remaining open. The easiest fix for now is to
299 ** simply close and restart the connection for each round-trip.
 
 
300 */
301 closeConnection = 1; /* FIX ME */
302 if( closeConnection ){
303 transport_close();
304 }else{
305 transport_rewind();
306 }
307
--- src/http.c
+++ src/http.c
@@ -112,10 +112,11 @@
112 fossil_free(zCredentials);
113 }
114 blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
115 blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION
116 " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
117 if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
118 if( g.fHttpTrace ){
119 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
120 }else{
121 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
122 }
@@ -217,10 +218,20 @@
218 if( iHttpVersion==0 ){
219 closeConnection = 1;
220 }else{
221 closeConnection = 0;
222 }
223 }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
224 if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
225 if( rc!=200 && rc!=302 ){
226 int ii;
227 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
228 while( zLine[ii]==' ' ) ii++;
229 fossil_warning("server says: %s", &zLine[ii]);
230 goto write_err;
231 }
232 closeConnection = 0;
233 }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
234 for(i=15; fossil_isspace(zLine[i]); i++){}
235 iLength = atoi(&zLine[i]);
236 }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
237 char c;
@@ -295,12 +306,14 @@
306 ** Close the connection to the server if appropriate.
307 **
308 ** FIXME: There is some bug in the lower layers that prevents the
309 ** connection from remaining open. The easiest fix for now is to
310 ** simply close and restart the connection for each round-trip.
311 **
312 ** For SSH we will leave the connection open.
313 */
314 if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
315 if( closeConnection ){
316 transport_close();
317 }else{
318 transport_rewind();
319 }
320
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209209
N -= (size_t)got;
210210
pContent = (void*)&((char*)pContent)[got];
211211
}
212212
return total;
213213
}
214
+
215
+/*
216
+** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
217
+** populated. For hostnames with more than one IP (or if overridden in
218
+** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
219
+*/
220
+void socket_ssh_resolve_addr(void){
221
+ struct hostent *pHost; /* Used to make best effort for rcvfrom */
222
+ struct sockaddr_in addr;
223
+
224
+ memset(&addr, 0, sizeof(addr));
225
+ pHost = gethostbyname(g.urlName);
226
+ if( pHost!=0 ){
227
+ memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
228
+ g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
229
+ }
230
+}
214231
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209 N -= (size_t)got;
210 pContent = (void*)&((char*)pContent)[got];
211 }
212 return total;
213 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
--- src/http_socket.c
+++ src/http_socket.c
@@ -209,5 +209,22 @@
209 N -= (size_t)got;
210 pContent = (void*)&((char*)pContent)[got];
211 }
212 return total;
213 }
214
215 /*
216 ** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
217 ** populated. For hostnames with more than one IP (or if overridden in
218 ** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
219 */
220 void socket_ssh_resolve_addr(void){
221 struct hostent *pHost; /* Used to make best effort for rcvfrom */
222 struct sockaddr_in addr;
223
224 memset(&addr, 0, sizeof(addr));
225 pHost = gethostbyname(g.urlName);
226 if( pHost!=0 ){
227 memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
228 g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
229 }
230 }
231
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
7474
transport.nSent = 0;
7575
transport.nRcvd = 0;
7676
}
7777
}
7878
79
-/*
80
-** Read text from sshIn. Zero-terminate and remove trailing
81
-** whitespace.
82
-*/
83
-static void sshin_read(char *zBuf, int szBuf){
84
- int got;
85
- zBuf[0] = 0;
86
- got = read(sshIn, zBuf, szBuf-1);
87
- while( got>=0 ){
88
- zBuf[got] = 0;
89
- if( got==0 || !fossil_isspace(zBuf[got-1]) ) break;
90
- got--;
91
- }
92
-}
93
-
9479
/*
9580
** Default SSH command
9681
*/
9782
#ifdef __MINGW32__
9883
static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
9984
#else
10085
static char zDefaultSshCmd[] = "ssh -e none -T";
10186
#endif
10287
10388
/*
104
-** Generate a random SSH link problem keyword
105
-*/
106
-static int random_probe(char *zProbe, int nProbe){
107
- unsigned r[4];
108
- sqlite3_randomness(sizeof(r), r);
109
- sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110
- r[0], r[1], r[2], r[3]);
111
- return (int)strlen(zProbe);
112
-}
113
-
114
-/*
115
-** Bring up an SSH link. This involves sending some "echo" commands and
116
-** get back appropriate responses. The point is to move past the MOTD and
117
-** verify that the link is working.
118
-*/
119
-static void transport_ssh_startup(void){
120
- char *zIn; /* An input line received back from remote */
121
- int nWait; /* Number of times waiting for the MOTD */
122
- char zProbe[40]; /* Text of the random probe */
123
- int nProbe; /* Size of probe message */
124
- int nIn; /* Size of input */
125
- static const int nBuf = 10000; /* Size of input buffer */
126
-
127
- zIn = fossil_malloc(nBuf);
128
- nProbe = random_probe(zProbe, sizeof(zProbe));
129
- fprintf(sshOut, "echo %s\n", zProbe);
130
- fflush(sshOut);
131
- if( g.fSshTrace ){
132
- printf("Sent: [echo %s]\n", zProbe);
133
- fflush(stdout);
134
- }
135
- memset(zIn, '*', nProbe);
136
- for(nWait=1; nWait<=10; nWait++){
137
- sshin_read(zIn+nProbe, nBuf-nProbe);
138
- if( g.fSshTrace ){
139
- printf("Got back-----------------------------------------------\n"
140
- "%s\n"
141
- "-------------------------------------------------------\n",
142
- zIn+nProbe);
143
- }
144
- if( strstr(zIn, zProbe) ) break;
145
- sqlite3_sleep(100*nWait);
146
- nIn = (int)strlen(zIn);
147
- memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148
- if( g.fSshTrace ){
149
- printf("Fetching more text. Looking for [%s]...\n", zProbe);
150
- fflush(stdout);
151
- }
152
- }
153
- nProbe = random_probe(zProbe, sizeof(zProbe));
154
- fprintf(sshOut, "echo %s\n", zProbe);
155
- fflush(sshOut);
156
- if( g.fSshTrace ){
157
- printf("Sent: [echo %s]\n", zProbe);
158
- fflush(stdout);
159
- }
160
- sshin_read(zIn, nBuf);
161
- if( zIn[0]==0 ){
162
- sqlite3_sleep(250);
163
- sshin_read(zIn, nBuf);
164
- }
165
- if( g.fSshTrace ){
166
- printf("Got back-----------------------------------------------\n"
167
- "%s\n"
168
- "-------------------------------------------------------\n", zIn);
169
- }
170
- if( memcmp(zIn, zProbe, nProbe)!=0 ){
171
- pclose2(sshIn, sshOut, sshPid);
172
- fossil_fatal("ssh connection failed: [%s]", zIn);
173
- }
174
- fossil_free(zIn);
175
-}
176
-
177
-/*
178
-** Global initialization of the transport layer
179
-*/
180
-void transport_global_startup(void){
181
- if( g.urlIsSsh ){
182
- /* Only SSH requires a global initialization. For SSH we need to create
183
- ** and run an SSH command to talk to the remote machine.
184
- */
185
- const char *zSsh; /* The base SSH command */
186
- Blob zCmd; /* The SSH command */
187
- char *zHost; /* The host name to contact */
188
- int n; /* Size of prefix string */
189
-
190
- zSsh = db_get("ssh-command", zDefaultSshCmd);
191
- blob_init(&zCmd, zSsh, -1);
192
- if( g.urlPort!=g.urlDfltPort ){
193
-#ifdef __MINGW32__
194
- blob_appendf(&zCmd, " -P %d", g.urlPort);
195
-#else
196
- blob_appendf(&zCmd, " -p %d", g.urlPort);
197
-#endif
198
- }
199
- fossil_force_newline();
200
- fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201
- if( g.urlUser && g.urlUser[0] ){
202
- zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203
-#ifdef __MINGW32__
204
- /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205
- if( g.urlPasswd && g.urlPasswd[0] ){
206
- Blob pw;
207
- blob_zero(&pw);
208
- if( g.urlPasswd[0]=='*' ){
209
- char *zPrompt;
210
- zPrompt = mprintf("Password for [%s]: ", zHost);
211
- prompt_for_password(zPrompt, &pw, 0);
212
- free(zPrompt);
213
- }else{
214
- blob_init(&pw, g.urlPasswd, -1);
215
- }
216
- blob_append(&zCmd, " -pw ", -1);
217
- shell_escape(&zCmd, blob_str(&pw));
218
- blob_reset(&pw);
219
- fossil_print(" -pw ********"); /* Do not show the password text */
220
- }
221
-#endif
222
- }else{
223
- zHost = mprintf("%s", g.urlName);
224
- }
225
- n = blob_size(&zCmd);
226
- blob_append(&zCmd, " ", 1);
227
- shell_escape(&zCmd, zHost);
228
- if( g.urlShell ){
229
- blob_appendf(&zCmd, " %s", g.urlShell);
230
- }else{
231
-#if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232
- /* The following works. But only if the fossil on the remote side
233
- ** is recent enough to support the test-ssh-far-side command. That
234
- ** command was added on 2013-02-06. We will leave this turned off
235
- ** until most fossil servers have upgraded to that version or a later
236
- ** version. The sync will still work as long as the shell on the far
237
- ** side is bash and not tcsh. And if the default far side shell is
238
- ** tcsh, then the shell=/bin/bash query parameter can be used as a
239
- ** work-around. Enable this code after about a year...
240
- */
241
- blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242
-#endif
243
- }
244
- fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245
- free(zHost);
246
- popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247
- if( sshPid==0 ){
248
- fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249
- }
250
- blob_reset(&zCmd);
251
- transport_ssh_startup();
252
- }
253
-}
254
-
255
-/*
256
-** COMMAND: test-ssh-far-side
257
-**
258
-** Read lines of input text, one by one, and evaluate each line using
259
-** system(). The ssh: sync protocol uses this on the far side of the
260
-** SSH link.
261
-*/
262
-void test_ssh_far_side_cmd(void){
263
- int i = 0;
264
- int got;
265
- char zLine[5000];
266
- while( i<sizeof(zLine) ){
267
- got = read(0, zLine+i, 1);
268
- if( got==0 ) return;
269
- if( zLine[i]=='\n' ){
270
- zLine[i] = 0;
271
- system(zLine);
272
- i = 0;
273
- }else{
274
- i++;
275
- }
276
- }
89
+** SSH initialization of the transport layer
90
+*/
91
+int transport_ssh_open(void){
92
+ /* For SSH we need to create and run SSH fossil http
93
+ ** to talk to the remote machine.
94
+ */
95
+ const char *zSsh; /* The base SSH command */
96
+ Blob zCmd; /* The SSH command */
97
+ char *zHost; /* The host name to contact */
98
+ int n; /* Size of prefix string */
99
+
100
+ socket_ssh_resolve_addr();
101
+ zSsh = db_get("ssh-command", zDefaultSshCmd);
102
+ blob_init(&zCmd, zSsh, -1);
103
+ if( g.urlPort!=g.urlDfltPort && g.urlPort ){
104
+#ifdef __MINGW32__
105
+ blob_appendf(&zCmd, " -P %d", g.urlPort);
106
+#else
107
+ blob_appendf(&zCmd, " -p %d", g.urlPort);
108
+#endif
109
+ }
110
+ if( g.fSshTrace ){
111
+ fossil_force_newline();
112
+ fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
113
+ }
114
+ if( g.urlUser && g.urlUser[0] ){
115
+ zHost = mprintf("%s@%s", g.urlUser, g.urlName);
116
+ }else{
117
+ zHost = mprintf("%s", g.urlName);
118
+ }
119
+ n = blob_size(&zCmd);
120
+ blob_append(&zCmd, " ", 1);
121
+ shell_escape(&zCmd, zHost);
122
+ blob_append(&zCmd, " ", 1);
123
+ shell_escape(&zCmd, mprintf("%s", g.urlFossil));
124
+ blob_append(&zCmd, " test-http", 10);
125
+ if( g.urlPath && g.urlPath[0] ){
126
+ blob_append(&zCmd, " ", 1);
127
+ shell_escape(&zCmd, mprintf("%s", g.urlPath));
128
+ }
129
+ if( g.fSshTrace ){
130
+ fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
131
+ }
132
+ free(zHost);
133
+ popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
134
+ if( sshPid==0 ){
135
+ socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
136
+ }
137
+ blob_reset(&zCmd);
138
+ return sshPid==0;
277139
}
278140
279141
/*
280142
** Open a connection to the server. The server is defined by the following
281143
** global variables:
@@ -288,19 +150,12 @@
288150
*/
289151
int transport_open(void){
290152
int rc = 0;
291153
if( transport.isOpen==0 ){
292154
if( g.urlIsSsh ){
293
- Blob cmd;
294
- blob_zero(&cmd);
295
- shell_escape(&cmd, g.urlFossil);
296
- blob_append(&cmd, " test-http ", -1);
297
- shell_escape(&cmd, g.urlPath);
298
- fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299
- fflush(sshOut);
300
- if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301
- blob_reset(&cmd);
155
+ rc = transport_ssh_open();
156
+ if( rc==0 ) transport.isOpen = 1;
302157
}else if( g.urlIsHttps ){
303158
#ifdef FOSSIL_ENABLE_SSL
304159
rc = ssl_open();
305160
if( rc==0 ) transport.isOpen = 1;
306161
#else
@@ -340,11 +195,11 @@
340195
if( transport.pLog ){
341196
fclose(transport.pLog);
342197
transport.pLog = 0;
343198
}
344199
if( g.urlIsSsh ){
345
- /* No-op */
200
+ transport_ssh_close();
346201
}else if( g.urlIsHttps ){
347202
#ifdef FOSSIL_ENABLE_SSL
348203
ssl_close();
349204
#endif
350205
}else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
399254
/*
400255
** This routine is called when the outbound message is complete and
401256
** it is time to being receiving a reply.
402257
*/
403258
void transport_flip(void){
404
- if( g.urlIsSsh ){
405
- fprintf(sshOut, "\n\n");
406
- }else if( g.urlIsFile ){
259
+ if( g.urlIsFile ){
407260
char *zCmd;
408261
fclose(transport.pFile);
409262
zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410263
g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411264
);
@@ -581,20 +434,32 @@
581434
}
582435
if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583436
return &transport.pBuf[iStart];
584437
}
585438
439
+/*
440
+** Global transport shutdown
441
+*/
586442
void transport_global_shutdown(void){
587
- if( g.urlIsSsh && sshPid ){
588
- /*printf("Closing SSH tunnel: ");*/
589
- fflush(stdout);
590
- pclose2(sshIn, sshOut, sshPid);
591
- sshPid = 0;
443
+ if( g.urlIsSsh ){
444
+ transport_ssh_close();
592445
}
593446
if( g.urlIsHttps ){
594447
#ifdef FOSSIL_ENABLE_SSL
595448
ssl_global_shutdown();
596449
#endif
597450
}else{
598451
socket_global_shutdown();
599452
}
600453
}
454
+
455
+/*
456
+** Close SSH transport.
457
+*/
458
+void transport_ssh_close(void){
459
+ if( sshPid ){
460
+ /*printf("Closing SSH tunnel: ");*/
461
+ fflush(stdout);
462
+ pclose2(sshIn, sshOut, sshPid);
463
+ sshPid = 0;
464
+ }
465
+}
601466
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
74 transport.nSent = 0;
75 transport.nRcvd = 0;
76 }
77 }
78
79 /*
80 ** Read text from sshIn. Zero-terminate and remove trailing
81 ** whitespace.
82 */
83 static void sshin_read(char *zBuf, int szBuf){
84 int got;
85 zBuf[0] = 0;
86 got = read(sshIn, zBuf, szBuf-1);
87 while( got>=0 ){
88 zBuf[got] = 0;
89 if( got==0 || !fossil_isspace(zBuf[got-1]) ) break;
90 got--;
91 }
92 }
93
94 /*
95 ** Default SSH command
96 */
97 #ifdef __MINGW32__
98 static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
99 #else
100 static char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
102
103 /*
104 ** Generate a random SSH link problem keyword
105 */
106 static int random_probe(char *zProbe, int nProbe){
107 unsigned r[4];
108 sqlite3_randomness(sizeof(r), r);
109 sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110 r[0], r[1], r[2], r[3]);
111 return (int)strlen(zProbe);
112 }
113
114 /*
115 ** Bring up an SSH link. This involves sending some "echo" commands and
116 ** get back appropriate responses. The point is to move past the MOTD and
117 ** verify that the link is working.
118 */
119 static void transport_ssh_startup(void){
120 char *zIn; /* An input line received back from remote */
121 int nWait; /* Number of times waiting for the MOTD */
122 char zProbe[40]; /* Text of the random probe */
123 int nProbe; /* Size of probe message */
124 int nIn; /* Size of input */
125 static const int nBuf = 10000; /* Size of input buffer */
126
127 zIn = fossil_malloc(nBuf);
128 nProbe = random_probe(zProbe, sizeof(zProbe));
129 fprintf(sshOut, "echo %s\n", zProbe);
130 fflush(sshOut);
131 if( g.fSshTrace ){
132 printf("Sent: [echo %s]\n", zProbe);
133 fflush(stdout);
134 }
135 memset(zIn, '*', nProbe);
136 for(nWait=1; nWait<=10; nWait++){
137 sshin_read(zIn+nProbe, nBuf-nProbe);
138 if( g.fSshTrace ){
139 printf("Got back-----------------------------------------------\n"
140 "%s\n"
141 "-------------------------------------------------------\n",
142 zIn+nProbe);
143 }
144 if( strstr(zIn, zProbe) ) break;
145 sqlite3_sleep(100*nWait);
146 nIn = (int)strlen(zIn);
147 memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148 if( g.fSshTrace ){
149 printf("Fetching more text. Looking for [%s]...\n", zProbe);
150 fflush(stdout);
151 }
152 }
153 nProbe = random_probe(zProbe, sizeof(zProbe));
154 fprintf(sshOut, "echo %s\n", zProbe);
155 fflush(sshOut);
156 if( g.fSshTrace ){
157 printf("Sent: [echo %s]\n", zProbe);
158 fflush(stdout);
159 }
160 sshin_read(zIn, nBuf);
161 if( zIn[0]==0 ){
162 sqlite3_sleep(250);
163 sshin_read(zIn, nBuf);
164 }
165 if( g.fSshTrace ){
166 printf("Got back-----------------------------------------------\n"
167 "%s\n"
168 "-------------------------------------------------------\n", zIn);
169 }
170 if( memcmp(zIn, zProbe, nProbe)!=0 ){
171 pclose2(sshIn, sshOut, sshPid);
172 fossil_fatal("ssh connection failed: [%s]", zIn);
173 }
174 fossil_free(zIn);
175 }
176
177 /*
178 ** Global initialization of the transport layer
179 */
180 void transport_global_startup(void){
181 if( g.urlIsSsh ){
182 /* Only SSH requires a global initialization. For SSH we need to create
183 ** and run an SSH command to talk to the remote machine.
184 */
185 const char *zSsh; /* The base SSH command */
186 Blob zCmd; /* The SSH command */
187 char *zHost; /* The host name to contact */
188 int n; /* Size of prefix string */
189
190 zSsh = db_get("ssh-command", zDefaultSshCmd);
191 blob_init(&zCmd, zSsh, -1);
192 if( g.urlPort!=g.urlDfltPort ){
193 #ifdef __MINGW32__
194 blob_appendf(&zCmd, " -P %d", g.urlPort);
195 #else
196 blob_appendf(&zCmd, " -p %d", g.urlPort);
197 #endif
198 }
199 fossil_force_newline();
200 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201 if( g.urlUser && g.urlUser[0] ){
202 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203 #ifdef __MINGW32__
204 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205 if( g.urlPasswd && g.urlPasswd[0] ){
206 Blob pw;
207 blob_zero(&pw);
208 if( g.urlPasswd[0]=='*' ){
209 char *zPrompt;
210 zPrompt = mprintf("Password for [%s]: ", zHost);
211 prompt_for_password(zPrompt, &pw, 0);
212 free(zPrompt);
213 }else{
214 blob_init(&pw, g.urlPasswd, -1);
215 }
216 blob_append(&zCmd, " -pw ", -1);
217 shell_escape(&zCmd, blob_str(&pw));
218 blob_reset(&pw);
219 fossil_print(" -pw ********"); /* Do not show the password text */
220 }
221 #endif
222 }else{
223 zHost = mprintf("%s", g.urlName);
224 }
225 n = blob_size(&zCmd);
226 blob_append(&zCmd, " ", 1);
227 shell_escape(&zCmd, zHost);
228 if( g.urlShell ){
229 blob_appendf(&zCmd, " %s", g.urlShell);
230 }else{
231 #if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232 /* The following works. But only if the fossil on the remote side
233 ** is recent enough to support the test-ssh-far-side command. That
234 ** command was added on 2013-02-06. We will leave this turned off
235 ** until most fossil servers have upgraded to that version or a later
236 ** version. The sync will still work as long as the shell on the far
237 ** side is bash and not tcsh. And if the default far side shell is
238 ** tcsh, then the shell=/bin/bash query parameter can be used as a
239 ** work-around. Enable this code after about a year...
240 */
241 blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242 #endif
243 }
244 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245 free(zHost);
246 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247 if( sshPid==0 ){
248 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249 }
250 blob_reset(&zCmd);
251 transport_ssh_startup();
252 }
253 }
254
255 /*
256 ** COMMAND: test-ssh-far-side
257 **
258 ** Read lines of input text, one by one, and evaluate each line using
259 ** system(). The ssh: sync protocol uses this on the far side of the
260 ** SSH link.
261 */
262 void test_ssh_far_side_cmd(void){
263 int i = 0;
264 int got;
265 char zLine[5000];
266 while( i<sizeof(zLine) ){
267 got = read(0, zLine+i, 1);
268 if( got==0 ) return;
269 if( zLine[i]=='\n' ){
270 zLine[i] = 0;
271 system(zLine);
272 i = 0;
273 }else{
274 i++;
275 }
276 }
277 }
278
279 /*
280 ** Open a connection to the server. The server is defined by the following
281 ** global variables:
@@ -288,19 +150,12 @@
288 */
289 int transport_open(void){
290 int rc = 0;
291 if( transport.isOpen==0 ){
292 if( g.urlIsSsh ){
293 Blob cmd;
294 blob_zero(&cmd);
295 shell_escape(&cmd, g.urlFossil);
296 blob_append(&cmd, " test-http ", -1);
297 shell_escape(&cmd, g.urlPath);
298 fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299 fflush(sshOut);
300 if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301 blob_reset(&cmd);
302 }else if( g.urlIsHttps ){
303 #ifdef FOSSIL_ENABLE_SSL
304 rc = ssl_open();
305 if( rc==0 ) transport.isOpen = 1;
306 #else
@@ -340,11 +195,11 @@
340 if( transport.pLog ){
341 fclose(transport.pLog);
342 transport.pLog = 0;
343 }
344 if( g.urlIsSsh ){
345 /* No-op */
346 }else if( g.urlIsHttps ){
347 #ifdef FOSSIL_ENABLE_SSL
348 ssl_close();
349 #endif
350 }else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
399 /*
400 ** This routine is called when the outbound message is complete and
401 ** it is time to being receiving a reply.
402 */
403 void transport_flip(void){
404 if( g.urlIsSsh ){
405 fprintf(sshOut, "\n\n");
406 }else if( g.urlIsFile ){
407 char *zCmd;
408 fclose(transport.pFile);
409 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411 );
@@ -581,20 +434,32 @@
581 }
582 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583 return &transport.pBuf[iStart];
584 }
585
 
 
 
586 void transport_global_shutdown(void){
587 if( g.urlIsSsh && sshPid ){
588 /*printf("Closing SSH tunnel: ");*/
589 fflush(stdout);
590 pclose2(sshIn, sshOut, sshPid);
591 sshPid = 0;
592 }
593 if( g.urlIsHttps ){
594 #ifdef FOSSIL_ENABLE_SSL
595 ssl_global_shutdown();
596 #endif
597 }else{
598 socket_global_shutdown();
599 }
600 }
 
 
 
 
 
 
 
 
 
 
 
 
601
--- src/http_transport.c
+++ src/http_transport.c
@@ -74,25 +74,10 @@
74 transport.nSent = 0;
75 transport.nRcvd = 0;
76 }
77 }
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79 /*
80 ** Default SSH command
81 */
82 #ifdef __MINGW32__
83 static char zDefaultSshCmd[] = "ssh -T";
@@ -99,183 +84,60 @@
84 #else
85 static char zDefaultSshCmd[] = "ssh -e none -T";
86 #endif
87
88 /*
89 ** SSH initialization of the transport layer
90 */
91 int transport_ssh_open(void){
92 /* For SSH we need to create and run SSH fossil http
93 ** to talk to the remote machine.
94 */
95 const char *zSsh; /* The base SSH command */
96 Blob zCmd; /* The SSH command */
97 char *zHost; /* The host name to contact */
98 int n; /* Size of prefix string */
99
100 socket_ssh_resolve_addr();
101 zSsh = db_get("ssh-command", zDefaultSshCmd);
102 blob_init(&zCmd, zSsh, -1);
103 if( g.urlPort!=g.urlDfltPort && g.urlPort ){
104 #ifdef __MINGW32__
105 blob_appendf(&zCmd, " -P %d", g.urlPort);
106 #else
107 blob_appendf(&zCmd, " -p %d", g.urlPort);
108 #endif
109 }
110 if( g.fSshTrace ){
111 fossil_force_newline();
112 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
113 }
114 if( g.urlUser && g.urlUser[0] ){
115 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
116 }else{
117 zHost = mprintf("%s", g.urlName);
118 }
119 n = blob_size(&zCmd);
120 blob_append(&zCmd, " ", 1);
121 shell_escape(&zCmd, zHost);
122 blob_append(&zCmd, " ", 1);
123 shell_escape(&zCmd, mprintf("%s", g.urlFossil));
124 blob_append(&zCmd, " test-http", 10);
125 if( g.urlPath && g.urlPath[0] ){
126 blob_append(&zCmd, " ", 1);
127 shell_escape(&zCmd, mprintf("%s", g.urlPath));
128 }
129 if( g.fSshTrace ){
130 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
131 }
132 free(zHost);
133 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
134 if( sshPid==0 ){
135 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
136 }
137 blob_reset(&zCmd);
138 return sshPid==0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139 }
140
141 /*
142 ** Open a connection to the server. The server is defined by the following
143 ** global variables:
@@ -288,19 +150,12 @@
150 */
151 int transport_open(void){
152 int rc = 0;
153 if( transport.isOpen==0 ){
154 if( g.urlIsSsh ){
155 rc = transport_ssh_open();
156 if( rc==0 ) transport.isOpen = 1;
 
 
 
 
 
 
 
157 }else if( g.urlIsHttps ){
158 #ifdef FOSSIL_ENABLE_SSL
159 rc = ssl_open();
160 if( rc==0 ) transport.isOpen = 1;
161 #else
@@ -340,11 +195,11 @@
195 if( transport.pLog ){
196 fclose(transport.pLog);
197 transport.pLog = 0;
198 }
199 if( g.urlIsSsh ){
200 transport_ssh_close();
201 }else if( g.urlIsHttps ){
202 #ifdef FOSSIL_ENABLE_SSL
203 ssl_close();
204 #endif
205 }else if( g.urlIsFile ){
@@ -399,13 +254,11 @@
254 /*
255 ** This routine is called when the outbound message is complete and
256 ** it is time to being receiving a reply.
257 */
258 void transport_flip(void){
259 if( g.urlIsFile ){
 
 
260 char *zCmd;
261 fclose(transport.pFile);
262 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
263 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
264 );
@@ -581,20 +434,32 @@
434 }
435 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
436 return &transport.pBuf[iStart];
437 }
438
439 /*
440 ** Global transport shutdown
441 */
442 void transport_global_shutdown(void){
443 if( g.urlIsSsh ){
444 transport_ssh_close();
 
 
 
445 }
446 if( g.urlIsHttps ){
447 #ifdef FOSSIL_ENABLE_SSL
448 ssl_global_shutdown();
449 #endif
450 }else{
451 socket_global_shutdown();
452 }
453 }
454
455 /*
456 ** Close SSH transport.
457 */
458 void transport_ssh_close(void){
459 if( sshPid ){
460 /*printf("Closing SSH tunnel: ");*/
461 fflush(stdout);
462 pclose2(sshIn, sshOut, sshPid);
463 sshPid = 0;
464 }
465 }
466
+1 -1
--- src/import.c
+++ src/import.c
@@ -419,11 +419,11 @@
419419
gg.zPrevCheckin = 0;
420420
}
421421
if( gg.zFrom==0 ) return;
422422
rid = fast_uuid_to_rid(gg.zFrom);
423423
if( rid==0 ) return;
424
- p = manifest_get(rid, CFTYPE_MANIFEST);
424
+ p = manifest_get(rid, CFTYPE_MANIFEST, 0);
425425
if( p==0 ) return;
426426
manifest_file_rewind(p);
427427
while( (pOld = manifest_file_next(p, 0))!=0 ){
428428
pNew = import_add_file();
429429
pNew->zName = fossil_strdup(pOld->zName);
430430
--- src/import.c
+++ src/import.c
@@ -419,11 +419,11 @@
419 gg.zPrevCheckin = 0;
420 }
421 if( gg.zFrom==0 ) return;
422 rid = fast_uuid_to_rid(gg.zFrom);
423 if( rid==0 ) return;
424 p = manifest_get(rid, CFTYPE_MANIFEST);
425 if( p==0 ) return;
426 manifest_file_rewind(p);
427 while( (pOld = manifest_file_next(p, 0))!=0 ){
428 pNew = import_add_file();
429 pNew->zName = fossil_strdup(pOld->zName);
430
--- src/import.c
+++ src/import.c
@@ -419,11 +419,11 @@
419 gg.zPrevCheckin = 0;
420 }
421 if( gg.zFrom==0 ) return;
422 rid = fast_uuid_to_rid(gg.zFrom);
423 if( rid==0 ) return;
424 p = manifest_get(rid, CFTYPE_MANIFEST, 0);
425 if( p==0 ) return;
426 manifest_file_rewind(p);
427 while( (pOld = manifest_file_next(p, 0))!=0 ){
428 pNew = import_add_file();
429 pNew->zName = fossil_strdup(pOld->zName);
430
+20 -7
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579579
@ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580580
}
581581
db_finalize(&q2);
582582
}
583583
if( g.perm.Hyperlink ){
584
- const char *zProjName = db_get("project-name", "unnamed");
584
+ char *zPJ = db_get("short-project-name", 0);
585
+ Blob projName;
586
+ int jj;
587
+ if( zPJ==0 ) zPJ = db_get("project-name", "unnamed");
588
+ blob_zero(&projName);
589
+ blob_append(&projName, zPJ, -1);
590
+ blob_trim(&projName);
591
+ zPJ = blob_str(&projName);
592
+ for(jj=0; zPJ[jj]; jj++){
593
+ if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
594
+ zPJ[jj] = '_';
595
+ }
596
+ }
585597
@ <tr><th>Timelines:</th><td>
586598
@ %z(href("%R/timeline?f=%S",zUuid))family</a>
587599
if( zParent ){
588600
@ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
589601
}
@@ -605,15 +617,15 @@
605617
606618
607619
/* The Download: line */
608620
if( g.perm.Zip ){
609621
char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
610
- zProjName, zUuid, zUuid);
622
+ zPJ, zUuid, zUuid);
611623
@ </td></tr>
612624
@ <tr><th>Downloads:</th><td>
613625
@ %z(href("%s",zUrl))Tarball</a>
614
- @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
626
+ @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
615627
@ ZIP archive</a>
616628
fossil_free(zUrl);
617629
}
618630
@ </td></tr>
619631
@ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
624636
if( g.perm.Write ){
625637
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
626638
}
627639
@ </td>
628640
@ </tr>
641
+ blob_reset(&projName);
629642
}
630643
@ </table>
631644
}else{
632645
style_header("Check-in Information");
633646
login_anonymous_available();
@@ -723,11 +736,11 @@
723736
const char *zModAction;
724737
725738
login_check_credentials();
726739
if( !g.perm.RdWiki ){ login_needed(); return; }
727740
rid = name_to_rid_www("name");
728
- if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI))==0 ){
741
+ if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){
729742
style_header("Wiki Page Information Error");
730743
@ No such object: %h(P("name"))
731744
style_footer();
732745
return;
733746
}
@@ -834,11 +847,11 @@
834847
}
835848
if( !is_a_version(rid) ){
836849
webpage_error("Artifact %s is not a checkin.", P(zParam));
837850
return 0;
838851
}
839
- return manifest_get(rid, CFTYPE_MANIFEST);
852
+ return manifest_get(rid, CFTYPE_MANIFEST, 0);
840853
}
841854
842855
/*
843856
** Output a description of a check-in
844857
*/
@@ -1485,11 +1498,11 @@
14851498
zCI = P("ci");
14861499
if( zCI==0 ) return 0;
14871500
zFilename = P("filename");
14881501
if( zFilename==0 ) return 0;
14891502
cirid = name_to_rid_www("ci");
1490
- pManifest = manifest_get(cirid, CFTYPE_MANIFEST);
1503
+ pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
14911504
if( pManifest==0 ) return 0;
14921505
manifest_file_rewind(pManifest);
14931506
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
14941507
if( fossil_strcmp(zFilename, pFile->zName)==0 ){
14951508
int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
@@ -1708,11 +1721,11 @@
17081721
}else{
17091722
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
17101723
g.zTop, zUuid);
17111724
}
17121725
}
1713
- pTktChng = manifest_get(rid, CFTYPE_TICKET);
1726
+ pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
17141727
if( pTktChng==0 ) fossil_redirect_home();
17151728
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
17161729
memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
17171730
if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
17181731
if( strcmp(zModAction,"delete")==0 ){
17191732
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580 }
581 db_finalize(&q2);
582 }
583 if( g.perm.Hyperlink ){
584 const char *zProjName = db_get("project-name", "unnamed");
 
 
 
 
 
 
 
 
 
 
 
 
585 @ <tr><th>Timelines:</th><td>
586 @ %z(href("%R/timeline?f=%S",zUuid))family</a>
587 if( zParent ){
588 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
589 }
@@ -605,15 +617,15 @@
605
606
607 /* The Download: line */
608 if( g.perm.Zip ){
609 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
610 zProjName, zUuid, zUuid);
611 @ </td></tr>
612 @ <tr><th>Downloads:</th><td>
613 @ %z(href("%s",zUrl))Tarball</a>
614 @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
615 @ ZIP archive</a>
616 fossil_free(zUrl);
617 }
618 @ </td></tr>
619 @ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
624 if( g.perm.Write ){
625 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
626 }
627 @ </td>
628 @ </tr>
 
629 }
630 @ </table>
631 }else{
632 style_header("Check-in Information");
633 login_anonymous_available();
@@ -723,11 +736,11 @@
723 const char *zModAction;
724
725 login_check_credentials();
726 if( !g.perm.RdWiki ){ login_needed(); return; }
727 rid = name_to_rid_www("name");
728 if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI))==0 ){
729 style_header("Wiki Page Information Error");
730 @ No such object: %h(P("name"))
731 style_footer();
732 return;
733 }
@@ -834,11 +847,11 @@
834 }
835 if( !is_a_version(rid) ){
836 webpage_error("Artifact %s is not a checkin.", P(zParam));
837 return 0;
838 }
839 return manifest_get(rid, CFTYPE_MANIFEST);
840 }
841
842 /*
843 ** Output a description of a check-in
844 */
@@ -1485,11 +1498,11 @@
1485 zCI = P("ci");
1486 if( zCI==0 ) return 0;
1487 zFilename = P("filename");
1488 if( zFilename==0 ) return 0;
1489 cirid = name_to_rid_www("ci");
1490 pManifest = manifest_get(cirid, CFTYPE_MANIFEST);
1491 if( pManifest==0 ) return 0;
1492 manifest_file_rewind(pManifest);
1493 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1494 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1495 int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
@@ -1708,11 +1721,11 @@
1708 }else{
1709 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1710 g.zTop, zUuid);
1711 }
1712 }
1713 pTktChng = manifest_get(rid, CFTYPE_TICKET);
1714 if( pTktChng==0 ) fossil_redirect_home();
1715 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1716 memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
1717 if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
1718 if( strcmp(zModAction,"delete")==0 ){
1719
--- src/info.c
+++ src/info.c
@@ -579,11 +579,23 @@
579 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
580 }
581 db_finalize(&q2);
582 }
583 if( g.perm.Hyperlink ){
584 char *zPJ = db_get("short-project-name", 0);
585 Blob projName;
586 int jj;
587 if( zPJ==0 ) zPJ = db_get("project-name", "unnamed");
588 blob_zero(&projName);
589 blob_append(&projName, zPJ, -1);
590 blob_trim(&projName);
591 zPJ = blob_str(&projName);
592 for(jj=0; zPJ[jj]; jj++){
593 if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
594 zPJ[jj] = '_';
595 }
596 }
597 @ <tr><th>Timelines:</th><td>
598 @ %z(href("%R/timeline?f=%S",zUuid))family</a>
599 if( zParent ){
600 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
601 }
@@ -605,15 +617,15 @@
617
618
619 /* The Download: line */
620 if( g.perm.Zip ){
621 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
622 zPJ, zUuid, zUuid);
623 @ </td></tr>
624 @ <tr><th>Downloads:</th><td>
625 @ %z(href("%s",zUrl))Tarball</a>
626 @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
627 @ ZIP archive</a>
628 fossil_free(zUrl);
629 }
630 @ </td></tr>
631 @ <tr><th>Other&nbsp;Links:</th>
@@ -624,10 +636,11 @@
636 if( g.perm.Write ){
637 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
638 }
639 @ </td>
640 @ </tr>
641 blob_reset(&projName);
642 }
643 @ </table>
644 }else{
645 style_header("Check-in Information");
646 login_anonymous_available();
@@ -723,11 +736,11 @@
736 const char *zModAction;
737
738 login_check_credentials();
739 if( !g.perm.RdWiki ){ login_needed(); return; }
740 rid = name_to_rid_www("name");
741 if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){
742 style_header("Wiki Page Information Error");
743 @ No such object: %h(P("name"))
744 style_footer();
745 return;
746 }
@@ -834,11 +847,11 @@
847 }
848 if( !is_a_version(rid) ){
849 webpage_error("Artifact %s is not a checkin.", P(zParam));
850 return 0;
851 }
852 return manifest_get(rid, CFTYPE_MANIFEST, 0);
853 }
854
855 /*
856 ** Output a description of a check-in
857 */
@@ -1485,11 +1498,11 @@
1498 zCI = P("ci");
1499 if( zCI==0 ) return 0;
1500 zFilename = P("filename");
1501 if( zFilename==0 ) return 0;
1502 cirid = name_to_rid_www("ci");
1503 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1504 if( pManifest==0 ) return 0;
1505 manifest_file_rewind(pManifest);
1506 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1507 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
1508 int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
@@ -1708,11 +1721,11 @@
1721 }else{
1722 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1723 g.zTop, zUuid);
1724 }
1725 }
1726 pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
1727 if( pTktChng==0 ) fossil_redirect_home();
1728 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1729 memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
1730 if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
1731 if( strcmp(zModAction,"delete")==0 ){
1732
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -192,11 +192,11 @@
192192
if(!eventTypeLabel){
193193
eventTypeLabel = json_new_string("ticket");
194194
json_gc_add("$EVENT_TYPE_LABEL(ticket)", eventTypeLabel);
195195
}
196196
197
- pTktChng = manifest_get(rid, CFTYPE_TICKET);
197
+ pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
198198
if( pTktChng==0 ){
199199
g.json.resultCode = FSL_JSON_E_MANIFEST_READ_FAILED;
200200
return NULL;
201201
}
202202
pay = cson_new_object();
203203
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -192,11 +192,11 @@
192 if(!eventTypeLabel){
193 eventTypeLabel = json_new_string("ticket");
194 json_gc_add("$EVENT_TYPE_LABEL(ticket)", eventTypeLabel);
195 }
196
197 pTktChng = manifest_get(rid, CFTYPE_TICKET);
198 if( pTktChng==0 ){
199 g.json.resultCode = FSL_JSON_E_MANIFEST_READ_FAILED;
200 return NULL;
201 }
202 pay = cson_new_object();
203
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -192,11 +192,11 @@
192 if(!eventTypeLabel){
193 eventTypeLabel = json_new_string("ticket");
194 json_gc_add("$EVENT_TYPE_LABEL(ticket)", eventTypeLabel);
195 }
196
197 pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
198 if( pTktChng==0 ){
199 g.json.resultCode = FSL_JSON_E_MANIFEST_READ_FAILED;
200 return NULL;
201 }
202 pay = cson_new_object();
203
--- src/json_branch.c
+++ src/json_branch.c
@@ -218,11 +218,11 @@
218218
if( rootid==0 ){
219219
zOpt->rcErrMsg = "Basis branch not found.";
220220
return FSL_JSON_E_RESOURCE_NOT_FOUND;
221221
}
222222
223
- pParent = manifest_get(rootid, CFTYPE_MANIFEST);
223
+ pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0);
224224
if( pParent==0 ){
225225
zOpt->rcErrMsg = "Could not read parent manifest.";
226226
return FSL_JSON_E_UNKNOWN;
227227
}
228228
229229
--- src/json_branch.c
+++ src/json_branch.c
@@ -218,11 +218,11 @@
218 if( rootid==0 ){
219 zOpt->rcErrMsg = "Basis branch not found.";
220 return FSL_JSON_E_RESOURCE_NOT_FOUND;
221 }
222
223 pParent = manifest_get(rootid, CFTYPE_MANIFEST);
224 if( pParent==0 ){
225 zOpt->rcErrMsg = "Could not read parent manifest.";
226 return FSL_JSON_E_UNKNOWN;
227 }
228
229
--- src/json_branch.c
+++ src/json_branch.c
@@ -218,11 +218,11 @@
218 if( rootid==0 ){
219 zOpt->rcErrMsg = "Basis branch not found.";
220 return FSL_JSON_E_RESOURCE_NOT_FOUND;
221 }
222
223 pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0);
224 if( pParent==0 ){
225 zOpt->rcErrMsg = "Could not read parent manifest.";
226 return FSL_JSON_E_UNKNOWN;
227 }
228
229
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -632,11 +632,11 @@
632632
int const rid = db_column_int(&q,0);
633633
Manifest * pMan = NULL;
634634
cson_value * rowV;
635635
cson_object * row;
636636
/*printf("rid=%d\n",rid);*/
637
- pMan = manifest_get(rid, CFTYPE_TICKET);
637
+ pMan = manifest_get(rid, CFTYPE_TICKET, 0);
638638
if(!pMan){
639639
/* this might be an attachment? I'm seeing this with
640640
rid 15380, uuid [1292fef05f2472108].
641641
642642
/json/artifact/1292fef05f2472108 returns not-found,
643643
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -632,11 +632,11 @@
632 int const rid = db_column_int(&q,0);
633 Manifest * pMan = NULL;
634 cson_value * rowV;
635 cson_object * row;
636 /*printf("rid=%d\n",rid);*/
637 pMan = manifest_get(rid, CFTYPE_TICKET);
638 if(!pMan){
639 /* this might be an attachment? I'm seeing this with
640 rid 15380, uuid [1292fef05f2472108].
641
642 /json/artifact/1292fef05f2472108 returns not-found,
643
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -632,11 +632,11 @@
632 int const rid = db_column_int(&q,0);
633 Manifest * pMan = NULL;
634 cson_value * rowV;
635 cson_object * row;
636 /*printf("rid=%d\n",rid);*/
637 pMan = manifest_get(rid, CFTYPE_TICKET, 0);
638 if(!pMan){
639 /* this might be an attachment? I'm seeing this with
640 rid 15380, uuid [1292fef05f2472108].
641
642 /json/artifact/1292fef05f2472108 returns not-found,
643
+3 -3
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -82,11 +82,11 @@
8282
** The returned value, if not NULL, is-a JSON Object owned by the
8383
** caller. If it returns NULL then it may set g.json's error state.
8484
*/
8585
cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
8686
Manifest * pWiki = NULL;
87
- if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
87
+ if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){
8888
json_set_err( FSL_JSON_E_UNKNOWN,
8989
"Error reading wiki page from manifest (rid=%d).",
9090
rid );
9191
return NULL;
9292
}else{
@@ -528,16 +528,16 @@
528528
}else if(0==r2){
529529
goto invalid;
530530
}
531531
532532
zErrTag = zV1;
533
- pW1 = manifest_get(r1, CFTYPE_WIKI);
533
+ pW1 = manifest_get(r1, CFTYPE_WIKI, 0);
534534
if( pW1==0 ) {
535535
goto manifest;
536536
}
537537
zErrTag = zV2;
538
- pW2 = manifest_get(r2, CFTYPE_WIKI);
538
+ pW2 = manifest_get(r2, CFTYPE_WIKI, 0);
539539
if( pW2==0 ) {
540540
goto manifest;
541541
}
542542
543543
blob_init(&w1, pW1->zWiki, -1);
544544
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -82,11 +82,11 @@
82 ** The returned value, if not NULL, is-a JSON Object owned by the
83 ** caller. If it returns NULL then it may set g.json's error state.
84 */
85 cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
86 Manifest * pWiki = NULL;
87 if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
88 json_set_err( FSL_JSON_E_UNKNOWN,
89 "Error reading wiki page from manifest (rid=%d).",
90 rid );
91 return NULL;
92 }else{
@@ -528,16 +528,16 @@
528 }else if(0==r2){
529 goto invalid;
530 }
531
532 zErrTag = zV1;
533 pW1 = manifest_get(r1, CFTYPE_WIKI);
534 if( pW1==0 ) {
535 goto manifest;
536 }
537 zErrTag = zV2;
538 pW2 = manifest_get(r2, CFTYPE_WIKI);
539 if( pW2==0 ) {
540 goto manifest;
541 }
542
543 blob_init(&w1, pW1->zWiki, -1);
544
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -82,11 +82,11 @@
82 ** The returned value, if not NULL, is-a JSON Object owned by the
83 ** caller. If it returns NULL then it may set g.json's error state.
84 */
85 cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){
86 Manifest * pWiki = NULL;
87 if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){
88 json_set_err( FSL_JSON_E_UNKNOWN,
89 "Error reading wiki page from manifest (rid=%d).",
90 rid );
91 return NULL;
92 }else{
@@ -528,16 +528,16 @@
528 }else if(0==r2){
529 goto invalid;
530 }
531
532 zErrTag = zV1;
533 pW1 = manifest_get(r1, CFTYPE_WIKI, 0);
534 if( pW1==0 ) {
535 goto manifest;
536 }
537 zErrTag = zV2;
538 pW2 = manifest_get(r2, CFTYPE_WIKI, 0);
539 if( pW2==0 ) {
540 goto manifest;
541 }
542
543 blob_init(&w1, pW1->zWiki, -1);
544
+2 -1
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793793
**
794794
** This feature allows the "fossil ui" command to give the user
795795
** full access rights without having to log in.
796796
*/
797797
zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798
- if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
798
+ if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
799
+ g.fSshClient & CGI_SSH_CLIENT )
799800
&& g.useLocalauth
800801
&& db_get_int("localauth",0)==0
801802
&& P("HTTPS")==0
802803
){
803804
uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
804805
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793 **
794 ** This feature allows the "fossil ui" command to give the user
795 ** full access rights without having to log in.
796 */
797 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798 if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
 
799 && g.useLocalauth
800 && db_get_int("localauth",0)==0
801 && P("HTTPS")==0
802 ){
803 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
804
--- src/login.c
+++ src/login.c
@@ -793,11 +793,12 @@
793 **
794 ** This feature allows the "fossil ui" command to give the user
795 ** full access rights without having to log in.
796 */
797 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
798 if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
799 g.fSshClient & CGI_SSH_CLIENT )
800 && g.useLocalauth
801 && db_get_int("localauth",0)==0
802 && P("HTTPS")==0
803 ){
804 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
805
+38 -5
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138138
int fSqlPrint; /* True if -sqlprint flag is present */
139139
int fQuiet; /* True if -quiet flag is present */
140140
int fHttpTrace; /* Trace outbound HTTP requests */
141141
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142142
int fSshTrace; /* Trace the SSH setup traffic */
143
+ int fSshClient; /* HTTP client flags for SSH client */
144
+ char *zSshCmd; /* SSH command string */
143145
int fNoSync; /* Do not do an autosync ever. --nosync */
144146
char *zPath; /* Name of webpage being served */
145147
char *zExtra; /* Extra path information past the webpage name */
146148
char *zBaseURL; /* Full text of the URL being served */
147149
char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
179181
char *urlUser; /* User id for http: */
180182
char *urlPasswd; /* Password for http: */
181183
char *urlCanonical; /* Canonical representation of the URL */
182184
char *urlProxyAuth; /* Proxy-Authorizer: string */
183185
char *urlFossil; /* The fossil query parameter on ssh: */
184
- char *urlShell; /* The shell query parameter on ssh: */
185186
unsigned urlFlags; /* Boolean flags controlling URL processing */
186187
187188
const char *zLogin; /* Login name. "" if not logged in. */
188189
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
189190
** SSL client identity */
@@ -603,10 +604,12 @@
603604
g.fQuiet = find_option("quiet", 0, 0)!=0;
604605
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
605606
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
606607
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
607608
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
609
+ g.fSshClient = 0;
610
+ g.zSshCmd = 0;
608611
if( g.fSqlTrace ) g.fSqlStats = 1;
609612
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
610613
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
611614
g.zLogin = find_option("user", "U", 1);
612615
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
13141317
}
13151318
13161319
/* Find the page that the user has requested, construct and deliver that
13171320
** page.
13181321
*/
1319
- if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
1322
+ if( g.zContentType &&
1323
+ strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
13201324
zPathInfo = "/xfer";
13211325
}
13221326
set_base_url(0);
13231327
if( zPathInfo==0 || zPathInfo[0]==0
13241328
|| (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
17311735
zIpAddr = g.argv[5];
17321736
}else{
17331737
g.httpIn = stdin;
17341738
g.httpOut = stdout;
17351739
zIpAddr = 0;
1740
+ }
1741
+ if( zIpAddr==0 ){
1742
+ zIpAddr = cgi_ssh_remote_addr(0);
1743
+ if( zIpAddr && zIpAddr[0] ){
1744
+ g.fSshClient |= CGI_SSH_CLIENT;
1745
+ }
17361746
}
17371747
find_server_repository(0);
17381748
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
17391749
if( useSCGI ){
17401750
cgi_handle_scgi_request();
1751
+ }else if( g.fSshClient & CGI_SSH_CLIENT ){
1752
+ ssh_request_loop(zIpAddr, glob_create(zFileGlob));
17411753
}else{
17421754
cgi_handle_http_request(zIpAddr);
17431755
}
17441756
process_one_web_page(zNotFound, glob_create(zFileGlob));
17451757
}
1758
+
1759
+/*
1760
+** Process all requests in a single SSH connection if possible.
1761
+*/
1762
+void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
1763
+ do{
1764
+ cgi_handle_ssh_http_request(zIpAddr);
1765
+ process_one_web_page(0, FileGlob);
1766
+ blob_reset(&g.cgiIn);
1767
+ } while ( g.fSshClient & CGI_SSH_FOSSIL ||
1768
+ g.fSshClient & CGI_SSH_COMPAT );
1769
+}
17461770
17471771
/*
17481772
** Note that the following command is used by ssh:// processing.
17491773
**
17501774
** COMMAND: test-http
17511775
** Works like the http command but gives setup permission to all users.
1776
+**
17521777
*/
17531778
void cmd_test_http(void){
1779
+ const char *zIpAddr; /* IP address of remote client */
1780
+
17541781
Th_InitTraceLog();
17551782
login_set_capabilities("sx", 0);
17561783
g.useLocalauth = 1;
1757
- cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
17581784
g.httpIn = stdin;
17591785
g.httpOut = stdout;
17601786
find_server_repository(0);
17611787
g.cgiOutput = 1;
17621788
g.fullHttpReply = 1;
1763
- cgi_handle_http_request(0);
1764
- process_one_web_page(0, 0);
1789
+ zIpAddr = cgi_ssh_remote_addr(0);
1790
+ if( zIpAddr && zIpAddr[0] ){
1791
+ g.fSshClient |= CGI_SSH_CLIENT;
1792
+ ssh_request_loop(zIpAddr, 0);
1793
+ }else{
1794
+ cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1795
+ cgi_handle_http_request(0);
1796
+ process_one_web_page(0, 0);
1797
+ }
17651798
}
17661799
17671800
#if !defined(_WIN32)
17681801
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17691802
/*
17701803
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138 int fSqlPrint; /* True if -sqlprint flag is present */
139 int fQuiet; /* True if -quiet flag is present */
140 int fHttpTrace; /* Trace outbound HTTP requests */
141 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142 int fSshTrace; /* Trace the SSH setup traffic */
 
 
143 int fNoSync; /* Do not do an autosync ever. --nosync */
144 char *zPath; /* Name of webpage being served */
145 char *zExtra; /* Extra path information past the webpage name */
146 char *zBaseURL; /* Full text of the URL being served */
147 char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
179 char *urlUser; /* User id for http: */
180 char *urlPasswd; /* Password for http: */
181 char *urlCanonical; /* Canonical representation of the URL */
182 char *urlProxyAuth; /* Proxy-Authorizer: string */
183 char *urlFossil; /* The fossil query parameter on ssh: */
184 char *urlShell; /* The shell query parameter on ssh: */
185 unsigned urlFlags; /* Boolean flags controlling URL processing */
186
187 const char *zLogin; /* Login name. "" if not logged in. */
188 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
189 ** SSL client identity */
@@ -603,10 +604,12 @@
603 g.fQuiet = find_option("quiet", 0, 0)!=0;
604 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
605 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
606 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
607 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
 
 
608 if( g.fSqlTrace ) g.fSqlStats = 1;
609 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
610 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
611 g.zLogin = find_option("user", "U", 1);
612 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
1314 }
1315
1316 /* Find the page that the user has requested, construct and deliver that
1317 ** page.
1318 */
1319 if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
 
1320 zPathInfo = "/xfer";
1321 }
1322 set_base_url(0);
1323 if( zPathInfo==0 || zPathInfo[0]==0
1324 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
1731 zIpAddr = g.argv[5];
1732 }else{
1733 g.httpIn = stdin;
1734 g.httpOut = stdout;
1735 zIpAddr = 0;
 
 
 
 
 
 
1736 }
1737 find_server_repository(0);
1738 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1739 if( useSCGI ){
1740 cgi_handle_scgi_request();
 
 
1741 }else{
1742 cgi_handle_http_request(zIpAddr);
1743 }
1744 process_one_web_page(zNotFound, glob_create(zFileGlob));
1745 }
 
 
 
 
 
 
 
 
 
 
 
 
1746
1747 /*
1748 ** Note that the following command is used by ssh:// processing.
1749 **
1750 ** COMMAND: test-http
1751 ** Works like the http command but gives setup permission to all users.
 
1752 */
1753 void cmd_test_http(void){
 
 
1754 Th_InitTraceLog();
1755 login_set_capabilities("sx", 0);
1756 g.useLocalauth = 1;
1757 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1758 g.httpIn = stdin;
1759 g.httpOut = stdout;
1760 find_server_repository(0);
1761 g.cgiOutput = 1;
1762 g.fullHttpReply = 1;
1763 cgi_handle_http_request(0);
1764 process_one_web_page(0, 0);
 
 
 
 
 
 
 
1765 }
1766
1767 #if !defined(_WIN32)
1768 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1769 /*
1770
--- src/main.c
+++ src/main.c
@@ -138,10 +138,12 @@
138 int fSqlPrint; /* True if -sqlprint flag is present */
139 int fQuiet; /* True if -quiet flag is present */
140 int fHttpTrace; /* Trace outbound HTTP requests */
141 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
142 int fSshTrace; /* Trace the SSH setup traffic */
143 int fSshClient; /* HTTP client flags for SSH client */
144 char *zSshCmd; /* SSH command string */
145 int fNoSync; /* Do not do an autosync ever. --nosync */
146 char *zPath; /* Name of webpage being served */
147 char *zExtra; /* Extra path information past the webpage name */
148 char *zBaseURL; /* Full text of the URL being served */
149 char *zTop; /* Parent directory of zPath */
@@ -179,11 +181,10 @@
181 char *urlUser; /* User id for http: */
182 char *urlPasswd; /* Password for http: */
183 char *urlCanonical; /* Canonical representation of the URL */
184 char *urlProxyAuth; /* Proxy-Authorizer: string */
185 char *urlFossil; /* The fossil query parameter on ssh: */
 
186 unsigned urlFlags; /* Boolean flags controlling URL processing */
187
188 const char *zLogin; /* Login name. "" if not logged in. */
189 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
190 ** SSL client identity */
@@ -603,10 +604,12 @@
604 g.fQuiet = find_option("quiet", 0, 0)!=0;
605 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
606 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
607 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
608 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
609 g.fSshClient = 0;
610 g.zSshCmd = 0;
611 if( g.fSqlTrace ) g.fSqlStats = 1;
612 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
613 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
614 g.zLogin = find_option("user", "U", 1);
615 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -1314,11 +1317,12 @@
1317 }
1318
1319 /* Find the page that the user has requested, construct and deliver that
1320 ** page.
1321 */
1322 if( g.zContentType &&
1323 strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
1324 zPathInfo = "/xfer";
1325 }
1326 set_base_url(0);
1327 if( zPathInfo==0 || zPathInfo[0]==0
1328 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
@@ -1731,39 +1735,68 @@
1735 zIpAddr = g.argv[5];
1736 }else{
1737 g.httpIn = stdin;
1738 g.httpOut = stdout;
1739 zIpAddr = 0;
1740 }
1741 if( zIpAddr==0 ){
1742 zIpAddr = cgi_ssh_remote_addr(0);
1743 if( zIpAddr && zIpAddr[0] ){
1744 g.fSshClient |= CGI_SSH_CLIENT;
1745 }
1746 }
1747 find_server_repository(0);
1748 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1749 if( useSCGI ){
1750 cgi_handle_scgi_request();
1751 }else if( g.fSshClient & CGI_SSH_CLIENT ){
1752 ssh_request_loop(zIpAddr, glob_create(zFileGlob));
1753 }else{
1754 cgi_handle_http_request(zIpAddr);
1755 }
1756 process_one_web_page(zNotFound, glob_create(zFileGlob));
1757 }
1758
1759 /*
1760 ** Process all requests in a single SSH connection if possible.
1761 */
1762 void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
1763 do{
1764 cgi_handle_ssh_http_request(zIpAddr);
1765 process_one_web_page(0, FileGlob);
1766 blob_reset(&g.cgiIn);
1767 } while ( g.fSshClient & CGI_SSH_FOSSIL ||
1768 g.fSshClient & CGI_SSH_COMPAT );
1769 }
1770
1771 /*
1772 ** Note that the following command is used by ssh:// processing.
1773 **
1774 ** COMMAND: test-http
1775 ** Works like the http command but gives setup permission to all users.
1776 **
1777 */
1778 void cmd_test_http(void){
1779 const char *zIpAddr; /* IP address of remote client */
1780
1781 Th_InitTraceLog();
1782 login_set_capabilities("sx", 0);
1783 g.useLocalauth = 1;
 
1784 g.httpIn = stdin;
1785 g.httpOut = stdout;
1786 find_server_repository(0);
1787 g.cgiOutput = 1;
1788 g.fullHttpReply = 1;
1789 zIpAddr = cgi_ssh_remote_addr(0);
1790 if( zIpAddr && zIpAddr[0] ){
1791 g.fSshClient |= CGI_SSH_CLIENT;
1792 ssh_request_loop(zIpAddr, 0);
1793 }else{
1794 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1795 cgi_handle_http_request(0);
1796 process_one_web_page(0, 0);
1797 }
1798 }
1799
1800 #if !defined(_WIN32)
1801 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1802 /*
1803
+41 -30
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -502,12 +502,12 @@
502502
endif
503503
endif
504504
505505
# With MinGW command line handling workaround
506506
ifdef MINGW_IS_32BIT_ONLY
507
-TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
508
-RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
507
+TCC += -DBROKEN_MINGW_CMDLINE=1
508
+RCC += -DBROKEN_MINGW_CMDLINE=1
509509
endif
510510
511511
# With HTTPS support
512512
ifdef FOSSIL_ENABLE_SSL
513513
TCC += -DFOSSIL_ENABLE_SSL=1
@@ -771,10 +771,11 @@
771771
}
772772
773773
774774
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
775775
set opt $SQLITE_OPTIONS
776
+append opt " -D_HAVE_SQLITE_CONFIG_H"
776777
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
777778
778779
set opt {}
779780
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
780781
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
@@ -973,10 +974,13 @@
973974
SRCDIR = $B\src
974975
OBJDIR = .
975976
OX = .
976977
O = .obj
977978
E = .exe
979
+
980
+# Uncomment to enable debug symbols
981
+# DEBUG = 1
978982
979983
# Uncomment to enable JSON API
980984
# FOSSIL_ENABLE_JSON = 1
981985
982986
# Uncomment to enable SSL support
@@ -987,37 +991,44 @@
987991
SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
988992
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
989993
!endif
990994
991995
# zlib options
992
-ZINCDIR = $(B)\compat\zlib
993
-ZLIBDIR = $(B)\compat\zlib
994
-ZLIB = zlib.lib
995
-
996
-INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
997
-
998
-!ifdef FOSSIL_ENABLE_SSL
999
-INCL = $(INCL) -I$(SSLINCDIR)
1000
-!endif
1001
-
1002
-CFLAGS = -nologo -MT -O2
1003
-BCC = $(CC) $(CFLAGS)
1004
-TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
1005
-RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
1006
-LIBS = $(ZLIB) ws2_32.lib advapi32.lib
1007
-LIBDIR = -LIBPATH:$(ZLIBDIR)
1008
-
1009
-!ifdef FOSSIL_ENABLE_JSON
1010
-TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
1011
-RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
1012
-!endif
1013
-
1014
-!ifdef FOSSIL_ENABLE_SSL
1015
-TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
1016
-RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
1017
-LIBS = $(LIBS) $(SSLLIB)
1018
-LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
996
+ZINCDIR = $(B)\compat\zlib
997
+ZLIBDIR = $(B)\compat\zlib
998
+ZLIB = zlib.lib
999
+
1000
+INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
1001
+
1002
+!ifdef FOSSIL_ENABLE_SSL
1003
+INCL = $(INCL) -I$(SSLINCDIR)
1004
+!endif
1005
+
1006
+CFLAGS = -nologo -MT -O2
1007
+LDFLAGS = /NODEFAULTLIB:msvcrt
1008
+
1009
+!ifdef DEBUG
1010
+CFLAGS = $(CFLAGS) -Zi
1011
+LDFLAGS = $(LDFLAGS) /DEBUG
1012
+!endif
1013
+
1014
+BCC = $(CC) $(CFLAGS)
1015
+TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
1016
+RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
1017
+LIBS = $(ZLIB) ws2_32.lib advapi32.lib
1018
+LIBDIR = -LIBPATH:$(ZLIBDIR)
1019
+
1020
+!ifdef FOSSIL_ENABLE_JSON
1021
+TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
1022
+RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
1023
+!endif
1024
+
1025
+!ifdef FOSSIL_ENABLE_SSL
1026
+TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
1027
+RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
1028
+LIBS = $(LIBS) $(SSLLIB)
1029
+LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
10191030
!endif
10201031
}
10211032
regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
10221033
set j " \\\n "
10231034
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
@@ -1052,11 +1063,11 @@
10521063
@echo Building zlib from "$(ZLIBDIR)"...
10531064
@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
10541065
10551066
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
10561067
cd $(OX)
1057
- link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
1068
+ link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
10581069
10591070
$(OX)\linkopts: $B\win\Makefile.msc}
10601071
set redir {>}
10611072
foreach s [lsort [concat $src $AdditionalObj]] {
10621073
writeln "\techo \$(OX)\\$s.obj $redir \$@"
10631074
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -502,12 +502,12 @@
502 endif
503 endif
504
505 # With MinGW command line handling workaround
506 ifdef MINGW_IS_32BIT_ONLY
507 TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
508 RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
509 endif
510
511 # With HTTPS support
512 ifdef FOSSIL_ENABLE_SSL
513 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -771,10 +771,11 @@
771 }
772
773
774 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
775 set opt $SQLITE_OPTIONS
 
776 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
777
778 set opt {}
779 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
780 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
@@ -973,10 +974,13 @@
973 SRCDIR = $B\src
974 OBJDIR = .
975 OX = .
976 O = .obj
977 E = .exe
 
 
 
978
979 # Uncomment to enable JSON API
980 # FOSSIL_ENABLE_JSON = 1
981
982 # Uncomment to enable SSL support
@@ -987,37 +991,44 @@
987 SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
988 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
989 !endif
990
991 # zlib options
992 ZINCDIR = $(B)\compat\zlib
993 ZLIBDIR = $(B)\compat\zlib
994 ZLIB = zlib.lib
995
996 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
997
998 !ifdef FOSSIL_ENABLE_SSL
999 INCL = $(INCL) -I$(SSLINCDIR)
1000 !endif
1001
1002 CFLAGS = -nologo -MT -O2
1003 BCC = $(CC) $(CFLAGS)
1004 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
1005 RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
1006 LIBS = $(ZLIB) ws2_32.lib advapi32.lib
1007 LIBDIR = -LIBPATH:$(ZLIBDIR)
1008
1009 !ifdef FOSSIL_ENABLE_JSON
1010 TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
1011 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
1012 !endif
1013
1014 !ifdef FOSSIL_ENABLE_SSL
1015 TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
1016 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
1017 LIBS = $(LIBS) $(SSLLIB)
1018 LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
 
 
 
 
 
 
 
1019 !endif
1020 }
1021 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
1022 set j " \\\n "
1023 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
@@ -1052,11 +1063,11 @@
1052 @echo Building zlib from "$(ZLIBDIR)"...
1053 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
1054
1055 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
1056 cd $(OX)
1057 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
1058
1059 $(OX)\linkopts: $B\win\Makefile.msc}
1060 set redir {>}
1061 foreach s [lsort [concat $src $AdditionalObj]] {
1062 writeln "\techo \$(OX)\\$s.obj $redir \$@"
1063
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -502,12 +502,12 @@
502 endif
503 endif
504
505 # With MinGW command line handling workaround
506 ifdef MINGW_IS_32BIT_ONLY
507 TCC += -DBROKEN_MINGW_CMDLINE=1
508 RCC += -DBROKEN_MINGW_CMDLINE=1
509 endif
510
511 # With HTTPS support
512 ifdef FOSSIL_ENABLE_SSL
513 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -771,10 +771,11 @@
771 }
772
773
774 writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c"
775 set opt $SQLITE_OPTIONS
776 append opt " -D_HAVE_SQLITE_CONFIG_H"
777 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
778
779 set opt {}
780 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
781 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
@@ -973,10 +974,13 @@
974 SRCDIR = $B\src
975 OBJDIR = .
976 OX = .
977 O = .obj
978 E = .exe
979
980 # Uncomment to enable debug symbols
981 # DEBUG = 1
982
983 # Uncomment to enable JSON API
984 # FOSSIL_ENABLE_JSON = 1
985
986 # Uncomment to enable SSL support
@@ -987,37 +991,44 @@
991 SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
992 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
993 !endif
994
995 # zlib options
996 ZINCDIR = $(B)\compat\zlib
997 ZLIBDIR = $(B)\compat\zlib
998 ZLIB = zlib.lib
999
1000 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
1001
1002 !ifdef FOSSIL_ENABLE_SSL
1003 INCL = $(INCL) -I$(SSLINCDIR)
1004 !endif
1005
1006 CFLAGS = -nologo -MT -O2
1007 LDFLAGS = /NODEFAULTLIB:msvcrt
1008
1009 !ifdef DEBUG
1010 CFLAGS = $(CFLAGS) -Zi
1011 LDFLAGS = $(LDFLAGS) /DEBUG
1012 !endif
1013
1014 BCC = $(CC) $(CFLAGS)
1015 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
1016 RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
1017 LIBS = $(ZLIB) ws2_32.lib advapi32.lib
1018 LIBDIR = -LIBPATH:$(ZLIBDIR)
1019
1020 !ifdef FOSSIL_ENABLE_JSON
1021 TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
1022 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
1023 !endif
1024
1025 !ifdef FOSSIL_ENABLE_SSL
1026 TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
1027 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
1028 LIBS = $(LIBS) $(SSLLIB)
1029 LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
1030 !endif
1031 }
1032 regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS
1033 set j " \\\n "
1034 writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
@@ -1052,11 +1063,11 @@
1063 @echo Building zlib from "$(ZLIBDIR)"...
1064 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
1065
1066 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
1067 cd $(OX)
1068 link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
1069
1070 $(OX)\linkopts: $B\win\Makefile.msc}
1071 set redir {>}
1072 foreach s [lsort [concat $src $AdditionalObj]] {
1073 writeln "\techo \$(OX)\\$s.obj $redir \$@"
1074
+6 -6
--- src/manifest.c
+++ src/manifest.c
@@ -955,11 +955,11 @@
955955
956956
/*
957957
** Get a manifest given the rid for the control artifact. Return
958958
** a pointer to the manifest on success or NULL if there is a failure.
959959
*/
960
-Manifest *manifest_get(int rid, int cfType){
960
+Manifest *manifest_get(int rid, int cfType, Blob *pErr){
961961
Blob content;
962962
Manifest *p;
963963
if( !rid ) return 0;
964964
p = manifest_cache_find(rid);
965965
if( p ){
@@ -968,11 +968,11 @@
968968
p = 0;
969969
}
970970
return p;
971971
}
972972
content_get(rid, &content);
973
- p = manifest_parse(&content, rid, 0);
973
+ p = manifest_parse(&content, rid, pErr);
974974
if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){
975975
manifest_destroy(p);
976976
p = 0;
977977
}
978978
return p;
@@ -989,11 +989,11 @@
989989
rid = name_to_typed_rid(zName, "ci");
990990
if( !is_a_version(rid) ){
991991
fossil_fatal("no such checkin: %s", zName);
992992
}
993993
if( pRid ) *pRid = rid;
994
- p = manifest_get(rid, CFTYPE_MANIFEST);
994
+ p = manifest_get(rid, CFTYPE_MANIFEST, 0);
995995
if( p==0 ){
996996
fossil_fatal("cannot parse manifest for checkin: %s", zName);
997997
}
998998
return p;
999999
}
@@ -1036,11 +1036,11 @@
10361036
** and return 1 if throwError is false.
10371037
*/
10381038
static int fetch_baseline(Manifest *p, int throwError){
10391039
if( p->zBaseline!=0 && p->pBaseline==0 ){
10401040
int rid = uuid_to_rid(p->zBaseline, 1);
1041
- p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST);
1041
+ p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST, 0);
10421042
if( p->pBaseline==0 ){
10431043
if( !throwError ){
10441044
db_multi_exec(
10451045
"INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
10461046
p->rid, rid
@@ -1899,11 +1899,11 @@
18991899
|| !validate16(p->zAttachTarget, UUID_SIZE)
19001900
){
19011901
char *zComment;
19021902
if( p->zAttachSrc && p->zAttachSrc[0] ){
19031903
zComment = mprintf(
1904
- "Add attachment [%R/artifact/%S|%h] to wiki page [%h]",
1904
+ "Add attachment [/artifact/%S|%h] to wiki page [%h]",
19051905
p->zAttachSrc, p->zAttachName, p->zAttachTarget);
19061906
}else{
19071907
zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
19081908
p->zAttachName, p->zAttachTarget);
19091909
}
@@ -1915,11 +1915,11 @@
19151915
free(zComment);
19161916
}else{
19171917
char *zComment;
19181918
if( p->zAttachSrc && p->zAttachSrc[0] ){
19191919
zComment = mprintf(
1920
- "Add attachment [%R/artifact/%S|%h] to ticket [%S]",
1920
+ "Add attachment [/artifact/%S|%h] to ticket [%S]",
19211921
p->zAttachSrc, p->zAttachName, p->zAttachTarget);
19221922
}else{
19231923
zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]",
19241924
p->zAttachName, p->zAttachTarget);
19251925
}
19261926
--- src/manifest.c
+++ src/manifest.c
@@ -955,11 +955,11 @@
955
956 /*
957 ** Get a manifest given the rid for the control artifact. Return
958 ** a pointer to the manifest on success or NULL if there is a failure.
959 */
960 Manifest *manifest_get(int rid, int cfType){
961 Blob content;
962 Manifest *p;
963 if( !rid ) return 0;
964 p = manifest_cache_find(rid);
965 if( p ){
@@ -968,11 +968,11 @@
968 p = 0;
969 }
970 return p;
971 }
972 content_get(rid, &content);
973 p = manifest_parse(&content, rid, 0);
974 if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){
975 manifest_destroy(p);
976 p = 0;
977 }
978 return p;
@@ -989,11 +989,11 @@
989 rid = name_to_typed_rid(zName, "ci");
990 if( !is_a_version(rid) ){
991 fossil_fatal("no such checkin: %s", zName);
992 }
993 if( pRid ) *pRid = rid;
994 p = manifest_get(rid, CFTYPE_MANIFEST);
995 if( p==0 ){
996 fossil_fatal("cannot parse manifest for checkin: %s", zName);
997 }
998 return p;
999 }
@@ -1036,11 +1036,11 @@
1036 ** and return 1 if throwError is false.
1037 */
1038 static int fetch_baseline(Manifest *p, int throwError){
1039 if( p->zBaseline!=0 && p->pBaseline==0 ){
1040 int rid = uuid_to_rid(p->zBaseline, 1);
1041 p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST);
1042 if( p->pBaseline==0 ){
1043 if( !throwError ){
1044 db_multi_exec(
1045 "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
1046 p->rid, rid
@@ -1899,11 +1899,11 @@
1899 || !validate16(p->zAttachTarget, UUID_SIZE)
1900 ){
1901 char *zComment;
1902 if( p->zAttachSrc && p->zAttachSrc[0] ){
1903 zComment = mprintf(
1904 "Add attachment [%R/artifact/%S|%h] to wiki page [%h]",
1905 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
1906 }else{
1907 zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
1908 p->zAttachName, p->zAttachTarget);
1909 }
@@ -1915,11 +1915,11 @@
1915 free(zComment);
1916 }else{
1917 char *zComment;
1918 if( p->zAttachSrc && p->zAttachSrc[0] ){
1919 zComment = mprintf(
1920 "Add attachment [%R/artifact/%S|%h] to ticket [%S]",
1921 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
1922 }else{
1923 zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]",
1924 p->zAttachName, p->zAttachTarget);
1925 }
1926
--- src/manifest.c
+++ src/manifest.c
@@ -955,11 +955,11 @@
955
956 /*
957 ** Get a manifest given the rid for the control artifact. Return
958 ** a pointer to the manifest on success or NULL if there is a failure.
959 */
960 Manifest *manifest_get(int rid, int cfType, Blob *pErr){
961 Blob content;
962 Manifest *p;
963 if( !rid ) return 0;
964 p = manifest_cache_find(rid);
965 if( p ){
@@ -968,11 +968,11 @@
968 p = 0;
969 }
970 return p;
971 }
972 content_get(rid, &content);
973 p = manifest_parse(&content, rid, pErr);
974 if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){
975 manifest_destroy(p);
976 p = 0;
977 }
978 return p;
@@ -989,11 +989,11 @@
989 rid = name_to_typed_rid(zName, "ci");
990 if( !is_a_version(rid) ){
991 fossil_fatal("no such checkin: %s", zName);
992 }
993 if( pRid ) *pRid = rid;
994 p = manifest_get(rid, CFTYPE_MANIFEST, 0);
995 if( p==0 ){
996 fossil_fatal("cannot parse manifest for checkin: %s", zName);
997 }
998 return p;
999 }
@@ -1036,11 +1036,11 @@
1036 ** and return 1 if throwError is false.
1037 */
1038 static int fetch_baseline(Manifest *p, int throwError){
1039 if( p->zBaseline!=0 && p->pBaseline==0 ){
1040 int rid = uuid_to_rid(p->zBaseline, 1);
1041 p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST, 0);
1042 if( p->pBaseline==0 ){
1043 if( !throwError ){
1044 db_multi_exec(
1045 "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
1046 p->rid, rid
@@ -1899,11 +1899,11 @@
1899 || !validate16(p->zAttachTarget, UUID_SIZE)
1900 ){
1901 char *zComment;
1902 if( p->zAttachSrc && p->zAttachSrc[0] ){
1903 zComment = mprintf(
1904 "Add attachment [/artifact/%S|%h] to wiki page [%h]",
1905 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
1906 }else{
1907 zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
1908 p->zAttachName, p->zAttachTarget);
1909 }
@@ -1915,11 +1915,11 @@
1915 free(zComment);
1916 }else{
1917 char *zComment;
1918 if( p->zAttachSrc && p->zAttachSrc[0] ){
1919 zComment = mprintf(
1920 "Add attachment [/artifact/%S|%h] to ticket [%S]",
1921 p->zAttachSrc, p->zAttachName, p->zAttachTarget);
1922 }else{
1923 zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]",
1924 p->zAttachName, p->zAttachTarget);
1925 }
1926
+1
--- src/md5.c
+++ src/md5.c
@@ -16,10 +16,11 @@
1616
* To compute the message digest of a chunk of bytes, declare an
1717
* MD5Context structure, pass it to MD5Init, call MD5Update as
1818
* needed on buffers full of bytes, and then call MD5Final, which
1919
* will fill a supplied 16-byte array with the digest.
2020
*/
21
+#include "config.h"
2122
#include <string.h>
2223
#include <stdio.h>
2324
#include <sqlite3.h>
2425
#include "md5.h"
2526
2627
--- src/md5.c
+++ src/md5.c
@@ -16,10 +16,11 @@
16 * To compute the message digest of a chunk of bytes, declare an
17 * MD5Context structure, pass it to MD5Init, call MD5Update as
18 * needed on buffers full of bytes, and then call MD5Final, which
19 * will fill a supplied 16-byte array with the digest.
20 */
 
21 #include <string.h>
22 #include <stdio.h>
23 #include <sqlite3.h>
24 #include "md5.h"
25
26
--- src/md5.c
+++ src/md5.c
@@ -16,10 +16,11 @@
16 * To compute the message digest of a chunk of bytes, declare an
17 * MD5Context structure, pass it to MD5Init, call MD5Update as
18 * needed on buffers full of bytes, and then call MD5Final, which
19 * will fill a supplied 16-byte array with the digest.
20 */
21 #include "config.h"
22 #include <string.h>
23 #include <stdio.h>
24 #include <sqlite3.h>
25 #include "md5.h"
26
27
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
2727
** Print a fatal error and quit.
2828
*/
2929
static void win32_fatal_error(const char *zMsg){
3030
fossil_fatal("%s", zMsg);
3131
}
32
+#else
33
+#include <signal.h>
34
+#include <sys/wait.h>
3235
#endif
3336
3437
/*
3538
** The following macros are used to cast pointers to integers and
3639
** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
171174
close(pout[0]);
172175
close(pout[1]);
173176
*pChildPid = 0;
174177
return 1;
175178
}
179
+ signal(SIGPIPE,SIG_IGN);
176180
if( *pChildPid==0 ){
177181
int fd;
178182
int nErr = 0;
179183
/* This is the child process */
180184
close(0);
@@ -211,7 +215,8 @@
211215
fclose(pOut);
212216
#else
213217
close(fdIn);
214218
fclose(pOut);
215219
kill(childPid, SIGINT);
220
+ while( waitpid(0, 0, WNOHANG)>0 ) {}
216221
#endif
217222
}
218223
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
27 ** Print a fatal error and quit.
28 */
29 static void win32_fatal_error(const char *zMsg){
30 fossil_fatal("%s", zMsg);
31 }
 
 
 
32 #endif
33
34 /*
35 ** The following macros are used to cast pointers to integers and
36 ** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
171 close(pout[0]);
172 close(pout[1]);
173 *pChildPid = 0;
174 return 1;
175 }
 
176 if( *pChildPid==0 ){
177 int fd;
178 int nErr = 0;
179 /* This is the child process */
180 close(0);
@@ -211,7 +215,8 @@
211 fclose(pOut);
212 #else
213 close(fdIn);
214 fclose(pOut);
215 kill(childPid, SIGINT);
 
216 #endif
217 }
218
--- src/popen.c
+++ src/popen.c
@@ -27,10 +27,13 @@
27 ** Print a fatal error and quit.
28 */
29 static void win32_fatal_error(const char *zMsg){
30 fossil_fatal("%s", zMsg);
31 }
32 #else
33 #include <signal.h>
34 #include <sys/wait.h>
35 #endif
36
37 /*
38 ** The following macros are used to cast pointers to integers and
39 ** integers to pointers. The way you do this varies from one compiler
@@ -171,10 +174,11 @@
174 close(pout[0]);
175 close(pout[1]);
176 *pChildPid = 0;
177 return 1;
178 }
179 signal(SIGPIPE,SIG_IGN);
180 if( *pChildPid==0 ){
181 int fd;
182 int nErr = 0;
183 /* This is the child process */
184 close(0);
@@ -211,7 +215,8 @@
215 fclose(pOut);
216 #else
217 close(fdIn);
218 fclose(pOut);
219 kill(childPid, SIGINT);
220 while( waitpid(0, 0, WNOHANG)>0 ) {}
221 #endif
222 }
223
+2 -1
--- src/rebuild.c
+++ src/rebuild.c
@@ -349,10 +349,11 @@
349349
" WHERE type='table'"
350350
" AND name NOT IN ('blob','delta','rcvfrom','user',"
351351
"'config','shun','private','reportfmt',"
352352
"'concealed','accesslog','modreq')"
353353
" AND name NOT GLOB 'sqlite_*'"
354
+ " AND name NOT GLOB 'fx_*'"
354355
);
355356
if( zTable==0 ) break;
356357
db_multi_exec("DROP TABLE %Q", zTable);
357358
free(zTable);
358359
}
@@ -721,11 +722,11 @@
721722
Manifest *p;
722723
int rid = bag_first(&pending);
723724
int i;
724725
725726
bag_remove(&pending, rid);
726
- p = manifest_get(rid, CFTYPE_CLUSTER);
727
+ p = manifest_get(rid, CFTYPE_CLUSTER, 0);
727728
if( p==0 ){
728729
fossil_fatal("bad cluster: rid=%d", rid);
729730
}
730731
for(i=0; i<p->nCChild; i++){
731732
const char *zUuid = p->azCChild[i];
732733
--- src/rebuild.c
+++ src/rebuild.c
@@ -349,10 +349,11 @@
349 " WHERE type='table'"
350 " AND name NOT IN ('blob','delta','rcvfrom','user',"
351 "'config','shun','private','reportfmt',"
352 "'concealed','accesslog','modreq')"
353 " AND name NOT GLOB 'sqlite_*'"
 
354 );
355 if( zTable==0 ) break;
356 db_multi_exec("DROP TABLE %Q", zTable);
357 free(zTable);
358 }
@@ -721,11 +722,11 @@
721 Manifest *p;
722 int rid = bag_first(&pending);
723 int i;
724
725 bag_remove(&pending, rid);
726 p = manifest_get(rid, CFTYPE_CLUSTER);
727 if( p==0 ){
728 fossil_fatal("bad cluster: rid=%d", rid);
729 }
730 for(i=0; i<p->nCChild; i++){
731 const char *zUuid = p->azCChild[i];
732
--- src/rebuild.c
+++ src/rebuild.c
@@ -349,10 +349,11 @@
349 " WHERE type='table'"
350 " AND name NOT IN ('blob','delta','rcvfrom','user',"
351 "'config','shun','private','reportfmt',"
352 "'concealed','accesslog','modreq')"
353 " AND name NOT GLOB 'sqlite_*'"
354 " AND name NOT GLOB 'fx_*'"
355 );
356 if( zTable==0 ) break;
357 db_multi_exec("DROP TABLE %Q", zTable);
358 free(zTable);
359 }
@@ -721,11 +722,11 @@
722 Manifest *p;
723 int rid = bag_first(&pending);
724 int i;
725
726 bag_remove(&pending, rid);
727 p = manifest_get(rid, CFTYPE_CLUSTER, 0);
728 if( p==0 ){
729 fossil_fatal("bad cluster: rid=%d", rid);
730 }
731 for(i=0; i<p->nCChild; i++){
732 const char *zUuid = p->azCChild[i];
733
+3 -6
--- src/search.c
+++ src/search.c
@@ -189,12 +189,12 @@
189189
int iBest;
190190
char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
191191
off the end of the
192192
results. */
193193
char const * zLimit = find_option("limit","n",1);
194
- int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries
195
- to list */
194
+ int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching
195
+ lines/entries to list */
196196
197197
db_must_be_within_tree();
198198
if( g.argc<2 ) return;
199199
blob_init(&pattern, g.argv[2], -1);
200200
for(i=3; i<g.argc; i++){
@@ -220,13 +220,10 @@
220220
"WHERE 1 ", -1);
221221
if(!fAll){
222222
blob_appendf(&sql,"AND x>%d ", iBest/3);
223223
}
224224
blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
225
- if(nLimit>0){
226
- blob_appendf(&sql, "LIMIT %d", nLimit);
227
- }
228225
db_prepare(&q, blob_str(&sql));
229226
blob_reset(&sql);
230
- print_timeline(&q, 1000, 0);
227
+ print_timeline(&q, nLimit, 79, 0);
231228
db_finalize(&q);
232229
}
233230
--- src/search.c
+++ src/search.c
@@ -189,12 +189,12 @@
189 int iBest;
190 char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
191 off the end of the
192 results. */
193 char const * zLimit = find_option("limit","n",1);
194 int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries
195 to list */
196
197 db_must_be_within_tree();
198 if( g.argc<2 ) return;
199 blob_init(&pattern, g.argv[2], -1);
200 for(i=3; i<g.argc; i++){
@@ -220,13 +220,10 @@
220 "WHERE 1 ", -1);
221 if(!fAll){
222 blob_appendf(&sql,"AND x>%d ", iBest/3);
223 }
224 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
225 if(nLimit>0){
226 blob_appendf(&sql, "LIMIT %d", nLimit);
227 }
228 db_prepare(&q, blob_str(&sql));
229 blob_reset(&sql);
230 print_timeline(&q, 1000, 0);
231 db_finalize(&q);
232 }
233
--- src/search.c
+++ src/search.c
@@ -189,12 +189,12 @@
189 int iBest;
190 char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
191 off the end of the
192 results. */
193 char const * zLimit = find_option("limit","n",1);
194 int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching
195 lines/entries to list */
196
197 db_must_be_within_tree();
198 if( g.argc<2 ) return;
199 blob_init(&pattern, g.argv[2], -1);
200 for(i=3; i<g.argc; i++){
@@ -220,13 +220,10 @@
220 "WHERE 1 ", -1);
221 if(!fAll){
222 blob_appendf(&sql,"AND x>%d ", iBest/3);
223 }
224 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
 
 
 
225 db_prepare(&q, blob_str(&sql));
226 blob_reset(&sql);
227 print_timeline(&q, nLimit, 79, 0);
228 db_finalize(&q);
229 }
230
+53 -4
--- src/setup.c
+++ src/setup.c
@@ -15,12 +15,12 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** Implementation of the Setup page
1919
*/
20
-#include <assert.h>
2120
#include "config.h"
21
+#include <assert.h>
2222
#include "setup.h"
2323
2424
/*
2525
** The table of web pages supported by this application is generated
2626
** automatically by the "mkindex" program and written into a file
@@ -727,11 +727,11 @@
727727
@ capabilities of the <span class="usertype">nobody</span> user are
728728
@ inherited by all users, regardless of whether or not they are logged in.
729729
@ To disable universal access to the repository, make sure no user named
730730
@ <span class="usertype">nobody</span> exists or that the
731731
@ <span class="usertype">nobody</span> user has no capabilities
732
- @ enabled. The password for <span class="usertype">nobody</span> is ignore.
732
+ @ enabled. The password for <span class="usertype">nobody</span> is ignored.
733733
@ To avoid problems with spiders overloading the server, it is recommended
734734
@ that the <span class="capability">h</span> (Hyperlinks) capability be
735735
@ turned off for the <span class="usertype">nobody</span> user.
736736
@ </p></li>
737737
@
@@ -849,10 +849,37 @@
849849
if( zLabel && *zLabel ){
850850
@ <span class="textareaLabel">%s(zLabel)</span>
851851
}
852852
}
853853
}
854
+
855
+/*
856
+** Generate a text box for an attribute.
857
+*/
858
+static void multiple_choice_attribute(
859
+ const char *zLabel, /* The text label on the menu */
860
+ const char *zVar, /* The corresponding row in the VAR table */
861
+ const char *zQP, /* The query parameter */
862
+ const char *zDflt, /* Default value if VAR table entry does not exist */
863
+ int nChoice, /* Number of choices */
864
+ const char **azChoice /* Choices. 2 per choice: (VAR value, Display) */
865
+){
866
+ const char *z = db_get(zVar, (char*)zDflt);
867
+ const char *zQ = P(zQP);
868
+ int i;
869
+ if( zQ && fossil_strcmp(zQ,z)!=0){
870
+ login_verify_csrf_secret();
871
+ db_set(zVar, zQ, 0);
872
+ z = zQ;
873
+ }
874
+ @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
875
+ for(i=0; i<nChoice*2; i+=2){
876
+ const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
877
+ @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
878
+ }
879
+ @ </select>
880
+}
854881
855882
856883
/*
857884
** WEBPAGE: setup_access
858885
*/
@@ -1124,10 +1151,16 @@
11241151
** WEBPAGE: setup_timeline
11251152
*/
11261153
void setup_timeline(void){
11271154
double tmDiff;
11281155
char zTmDiff[20];
1156
+ static const char *azTimeFormats[] = {
1157
+ "0", "HH:MM",
1158
+ "1", "HH:MM:SS",
1159
+ "2", "YYYY-MM-DD HH:MM",
1160
+ "3", "YYMMDD HH:MM"
1161
+ };
11291162
login_check_credentials();
11301163
if( !g.perm.Setup ){
11311164
login_needed();
11321165
}
11331166
@@ -1167,10 +1200,18 @@
11671200
@ %s(zTmDiff) hours behind UTC.</p>
11681201
}else{
11691202
@ %s(zTmDiff) hours ahead of UTC.</p>
11701203
}
11711204
1205
+ @ <hr />
1206
+ multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", "tdf", "0",
1207
+ 4, azTimeFormats);
1208
+ @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown
1209
+ @ in a separate box (using CSS class "timelineDate") whenever the date changes.
1210
+ @ With the "YYYY-MM-DD&nbsp;HH:MM" and "YYMMDD ..." formats, the complete date
1211
+ @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p>
1212
+
11721213
@ <hr />
11731214
onoff_attribute("Show version differences by default",
11741215
"show-version-diffs", "vdiff", 0, 0);
11751216
@ <p>On the version-information pages linked from the timeline can either
11761217
@ show complete diffs of all file changes, or can just list the names of
@@ -1273,16 +1314,24 @@
12731314
@ <form action="%s(g.zTop)/setup_config" method="post"><div>
12741315
login_insert_csrf_secret();
12751316
@ <hr />
12761317
entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
12771318
@ <p>Give your project a name so visitors know what this site is about.
1278
- @ The project name will also be used as the RSS feed title.</p>
1319
+ @ The project name will also be used as the RSS feed title.
1320
+ @ </p>
12791321
@ <hr />
12801322
textarea_attribute("Project Description", 3, 80,
12811323
"project-description", "pd", "", 0);
12821324
@ <p>Describe your project. This will be used in page headers for search
12831325
@ engines as well as a short RSS description.</p>
1326
+ @ <hr />
1327
+ entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name", "spn", "", 0);
1328
+ @ <p>This is used as a prefix on the names of generated tarballs and ZIP archive.
1329
+ @ For best results, keep this prefix brief and avoid special characters such
1330
+ @ as "/" and "\".
1331
+ @ If no tarball prefix is specified, then the full Project Name above is used.
1332
+ @ </p>
12841333
@ <hr />
12851334
onoff_attribute("Enable WYSIWYG Wiki Editing",
12861335
"wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
12871336
@ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
12881337
@ The WYSIWYG editor generates HTML instead of markup, which makes
@@ -1488,11 +1537,11 @@
14881537
@ <p>When enabled, any change to tickets is subject to the approval
14891538
@ a ticket moderator - a user with the "q" or Mod-Tkt privilege.
14901539
@ Ticket changes enter the system and are shown locally, but are not
14911540
@ synced until they are approved. The moderator has the option to
14921541
@ delete the change rather than approve it. Ticket changes made by
1493
- @ a user who hwas the Mod-Tkt privilege are never subject to
1542
+ @ a user who has the Mod-Tkt privilege are never subject to
14941543
@ moderation.
14951544
@
14961545
@ <hr />
14971546
onoff_attribute("Moderate wiki changes",
14981547
"modreq-wiki", "modreq-wiki", 0, 0);
14991548
--- src/setup.c
+++ src/setup.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** Implementation of the Setup page
19 */
20 #include <assert.h>
21 #include "config.h"
 
22 #include "setup.h"
23
24 /*
25 ** The table of web pages supported by this application is generated
26 ** automatically by the "mkindex" program and written into a file
@@ -727,11 +727,11 @@
727 @ capabilities of the <span class="usertype">nobody</span> user are
728 @ inherited by all users, regardless of whether or not they are logged in.
729 @ To disable universal access to the repository, make sure no user named
730 @ <span class="usertype">nobody</span> exists or that the
731 @ <span class="usertype">nobody</span> user has no capabilities
732 @ enabled. The password for <span class="usertype">nobody</span> is ignore.
733 @ To avoid problems with spiders overloading the server, it is recommended
734 @ that the <span class="capability">h</span> (Hyperlinks) capability be
735 @ turned off for the <span class="usertype">nobody</span> user.
736 @ </p></li>
737 @
@@ -849,10 +849,37 @@
849 if( zLabel && *zLabel ){
850 @ <span class="textareaLabel">%s(zLabel)</span>
851 }
852 }
853 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
854
855
856 /*
857 ** WEBPAGE: setup_access
858 */
@@ -1124,10 +1151,16 @@
1124 ** WEBPAGE: setup_timeline
1125 */
1126 void setup_timeline(void){
1127 double tmDiff;
1128 char zTmDiff[20];
 
 
 
 
 
 
1129 login_check_credentials();
1130 if( !g.perm.Setup ){
1131 login_needed();
1132 }
1133
@@ -1167,10 +1200,18 @@
1167 @ %s(zTmDiff) hours behind UTC.</p>
1168 }else{
1169 @ %s(zTmDiff) hours ahead of UTC.</p>
1170 }
1171
 
 
 
 
 
 
 
 
1172 @ <hr />
1173 onoff_attribute("Show version differences by default",
1174 "show-version-diffs", "vdiff", 0, 0);
1175 @ <p>On the version-information pages linked from the timeline can either
1176 @ show complete diffs of all file changes, or can just list the names of
@@ -1273,16 +1314,24 @@
1273 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
1274 login_insert_csrf_secret();
1275 @ <hr />
1276 entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
1277 @ <p>Give your project a name so visitors know what this site is about.
1278 @ The project name will also be used as the RSS feed title.</p>
 
1279 @ <hr />
1280 textarea_attribute("Project Description", 3, 80,
1281 "project-description", "pd", "", 0);
1282 @ <p>Describe your project. This will be used in page headers for search
1283 @ engines as well as a short RSS description.</p>
 
 
 
 
 
 
 
1284 @ <hr />
1285 onoff_attribute("Enable WYSIWYG Wiki Editing",
1286 "wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
1287 @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
1288 @ The WYSIWYG editor generates HTML instead of markup, which makes
@@ -1488,11 +1537,11 @@
1488 @ <p>When enabled, any change to tickets is subject to the approval
1489 @ a ticket moderator - a user with the "q" or Mod-Tkt privilege.
1490 @ Ticket changes enter the system and are shown locally, but are not
1491 @ synced until they are approved. The moderator has the option to
1492 @ delete the change rather than approve it. Ticket changes made by
1493 @ a user who hwas the Mod-Tkt privilege are never subject to
1494 @ moderation.
1495 @
1496 @ <hr />
1497 onoff_attribute("Moderate wiki changes",
1498 "modreq-wiki", "modreq-wiki", 0, 0);
1499
--- src/setup.c
+++ src/setup.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** Implementation of the Setup page
19 */
 
20 #include "config.h"
21 #include <assert.h>
22 #include "setup.h"
23
24 /*
25 ** The table of web pages supported by this application is generated
26 ** automatically by the "mkindex" program and written into a file
@@ -727,11 +727,11 @@
727 @ capabilities of the <span class="usertype">nobody</span> user are
728 @ inherited by all users, regardless of whether or not they are logged in.
729 @ To disable universal access to the repository, make sure no user named
730 @ <span class="usertype">nobody</span> exists or that the
731 @ <span class="usertype">nobody</span> user has no capabilities
732 @ enabled. The password for <span class="usertype">nobody</span> is ignored.
733 @ To avoid problems with spiders overloading the server, it is recommended
734 @ that the <span class="capability">h</span> (Hyperlinks) capability be
735 @ turned off for the <span class="usertype">nobody</span> user.
736 @ </p></li>
737 @
@@ -849,10 +849,37 @@
849 if( zLabel && *zLabel ){
850 @ <span class="textareaLabel">%s(zLabel)</span>
851 }
852 }
853 }
854
855 /*
856 ** Generate a text box for an attribute.
857 */
858 static void multiple_choice_attribute(
859 const char *zLabel, /* The text label on the menu */
860 const char *zVar, /* The corresponding row in the VAR table */
861 const char *zQP, /* The query parameter */
862 const char *zDflt, /* Default value if VAR table entry does not exist */
863 int nChoice, /* Number of choices */
864 const char **azChoice /* Choices. 2 per choice: (VAR value, Display) */
865 ){
866 const char *z = db_get(zVar, (char*)zDflt);
867 const char *zQ = P(zQP);
868 int i;
869 if( zQ && fossil_strcmp(zQ,z)!=0){
870 login_verify_csrf_secret();
871 db_set(zVar, zQ, 0);
872 z = zQ;
873 }
874 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
875 for(i=0; i<nChoice*2; i+=2){
876 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
877 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
878 }
879 @ </select>
880 }
881
882
883 /*
884 ** WEBPAGE: setup_access
885 */
@@ -1124,10 +1151,16 @@
1151 ** WEBPAGE: setup_timeline
1152 */
1153 void setup_timeline(void){
1154 double tmDiff;
1155 char zTmDiff[20];
1156 static const char *azTimeFormats[] = {
1157 "0", "HH:MM",
1158 "1", "HH:MM:SS",
1159 "2", "YYYY-MM-DD HH:MM",
1160 "3", "YYMMDD HH:MM"
1161 };
1162 login_check_credentials();
1163 if( !g.perm.Setup ){
1164 login_needed();
1165 }
1166
@@ -1167,10 +1200,18 @@
1200 @ %s(zTmDiff) hours behind UTC.</p>
1201 }else{
1202 @ %s(zTmDiff) hours ahead of UTC.</p>
1203 }
1204
1205 @ <hr />
1206 multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", "tdf", "0",
1207 4, azTimeFormats);
1208 @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown
1209 @ in a separate box (using CSS class "timelineDate") whenever the date changes.
1210 @ With the "YYYY-MM-DD&nbsp;HH:MM" and "YYMMDD ..." formats, the complete date
1211 @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p>
1212
1213 @ <hr />
1214 onoff_attribute("Show version differences by default",
1215 "show-version-diffs", "vdiff", 0, 0);
1216 @ <p>On the version-information pages linked from the timeline can either
1217 @ show complete diffs of all file changes, or can just list the names of
@@ -1273,16 +1314,24 @@
1314 @ <form action="%s(g.zTop)/setup_config" method="post"><div>
1315 login_insert_csrf_secret();
1316 @ <hr />
1317 entry_attribute("Project Name", 60, "project-name", "pn", "", 0);
1318 @ <p>Give your project a name so visitors know what this site is about.
1319 @ The project name will also be used as the RSS feed title.
1320 @ </p>
1321 @ <hr />
1322 textarea_attribute("Project Description", 3, 80,
1323 "project-description", "pd", "", 0);
1324 @ <p>Describe your project. This will be used in page headers for search
1325 @ engines as well as a short RSS description.</p>
1326 @ <hr />
1327 entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name", "spn", "", 0);
1328 @ <p>This is used as a prefix on the names of generated tarballs and ZIP archive.
1329 @ For best results, keep this prefix brief and avoid special characters such
1330 @ as "/" and "\".
1331 @ If no tarball prefix is specified, then the full Project Name above is used.
1332 @ </p>
1333 @ <hr />
1334 onoff_attribute("Enable WYSIWYG Wiki Editing",
1335 "wysiwyg-wiki", "wysiwyg-wiki", 0, 0);
1336 @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages.
1337 @ The WYSIWYG editor generates HTML instead of markup, which makes
@@ -1488,11 +1537,11 @@
1537 @ <p>When enabled, any change to tickets is subject to the approval
1538 @ a ticket moderator - a user with the "q" or Mod-Tkt privilege.
1539 @ Ticket changes enter the system and are shown locally, but are not
1540 @ synced until they are approved. The moderator has the option to
1541 @ delete the change rather than approve it. Ticket changes made by
1542 @ a user who has the Mod-Tkt privilege are never subject to
1543 @ moderation.
1544 @
1545 @ <hr />
1546 onoff_attribute("Moderate wiki changes",
1547 "modreq-wiki", "modreq-wiki", 0, 0);
1548
+1 -1
--- src/sha1.c
+++ src/sha1.c
@@ -1,10 +1,10 @@
11
/*
22
** This implementation of SHA1.
33
*/
4
-#include <sys/types.h>
54
#include "config.h"
5
+#include <sys/types.h>
66
#include "sha1.h"
77
88
99
/*
1010
** The SHA1 implementation below is adapted from:
1111
--- src/sha1.c
+++ src/sha1.c
@@ -1,10 +1,10 @@
1 /*
2 ** This implementation of SHA1.
3 */
4 #include <sys/types.h>
5 #include "config.h"
 
6 #include "sha1.h"
7
8
9 /*
10 ** The SHA1 implementation below is adapted from:
11
--- src/sha1.c
+++ src/sha1.c
@@ -1,10 +1,10 @@
1 /*
2 ** This implementation of SHA1.
3 */
 
4 #include "config.h"
5 #include <sys/types.h>
6 #include "sha1.h"
7
8
9 /*
10 ** The SHA1 implementation below is adapted from:
11
+3 -3
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972972
int i;
973973
const char *z;
974974
rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975975
if( rc!=SQLITE_OK || !pSelect ){
976976
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977
- p->nErr++;
977
+ if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
978978
return rc;
979979
}
980980
rc = sqlite3_step(pSelect);
981981
nResult = sqlite3_column_count(pSelect);
982982
while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999999
rc = sqlite3_step(pSelect);
10001000
}
10011001
rc = sqlite3_finalize(pSelect);
10021002
if( rc!=SQLITE_OK ){
10031003
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004
- p->nErr++;
1004
+ if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
10051005
}
10061006
return rc;
10071007
}
10081008
10091009
/*
@@ -1202,11 +1202,11 @@
12021202
}
12031203
do{
12041204
/* extract the data and data types */
12051205
for(i=0; i<nCol; i++){
12061206
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
1207
- if( x==SQLITE_BLOB && pArg->mode==MODE_Insert ){
1207
+ if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){
12081208
azVals[i] = "";
12091209
}else{
12101210
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
12111211
}
12121212
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
12131213
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972 int i;
973 const char *z;
974 rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975 if( rc!=SQLITE_OK || !pSelect ){
976 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977 p->nErr++;
978 return rc;
979 }
980 rc = sqlite3_step(pSelect);
981 nResult = sqlite3_column_count(pSelect);
982 while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999 rc = sqlite3_step(pSelect);
1000 }
1001 rc = sqlite3_finalize(pSelect);
1002 if( rc!=SQLITE_OK ){
1003 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004 p->nErr++;
1005 }
1006 return rc;
1007 }
1008
1009 /*
@@ -1202,11 +1202,11 @@
1202 }
1203 do{
1204 /* extract the data and data types */
1205 for(i=0; i<nCol; i++){
1206 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
1207 if( x==SQLITE_BLOB && pArg->mode==MODE_Insert ){
1208 azVals[i] = "";
1209 }else{
1210 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
1211 }
1212 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
1213
--- src/shell.c
+++ src/shell.c
@@ -972,11 +972,11 @@
972 int i;
973 const char *z;
974 rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
975 if( rc!=SQLITE_OK || !pSelect ){
976 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
977 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
978 return rc;
979 }
980 rc = sqlite3_step(pSelect);
981 nResult = sqlite3_column_count(pSelect);
982 while( rc==SQLITE_ROW ){
@@ -999,11 +999,11 @@
999 rc = sqlite3_step(pSelect);
1000 }
1001 rc = sqlite3_finalize(pSelect);
1002 if( rc!=SQLITE_OK ){
1003 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1004 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1005 }
1006 return rc;
1007 }
1008
1009 /*
@@ -1202,11 +1202,11 @@
1202 }
1203 do{
1204 /* extract the data and data types */
1205 for(i=0; i<nCol; i++){
1206 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
1207 if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){
1208 azVals[i] = "";
1209 }else{
1210 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
1211 }
1212 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
1213
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -15,12 +15,12 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** Implementation of the Setup page for "skins".
1919
*/
20
-#include <assert.h>
2120
#include "config.h"
21
+#include <assert.h>
2222
#include "skins.h"
2323
2424
/* @-comment: ## */
2525
/*
2626
** A black-and-white theme with the project title in a bar across the top
2727
--- src/skins.c
+++ src/skins.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** Implementation of the Setup page for "skins".
19 */
20 #include <assert.h>
21 #include "config.h"
 
22 #include "skins.h"
23
24 /* @-comment: ## */
25 /*
26 ** A black-and-white theme with the project title in a bar across the top
27
--- src/skins.c
+++ src/skins.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** Implementation of the Setup page for "skins".
19 */
 
20 #include "config.h"
21 #include <assert.h>
22 #include "skins.h"
23
24 /* @-comment: ## */
25 /*
26 ** A black-and-white theme with the project title in a bar across the top
27
+2022 -1223
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -23,531 +23,10 @@
2323
# define SQLITE_PRIVATE static
2424
#endif
2525
#ifndef SQLITE_API
2626
# define SQLITE_API
2727
#endif
28
-/************** Begin file sqliteInt.h ***************************************/
29
-/*
30
-** 2001 September 15
31
-**
32
-** The author disclaims copyright to this source code. In place of
33
-** a legal notice, here is a blessing:
34
-**
35
-** May you do good and not evil.
36
-** May you find forgiveness for yourself and forgive others.
37
-** May you share freely, never taking more than you give.
38
-**
39
-*************************************************************************
40
-** Internal interface definitions for SQLite.
41
-**
42
-*/
43
-#ifndef _SQLITEINT_H_
44
-#define _SQLITEINT_H_
45
-
46
-/*
47
-** These #defines should enable >2GB file support on POSIX if the
48
-** underlying operating system supports it. If the OS lacks
49
-** large file support, or if the OS is windows, these should be no-ops.
50
-**
51
-** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
52
-** system #includes. Hence, this block of code must be the very first
53
-** code in all source files.
54
-**
55
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
56
-** on the compiler command line. This is necessary if you are compiling
57
-** on a recent machine (ex: Red Hat 7.2) but you want your code to work
58
-** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
59
-** without this option, LFS is enable. But LFS does not exist in the kernel
60
-** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
61
-** portability you should omit LFS.
62
-**
63
-** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
64
-*/
65
-#ifndef SQLITE_DISABLE_LFS
66
-# define _LARGE_FILE 1
67
-# ifndef _FILE_OFFSET_BITS
68
-# define _FILE_OFFSET_BITS 64
69
-# endif
70
-# define _LARGEFILE_SOURCE 1
71
-#endif
72
-
73
-/*
74
-** Include the configuration header output by 'configure' if we're using the
75
-** autoconf-based build
76
-*/
77
-#ifdef _HAVE_SQLITE_CONFIG_H
78
-#include "config.h"
79
-#endif
80
-
81
-/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
82
-/************** Begin file sqliteLimit.h *************************************/
83
-/*
84
-** 2007 May 7
85
-**
86
-** The author disclaims copyright to this source code. In place of
87
-** a legal notice, here is a blessing:
88
-**
89
-** May you do good and not evil.
90
-** May you find forgiveness for yourself and forgive others.
91
-** May you share freely, never taking more than you give.
92
-**
93
-*************************************************************************
94
-**
95
-** This file defines various limits of what SQLite can process.
96
-*/
97
-
98
-/*
99
-** The maximum length of a TEXT or BLOB in bytes. This also
100
-** limits the size of a row in a table or index.
101
-**
102
-** The hard limit is the ability of a 32-bit signed integer
103
-** to count the size: 2^31-1 or 2147483647.
104
-*/
105
-#ifndef SQLITE_MAX_LENGTH
106
-# define SQLITE_MAX_LENGTH 1000000000
107
-#endif
108
-
109
-/*
110
-** This is the maximum number of
111
-**
112
-** * Columns in a table
113
-** * Columns in an index
114
-** * Columns in a view
115
-** * Terms in the SET clause of an UPDATE statement
116
-** * Terms in the result set of a SELECT statement
117
-** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
118
-** * Terms in the VALUES clause of an INSERT statement
119
-**
120
-** The hard upper limit here is 32676. Most database people will
121
-** tell you that in a well-normalized database, you usually should
122
-** not have more than a dozen or so columns in any table. And if
123
-** that is the case, there is no point in having more than a few
124
-** dozen values in any of the other situations described above.
125
-*/
126
-#ifndef SQLITE_MAX_COLUMN
127
-# define SQLITE_MAX_COLUMN 2000
128
-#endif
129
-
130
-/*
131
-** The maximum length of a single SQL statement in bytes.
132
-**
133
-** It used to be the case that setting this value to zero would
134
-** turn the limit off. That is no longer true. It is not possible
135
-** to turn this limit off.
136
-*/
137
-#ifndef SQLITE_MAX_SQL_LENGTH
138
-# define SQLITE_MAX_SQL_LENGTH 1000000000
139
-#endif
140
-
141
-/*
142
-** The maximum depth of an expression tree. This is limited to
143
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
144
-** want to place more severe limits on the complexity of an
145
-** expression.
146
-**
147
-** A value of 0 used to mean that the limit was not enforced.
148
-** But that is no longer true. The limit is now strictly enforced
149
-** at all times.
150
-*/
151
-#ifndef SQLITE_MAX_EXPR_DEPTH
152
-# define SQLITE_MAX_EXPR_DEPTH 1000
153
-#endif
154
-
155
-/*
156
-** The maximum number of terms in a compound SELECT statement.
157
-** The code generator for compound SELECT statements does one
158
-** level of recursion for each term. A stack overflow can result
159
-** if the number of terms is too large. In practice, most SQL
160
-** never has more than 3 or 4 terms. Use a value of 0 to disable
161
-** any limit on the number of terms in a compount SELECT.
162
-*/
163
-#ifndef SQLITE_MAX_COMPOUND_SELECT
164
-# define SQLITE_MAX_COMPOUND_SELECT 500
165
-#endif
166
-
167
-/*
168
-** The maximum number of opcodes in a VDBE program.
169
-** Not currently enforced.
170
-*/
171
-#ifndef SQLITE_MAX_VDBE_OP
172
-# define SQLITE_MAX_VDBE_OP 25000
173
-#endif
174
-
175
-/*
176
-** The maximum number of arguments to an SQL function.
177
-*/
178
-#ifndef SQLITE_MAX_FUNCTION_ARG
179
-# define SQLITE_MAX_FUNCTION_ARG 127
180
-#endif
181
-
182
-/*
183
-** The maximum number of in-memory pages to use for the main database
184
-** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
185
-*/
186
-#ifndef SQLITE_DEFAULT_CACHE_SIZE
187
-# define SQLITE_DEFAULT_CACHE_SIZE 2000
188
-#endif
189
-#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
190
-# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
191
-#endif
192
-
193
-/*
194
-** The default number of frames to accumulate in the log file before
195
-** checkpointing the database in WAL mode.
196
-*/
197
-#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
198
-# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
199
-#endif
200
-
201
-/*
202
-** The maximum number of attached databases. This must be between 0
203
-** and 62. The upper bound on 62 is because a 64-bit integer bitmap
204
-** is used internally to track attached databases.
205
-*/
206
-#ifndef SQLITE_MAX_ATTACHED
207
-# define SQLITE_MAX_ATTACHED 10
208
-#endif
209
-
210
-
211
-/*
212
-** The maximum value of a ?nnn wildcard that the parser will accept.
213
-*/
214
-#ifndef SQLITE_MAX_VARIABLE_NUMBER
215
-# define SQLITE_MAX_VARIABLE_NUMBER 999
216
-#endif
217
-
218
-/* Maximum page size. The upper bound on this value is 65536. This a limit
219
-** imposed by the use of 16-bit offsets within each page.
220
-**
221
-** Earlier versions of SQLite allowed the user to change this value at
222
-** compile time. This is no longer permitted, on the grounds that it creates
223
-** a library that is technically incompatible with an SQLite library
224
-** compiled with a different limit. If a process operating on a database
225
-** with a page-size of 65536 bytes crashes, then an instance of SQLite
226
-** compiled with the default page-size limit will not be able to rollback
227
-** the aborted transaction. This could lead to database corruption.
228
-*/
229
-#ifdef SQLITE_MAX_PAGE_SIZE
230
-# undef SQLITE_MAX_PAGE_SIZE
231
-#endif
232
-#define SQLITE_MAX_PAGE_SIZE 65536
233
-
234
-
235
-/*
236
-** The default size of a database page.
237
-*/
238
-#ifndef SQLITE_DEFAULT_PAGE_SIZE
239
-# define SQLITE_DEFAULT_PAGE_SIZE 1024
240
-#endif
241
-#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
242
-# undef SQLITE_DEFAULT_PAGE_SIZE
243
-# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
244
-#endif
245
-
246
-/*
247
-** Ordinarily, if no value is explicitly provided, SQLite creates databases
248
-** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
249
-** device characteristics (sector-size and atomic write() support),
250
-** SQLite may choose a larger value. This constant is the maximum value
251
-** SQLite will choose on its own.
252
-*/
253
-#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
254
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
255
-#endif
256
-#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
257
-# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
258
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
259
-#endif
260
-
261
-
262
-/*
263
-** Maximum number of pages in one database file.
264
-**
265
-** This is really just the default value for the max_page_count pragma.
266
-** This value can be lowered (or raised) at run-time using that the
267
-** max_page_count macro.
268
-*/
269
-#ifndef SQLITE_MAX_PAGE_COUNT
270
-# define SQLITE_MAX_PAGE_COUNT 1073741823
271
-#endif
272
-
273
-/*
274
-** Maximum length (in bytes) of the pattern in a LIKE or GLOB
275
-** operator.
276
-*/
277
-#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
278
-# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
279
-#endif
280
-
281
-/*
282
-** Maximum depth of recursion for triggers.
283
-**
284
-** A value of 1 means that a trigger program will not be able to itself
285
-** fire any triggers. A value of 0 means that no trigger programs at all
286
-** may be executed.
287
-*/
288
-#ifndef SQLITE_MAX_TRIGGER_DEPTH
289
-# define SQLITE_MAX_TRIGGER_DEPTH 1000
290
-#endif
291
-
292
-/************** End of sqliteLimit.h *****************************************/
293
-/************** Continuing where we left off in sqliteInt.h ******************/
294
-
295
-/* Disable nuisance warnings on Borland compilers */
296
-#if defined(__BORLANDC__)
297
-#pragma warn -rch /* unreachable code */
298
-#pragma warn -ccc /* Condition is always true or false */
299
-#pragma warn -aus /* Assigned value is never used */
300
-#pragma warn -csu /* Comparing signed and unsigned */
301
-#pragma warn -spa /* Suspicious pointer arithmetic */
302
-#endif
303
-
304
-/* Needed for various definitions... */
305
-#ifndef _GNU_SOURCE
306
-# define _GNU_SOURCE
307
-#endif
308
-
309
-#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
310
-# define _BSD_SOURCE
311
-#endif
312
-
313
-/*
314
-** Include standard header files as necessary
315
-*/
316
-#ifdef HAVE_STDINT_H
317
-#include <stdint.h>
318
-#endif
319
-#ifdef HAVE_INTTYPES_H
320
-#include <inttypes.h>
321
-#endif
322
-
323
-/*
324
-** The following macros are used to cast pointers to integers and
325
-** integers to pointers. The way you do this varies from one compiler
326
-** to the next, so we have developed the following set of #if statements
327
-** to generate appropriate macros for a wide range of compilers.
328
-**
329
-** The correct "ANSI" way to do this is to use the intptr_t type.
330
-** Unfortunately, that typedef is not available on all compilers, or
331
-** if it is available, it requires an #include of specific headers
332
-** that vary from one machine to the next.
333
-**
334
-** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
335
-** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
336
-** So we have to define the macros in different ways depending on the
337
-** compiler.
338
-*/
339
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
340
-# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
341
-# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
342
-#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
343
-# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
344
-# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
345
-#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
346
-# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
347
-# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
348
-#else /* Generates a warning - but it always works */
349
-# define SQLITE_INT_TO_PTR(X) ((void*)(X))
350
-# define SQLITE_PTR_TO_INT(X) ((int)(X))
351
-#endif
352
-
353
-/*
354
-** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
355
-** 0 means mutexes are permanently disable and the library is never
356
-** threadsafe. 1 means the library is serialized which is the highest
357
-** level of threadsafety. 2 means the library is multithreaded - multiple
358
-** threads can use SQLite as long as no two threads try to use the same
359
-** database connection at the same time.
360
-**
361
-** Older versions of SQLite used an optional THREADSAFE macro.
362
-** We support that for legacy.
363
-*/
364
-#if !defined(SQLITE_THREADSAFE)
365
-# if defined(THREADSAFE)
366
-# define SQLITE_THREADSAFE THREADSAFE
367
-# else
368
-# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
369
-# endif
370
-#endif
371
-
372
-/*
373
-** Powersafe overwrite is on by default. But can be turned off using
374
-** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
375
-*/
376
-#ifndef SQLITE_POWERSAFE_OVERWRITE
377
-# define SQLITE_POWERSAFE_OVERWRITE 1
378
-#endif
379
-
380
-/*
381
-** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
382
-** It determines whether or not the features related to
383
-** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
384
-** be overridden at runtime using the sqlite3_config() API.
385
-*/
386
-#if !defined(SQLITE_DEFAULT_MEMSTATUS)
387
-# define SQLITE_DEFAULT_MEMSTATUS 1
388
-#endif
389
-
390
-/*
391
-** Exactly one of the following macros must be defined in order to
392
-** specify which memory allocation subsystem to use.
393
-**
394
-** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
395
-** SQLITE_WIN32_MALLOC // Use Win32 native heap API
396
-** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
397
-** SQLITE_MEMDEBUG // Debugging version of system malloc()
398
-**
399
-** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
400
-** assert() macro is enabled, each call into the Win32 native heap subsystem
401
-** will cause HeapValidate to be called. If heap validation should fail, an
402
-** assertion will be triggered.
403
-**
404
-** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
405
-** the default.
406
-*/
407
-#if defined(SQLITE_SYSTEM_MALLOC) \
408
- + defined(SQLITE_WIN32_MALLOC) \
409
- + defined(SQLITE_ZERO_MALLOC) \
410
- + defined(SQLITE_MEMDEBUG)>1
411
-# error "Two or more of the following compile-time configuration options\
412
- are defined but at most one is allowed:\
413
- SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
414
- SQLITE_ZERO_MALLOC"
415
-#endif
416
-#if defined(SQLITE_SYSTEM_MALLOC) \
417
- + defined(SQLITE_WIN32_MALLOC) \
418
- + defined(SQLITE_ZERO_MALLOC) \
419
- + defined(SQLITE_MEMDEBUG)==0
420
-# define SQLITE_SYSTEM_MALLOC 1
421
-#endif
422
-
423
-/*
424
-** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
425
-** sizes of memory allocations below this value where possible.
426
-*/
427
-#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
428
-# define SQLITE_MALLOC_SOFT_LIMIT 1024
429
-#endif
430
-
431
-/*
432
-** We need to define _XOPEN_SOURCE as follows in order to enable
433
-** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
434
-** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
435
-** it.
436
-*/
437
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
438
-# define _XOPEN_SOURCE 600
439
-#endif
440
-
441
-/*
442
-** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
443
-** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
444
-** make it true by defining or undefining NDEBUG.
445
-**
446
-** Setting NDEBUG makes the code smaller and faster by disabling the
447
-** assert() statements in the code. So we want the default action
448
-** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
449
-** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
450
-** feature.
451
-*/
452
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
453
-# define NDEBUG 1
454
-#endif
455
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
456
-# undef NDEBUG
457
-#endif
458
-
459
-/*
460
-** The testcase() macro is used to aid in coverage testing. When
461
-** doing coverage testing, the condition inside the argument to
462
-** testcase() must be evaluated both true and false in order to
463
-** get full branch coverage. The testcase() macro is inserted
464
-** to help ensure adequate test coverage in places where simple
465
-** condition/decision coverage is inadequate. For example, testcase()
466
-** can be used to make sure boundary values are tested. For
467
-** bitmask tests, testcase() can be used to make sure each bit
468
-** is significant and used at least once. On switch statements
469
-** where multiple cases go to the same block of code, testcase()
470
-** can insure that all cases are evaluated.
471
-**
472
-*/
473
-#ifdef SQLITE_COVERAGE_TEST
474
-SQLITE_PRIVATE void sqlite3Coverage(int);
475
-# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
476
-#else
477
-# define testcase(X)
478
-#endif
479
-
480
-/*
481
-** The TESTONLY macro is used to enclose variable declarations or
482
-** other bits of code that are needed to support the arguments
483
-** within testcase() and assert() macros.
484
-*/
485
-#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
486
-# define TESTONLY(X) X
487
-#else
488
-# define TESTONLY(X)
489
-#endif
490
-
491
-/*
492
-** Sometimes we need a small amount of code such as a variable initialization
493
-** to setup for a later assert() statement. We do not want this code to
494
-** appear when assert() is disabled. The following macro is therefore
495
-** used to contain that setup code. The "VVA" acronym stands for
496
-** "Verification, Validation, and Accreditation". In other words, the
497
-** code within VVA_ONLY() will only run during verification processes.
498
-*/
499
-#ifndef NDEBUG
500
-# define VVA_ONLY(X) X
501
-#else
502
-# define VVA_ONLY(X)
503
-#endif
504
-
505
-/*
506
-** The ALWAYS and NEVER macros surround boolean expressions which
507
-** are intended to always be true or false, respectively. Such
508
-** expressions could be omitted from the code completely. But they
509
-** are included in a few cases in order to enhance the resilience
510
-** of SQLite to unexpected behavior - to make the code "self-healing"
511
-** or "ductile" rather than being "brittle" and crashing at the first
512
-** hint of unplanned behavior.
513
-**
514
-** In other words, ALWAYS and NEVER are added for defensive code.
515
-**
516
-** When doing coverage testing ALWAYS and NEVER are hard-coded to
517
-** be true and false so that the unreachable code they specify will
518
-** not be counted as untested code.
519
-*/
520
-#if defined(SQLITE_COVERAGE_TEST)
521
-# define ALWAYS(X) (1)
522
-# define NEVER(X) (0)
523
-#elif !defined(NDEBUG)
524
-# define ALWAYS(X) ((X)?1:(assert(0),0))
525
-# define NEVER(X) ((X)?(assert(0),1):0)
526
-#else
527
-# define ALWAYS(X) (X)
528
-# define NEVER(X) (X)
529
-#endif
530
-
531
-/*
532
-** Return true (non-zero) if the input is a integer that is too large
533
-** to fit in 32-bits. This macro is used inside of various testcase()
534
-** macros to verify that we have tested SQLite for large-file support.
535
-*/
536
-#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
537
-
538
-/*
539
-** The macro unlikely() is a hint that surrounds a boolean
540
-** expression that is usually false. Macro likely() surrounds
541
-** a boolean expression that is usually true. These hints could,
542
-** in theory, be used by the compiler to generate better code, but
543
-** currently they are just comments for human readers.
544
-*/
545
-#define likely(X) (X)
546
-#define unlikely(X) (X)
547
-
548
-/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
54928
/************** Begin file sqlite3.h *****************************************/
55029
/*
55130
** 2001 September 15
55231
**
55332
** The author disclaims copyright to this source code. In place of
@@ -656,11 +135,11 @@
656135
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657136
** [sqlite_version()] and [sqlite_source_id()].
658137
*/
659138
#define SQLITE_VERSION "3.8.1"
660139
#define SQLITE_VERSION_NUMBER 3008001
661
-#define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
140
+#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a"
662141
663142
/*
664143
** CAPI3REF: Run-Time Library Version Numbers
665144
** KEYWORDS: sqlite3_version, sqlite3_sourceid
666145
**
@@ -2164,31 +1643,31 @@
21641643
** supplied by the application must not invoke any SQLite interface.
21651644
** In a multi-threaded application, the application-defined logger
21661645
** function must be threadsafe. </dd>
21671646
**
21681647
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
2169
-** <dd> This option takes a single argument of type int. If non-zero, then
1648
+** <dd>^(This option takes a single argument of type int. If non-zero, then
21701649
** URI handling is globally enabled. If the parameter is zero, then URI handling
2171
-** is globally disabled. If URI handling is globally enabled, all filenames
1650
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
21721651
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
21731652
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
21741653
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
2175
-** connection is opened. If it is globally disabled, filenames are
1654
+** connection is opened. ^If it is globally disabled, filenames are
21761655
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
2177
-** database connection is opened. By default, URI handling is globally
1656
+** database connection is opened. ^(By default, URI handling is globally
21781657
** disabled. The default value may be changed by compiling with the
2179
-** [SQLITE_USE_URI] symbol defined.
1658
+** [SQLITE_USE_URI] symbol defined.)^
21801659
**
21811660
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
2182
-** <dd> This option takes a single integer argument which is interpreted as
1661
+** <dd>^This option takes a single integer argument which is interpreted as
21831662
** a boolean in order to enable or disable the use of covering indices for
2184
-** full table scans in the query optimizer. The default setting is determined
1663
+** full table scans in the query optimizer. ^The default setting is determined
21851664
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
21861665
** if that compile-time option is omitted.
21871666
** The ability to disable the use of covering indices for full table scans
21881667
** is because some incorrectly coded legacy applications might malfunction
2189
-** malfunction when the optimization is enabled. Providing the ability to
1668
+** when the optimization is enabled. Providing the ability to
21901669
** disable the optimization allows the older, buggy application code to work
21911670
** without change even with newer versions of SQLite.
21921671
**
21931672
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
21941673
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -2213,20 +1692,20 @@
22131692
** configuration option can be seen in the "test_sqllog.c" source file in
22141693
** the canonical SQLite source tree.</dd>
22151694
**
22161695
** [[SQLITE_CONFIG_MMAP_SIZE]]
22171696
** <dt>SQLITE_CONFIG_MMAP_SIZE
2218
-** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
1697
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
22191698
** that are the default mmap size limit (the default setting for
22201699
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
2221
-** The default setting can be overridden by each database connection using
1700
+** ^The default setting can be overridden by each database connection using
22221701
** either the [PRAGMA mmap_size] command, or by using the
2223
-** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
1702
+** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
22241703
** cannot be changed at run-time. Nor may the maximum allowed mmap size
22251704
** exceed the compile-time maximum mmap size set by the
2226
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.
2227
-** If either argument to this option is negative, then that argument is
1705
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
1706
+** ^If either argument to this option is negative, then that argument is
22281707
** changed to its compile-time default.
22291708
** </dl>
22301709
*/
22311710
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
22321711
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
@@ -7846,11 +7325,530 @@
78467325
78477326
#endif /* ifndef _SQLITE3RTREE_H_ */
78487327
78497328
78507329
/************** End of sqlite3.h *********************************************/
7330
+/************** Begin file sqliteInt.h ***************************************/
7331
+/*
7332
+** 2001 September 15
7333
+**
7334
+** The author disclaims copyright to this source code. In place of
7335
+** a legal notice, here is a blessing:
7336
+**
7337
+** May you do good and not evil.
7338
+** May you find forgiveness for yourself and forgive others.
7339
+** May you share freely, never taking more than you give.
7340
+**
7341
+*************************************************************************
7342
+** Internal interface definitions for SQLite.
7343
+**
7344
+*/
7345
+#ifndef _SQLITEINT_H_
7346
+#define _SQLITEINT_H_
7347
+
7348
+/*
7349
+** These #defines should enable >2GB file support on POSIX if the
7350
+** underlying operating system supports it. If the OS lacks
7351
+** large file support, or if the OS is windows, these should be no-ops.
7352
+**
7353
+** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
7354
+** system #includes. Hence, this block of code must be the very first
7355
+** code in all source files.
7356
+**
7357
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
7358
+** on the compiler command line. This is necessary if you are compiling
7359
+** on a recent machine (ex: Red Hat 7.2) but you want your code to work
7360
+** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
7361
+** without this option, LFS is enable. But LFS does not exist in the kernel
7362
+** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
7363
+** portability you should omit LFS.
7364
+**
7365
+** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
7366
+*/
7367
+#ifndef SQLITE_DISABLE_LFS
7368
+# define _LARGE_FILE 1
7369
+# ifndef _FILE_OFFSET_BITS
7370
+# define _FILE_OFFSET_BITS 64
7371
+# endif
7372
+# define _LARGEFILE_SOURCE 1
7373
+#endif
7374
+
7375
+/*
7376
+** Include the configuration header output by 'configure' if we're using the
7377
+** autoconf-based build
7378
+*/
7379
+#ifdef _HAVE_SQLITE_CONFIG_H
7380
+#include "config.h"
7381
+#endif
7382
+
7383
+/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
7384
+/************** Begin file sqliteLimit.h *************************************/
7385
+/*
7386
+** 2007 May 7
7387
+**
7388
+** The author disclaims copyright to this source code. In place of
7389
+** a legal notice, here is a blessing:
7390
+**
7391
+** May you do good and not evil.
7392
+** May you find forgiveness for yourself and forgive others.
7393
+** May you share freely, never taking more than you give.
7394
+**
7395
+*************************************************************************
7396
+**
7397
+** This file defines various limits of what SQLite can process.
7398
+*/
7399
+
7400
+/*
7401
+** The maximum length of a TEXT or BLOB in bytes. This also
7402
+** limits the size of a row in a table or index.
7403
+**
7404
+** The hard limit is the ability of a 32-bit signed integer
7405
+** to count the size: 2^31-1 or 2147483647.
7406
+*/
7407
+#ifndef SQLITE_MAX_LENGTH
7408
+# define SQLITE_MAX_LENGTH 1000000000
7409
+#endif
7410
+
7411
+/*
7412
+** This is the maximum number of
7413
+**
7414
+** * Columns in a table
7415
+** * Columns in an index
7416
+** * Columns in a view
7417
+** * Terms in the SET clause of an UPDATE statement
7418
+** * Terms in the result set of a SELECT statement
7419
+** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
7420
+** * Terms in the VALUES clause of an INSERT statement
7421
+**
7422
+** The hard upper limit here is 32676. Most database people will
7423
+** tell you that in a well-normalized database, you usually should
7424
+** not have more than a dozen or so columns in any table. And if
7425
+** that is the case, there is no point in having more than a few
7426
+** dozen values in any of the other situations described above.
7427
+*/
7428
+#ifndef SQLITE_MAX_COLUMN
7429
+# define SQLITE_MAX_COLUMN 2000
7430
+#endif
7431
+
7432
+/*
7433
+** The maximum length of a single SQL statement in bytes.
7434
+**
7435
+** It used to be the case that setting this value to zero would
7436
+** turn the limit off. That is no longer true. It is not possible
7437
+** to turn this limit off.
7438
+*/
7439
+#ifndef SQLITE_MAX_SQL_LENGTH
7440
+# define SQLITE_MAX_SQL_LENGTH 1000000000
7441
+#endif
7442
+
7443
+/*
7444
+** The maximum depth of an expression tree. This is limited to
7445
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
7446
+** want to place more severe limits on the complexity of an
7447
+** expression.
7448
+**
7449
+** A value of 0 used to mean that the limit was not enforced.
7450
+** But that is no longer true. The limit is now strictly enforced
7451
+** at all times.
7452
+*/
7453
+#ifndef SQLITE_MAX_EXPR_DEPTH
7454
+# define SQLITE_MAX_EXPR_DEPTH 1000
7455
+#endif
7456
+
7457
+/*
7458
+** The maximum number of terms in a compound SELECT statement.
7459
+** The code generator for compound SELECT statements does one
7460
+** level of recursion for each term. A stack overflow can result
7461
+** if the number of terms is too large. In practice, most SQL
7462
+** never has more than 3 or 4 terms. Use a value of 0 to disable
7463
+** any limit on the number of terms in a compount SELECT.
7464
+*/
7465
+#ifndef SQLITE_MAX_COMPOUND_SELECT
7466
+# define SQLITE_MAX_COMPOUND_SELECT 500
7467
+#endif
7468
+
7469
+/*
7470
+** The maximum number of opcodes in a VDBE program.
7471
+** Not currently enforced.
7472
+*/
7473
+#ifndef SQLITE_MAX_VDBE_OP
7474
+# define SQLITE_MAX_VDBE_OP 25000
7475
+#endif
7476
+
7477
+/*
7478
+** The maximum number of arguments to an SQL function.
7479
+*/
7480
+#ifndef SQLITE_MAX_FUNCTION_ARG
7481
+# define SQLITE_MAX_FUNCTION_ARG 127
7482
+#endif
7483
+
7484
+/*
7485
+** The maximum number of in-memory pages to use for the main database
7486
+** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
7487
+*/
7488
+#ifndef SQLITE_DEFAULT_CACHE_SIZE
7489
+# define SQLITE_DEFAULT_CACHE_SIZE 2000
7490
+#endif
7491
+#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
7492
+# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
7493
+#endif
7494
+
7495
+/*
7496
+** The default number of frames to accumulate in the log file before
7497
+** checkpointing the database in WAL mode.
7498
+*/
7499
+#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
7500
+# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
7501
+#endif
7502
+
7503
+/*
7504
+** The maximum number of attached databases. This must be between 0
7505
+** and 62. The upper bound on 62 is because a 64-bit integer bitmap
7506
+** is used internally to track attached databases.
7507
+*/
7508
+#ifndef SQLITE_MAX_ATTACHED
7509
+# define SQLITE_MAX_ATTACHED 10
7510
+#endif
7511
+
7512
+
7513
+/*
7514
+** The maximum value of a ?nnn wildcard that the parser will accept.
7515
+*/
7516
+#ifndef SQLITE_MAX_VARIABLE_NUMBER
7517
+# define SQLITE_MAX_VARIABLE_NUMBER 999
7518
+#endif
7519
+
7520
+/* Maximum page size. The upper bound on this value is 65536. This a limit
7521
+** imposed by the use of 16-bit offsets within each page.
7522
+**
7523
+** Earlier versions of SQLite allowed the user to change this value at
7524
+** compile time. This is no longer permitted, on the grounds that it creates
7525
+** a library that is technically incompatible with an SQLite library
7526
+** compiled with a different limit. If a process operating on a database
7527
+** with a page-size of 65536 bytes crashes, then an instance of SQLite
7528
+** compiled with the default page-size limit will not be able to rollback
7529
+** the aborted transaction. This could lead to database corruption.
7530
+*/
7531
+#ifdef SQLITE_MAX_PAGE_SIZE
7532
+# undef SQLITE_MAX_PAGE_SIZE
7533
+#endif
7534
+#define SQLITE_MAX_PAGE_SIZE 65536
7535
+
7536
+
7537
+/*
7538
+** The default size of a database page.
7539
+*/
7540
+#ifndef SQLITE_DEFAULT_PAGE_SIZE
7541
+# define SQLITE_DEFAULT_PAGE_SIZE 1024
7542
+#endif
7543
+#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
7544
+# undef SQLITE_DEFAULT_PAGE_SIZE
7545
+# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
7546
+#endif
7547
+
7548
+/*
7549
+** Ordinarily, if no value is explicitly provided, SQLite creates databases
7550
+** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
7551
+** device characteristics (sector-size and atomic write() support),
7552
+** SQLite may choose a larger value. This constant is the maximum value
7553
+** SQLite will choose on its own.
7554
+*/
7555
+#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
7556
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
7557
+#endif
7558
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
7559
+# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
7560
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
7561
+#endif
7562
+
7563
+
7564
+/*
7565
+** Maximum number of pages in one database file.
7566
+**
7567
+** This is really just the default value for the max_page_count pragma.
7568
+** This value can be lowered (or raised) at run-time using that the
7569
+** max_page_count macro.
7570
+*/
7571
+#ifndef SQLITE_MAX_PAGE_COUNT
7572
+# define SQLITE_MAX_PAGE_COUNT 1073741823
7573
+#endif
7574
+
7575
+/*
7576
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
7577
+** operator.
7578
+*/
7579
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
7580
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
7581
+#endif
7582
+
7583
+/*
7584
+** Maximum depth of recursion for triggers.
7585
+**
7586
+** A value of 1 means that a trigger program will not be able to itself
7587
+** fire any triggers. A value of 0 means that no trigger programs at all
7588
+** may be executed.
7589
+*/
7590
+#ifndef SQLITE_MAX_TRIGGER_DEPTH
7591
+# define SQLITE_MAX_TRIGGER_DEPTH 1000
7592
+#endif
7593
+
7594
+/************** End of sqliteLimit.h *****************************************/
78517595
/************** Continuing where we left off in sqliteInt.h ******************/
7596
+
7597
+/* Disable nuisance warnings on Borland compilers */
7598
+#if defined(__BORLANDC__)
7599
+#pragma warn -rch /* unreachable code */
7600
+#pragma warn -ccc /* Condition is always true or false */
7601
+#pragma warn -aus /* Assigned value is never used */
7602
+#pragma warn -csu /* Comparing signed and unsigned */
7603
+#pragma warn -spa /* Suspicious pointer arithmetic */
7604
+#endif
7605
+
7606
+/* Needed for various definitions... */
7607
+#ifndef _GNU_SOURCE
7608
+# define _GNU_SOURCE
7609
+#endif
7610
+
7611
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
7612
+# define _BSD_SOURCE
7613
+#endif
7614
+
7615
+/*
7616
+** Include standard header files as necessary
7617
+*/
7618
+#ifdef HAVE_STDINT_H
7619
+#include <stdint.h>
7620
+#endif
7621
+#ifdef HAVE_INTTYPES_H
7622
+#include <inttypes.h>
7623
+#endif
7624
+
7625
+/*
7626
+** The following macros are used to cast pointers to integers and
7627
+** integers to pointers. The way you do this varies from one compiler
7628
+** to the next, so we have developed the following set of #if statements
7629
+** to generate appropriate macros for a wide range of compilers.
7630
+**
7631
+** The correct "ANSI" way to do this is to use the intptr_t type.
7632
+** Unfortunately, that typedef is not available on all compilers, or
7633
+** if it is available, it requires an #include of specific headers
7634
+** that vary from one machine to the next.
7635
+**
7636
+** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
7637
+** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
7638
+** So we have to define the macros in different ways depending on the
7639
+** compiler.
7640
+*/
7641
+#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
7642
+# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
7643
+# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
7644
+#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
7645
+# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
7646
+# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
7647
+#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
7648
+# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
7649
+# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
7650
+#else /* Generates a warning - but it always works */
7651
+# define SQLITE_INT_TO_PTR(X) ((void*)(X))
7652
+# define SQLITE_PTR_TO_INT(X) ((int)(X))
7653
+#endif
7654
+
7655
+/*
7656
+** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
7657
+** 0 means mutexes are permanently disable and the library is never
7658
+** threadsafe. 1 means the library is serialized which is the highest
7659
+** level of threadsafety. 2 means the library is multithreaded - multiple
7660
+** threads can use SQLite as long as no two threads try to use the same
7661
+** database connection at the same time.
7662
+**
7663
+** Older versions of SQLite used an optional THREADSAFE macro.
7664
+** We support that for legacy.
7665
+*/
7666
+#if !defined(SQLITE_THREADSAFE)
7667
+# if defined(THREADSAFE)
7668
+# define SQLITE_THREADSAFE THREADSAFE
7669
+# else
7670
+# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
7671
+# endif
7672
+#endif
7673
+
7674
+/*
7675
+** Powersafe overwrite is on by default. But can be turned off using
7676
+** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
7677
+*/
7678
+#ifndef SQLITE_POWERSAFE_OVERWRITE
7679
+# define SQLITE_POWERSAFE_OVERWRITE 1
7680
+#endif
7681
+
7682
+/*
7683
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
7684
+** It determines whether or not the features related to
7685
+** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
7686
+** be overridden at runtime using the sqlite3_config() API.
7687
+*/
7688
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
7689
+# define SQLITE_DEFAULT_MEMSTATUS 1
7690
+#endif
7691
+
7692
+/*
7693
+** Exactly one of the following macros must be defined in order to
7694
+** specify which memory allocation subsystem to use.
7695
+**
7696
+** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
7697
+** SQLITE_WIN32_MALLOC // Use Win32 native heap API
7698
+** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
7699
+** SQLITE_MEMDEBUG // Debugging version of system malloc()
7700
+**
7701
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
7702
+** assert() macro is enabled, each call into the Win32 native heap subsystem
7703
+** will cause HeapValidate to be called. If heap validation should fail, an
7704
+** assertion will be triggered.
7705
+**
7706
+** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
7707
+** the default.
7708
+*/
7709
+#if defined(SQLITE_SYSTEM_MALLOC) \
7710
+ + defined(SQLITE_WIN32_MALLOC) \
7711
+ + defined(SQLITE_ZERO_MALLOC) \
7712
+ + defined(SQLITE_MEMDEBUG)>1
7713
+# error "Two or more of the following compile-time configuration options\
7714
+ are defined but at most one is allowed:\
7715
+ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
7716
+ SQLITE_ZERO_MALLOC"
7717
+#endif
7718
+#if defined(SQLITE_SYSTEM_MALLOC) \
7719
+ + defined(SQLITE_WIN32_MALLOC) \
7720
+ + defined(SQLITE_ZERO_MALLOC) \
7721
+ + defined(SQLITE_MEMDEBUG)==0
7722
+# define SQLITE_SYSTEM_MALLOC 1
7723
+#endif
7724
+
7725
+/*
7726
+** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
7727
+** sizes of memory allocations below this value where possible.
7728
+*/
7729
+#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
7730
+# define SQLITE_MALLOC_SOFT_LIMIT 1024
7731
+#endif
7732
+
7733
+/*
7734
+** We need to define _XOPEN_SOURCE as follows in order to enable
7735
+** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
7736
+** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
7737
+** it.
7738
+*/
7739
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
7740
+# define _XOPEN_SOURCE 600
7741
+#endif
7742
+
7743
+/*
7744
+** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
7745
+** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
7746
+** make it true by defining or undefining NDEBUG.
7747
+**
7748
+** Setting NDEBUG makes the code smaller and faster by disabling the
7749
+** assert() statements in the code. So we want the default action
7750
+** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
7751
+** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
7752
+** feature.
7753
+*/
7754
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
7755
+# define NDEBUG 1
7756
+#endif
7757
+#if defined(NDEBUG) && defined(SQLITE_DEBUG)
7758
+# undef NDEBUG
7759
+#endif
7760
+
7761
+/*
7762
+** The testcase() macro is used to aid in coverage testing. When
7763
+** doing coverage testing, the condition inside the argument to
7764
+** testcase() must be evaluated both true and false in order to
7765
+** get full branch coverage. The testcase() macro is inserted
7766
+** to help ensure adequate test coverage in places where simple
7767
+** condition/decision coverage is inadequate. For example, testcase()
7768
+** can be used to make sure boundary values are tested. For
7769
+** bitmask tests, testcase() can be used to make sure each bit
7770
+** is significant and used at least once. On switch statements
7771
+** where multiple cases go to the same block of code, testcase()
7772
+** can insure that all cases are evaluated.
7773
+**
7774
+*/
7775
+#ifdef SQLITE_COVERAGE_TEST
7776
+SQLITE_PRIVATE void sqlite3Coverage(int);
7777
+# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
7778
+#else
7779
+# define testcase(X)
7780
+#endif
7781
+
7782
+/*
7783
+** The TESTONLY macro is used to enclose variable declarations or
7784
+** other bits of code that are needed to support the arguments
7785
+** within testcase() and assert() macros.
7786
+*/
7787
+#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
7788
+# define TESTONLY(X) X
7789
+#else
7790
+# define TESTONLY(X)
7791
+#endif
7792
+
7793
+/*
7794
+** Sometimes we need a small amount of code such as a variable initialization
7795
+** to setup for a later assert() statement. We do not want this code to
7796
+** appear when assert() is disabled. The following macro is therefore
7797
+** used to contain that setup code. The "VVA" acronym stands for
7798
+** "Verification, Validation, and Accreditation". In other words, the
7799
+** code within VVA_ONLY() will only run during verification processes.
7800
+*/
7801
+#ifndef NDEBUG
7802
+# define VVA_ONLY(X) X
7803
+#else
7804
+# define VVA_ONLY(X)
7805
+#endif
7806
+
7807
+/*
7808
+** The ALWAYS and NEVER macros surround boolean expressions which
7809
+** are intended to always be true or false, respectively. Such
7810
+** expressions could be omitted from the code completely. But they
7811
+** are included in a few cases in order to enhance the resilience
7812
+** of SQLite to unexpected behavior - to make the code "self-healing"
7813
+** or "ductile" rather than being "brittle" and crashing at the first
7814
+** hint of unplanned behavior.
7815
+**
7816
+** In other words, ALWAYS and NEVER are added for defensive code.
7817
+**
7818
+** When doing coverage testing ALWAYS and NEVER are hard-coded to
7819
+** be true and false so that the unreachable code they specify will
7820
+** not be counted as untested code.
7821
+*/
7822
+#if defined(SQLITE_COVERAGE_TEST)
7823
+# define ALWAYS(X) (1)
7824
+# define NEVER(X) (0)
7825
+#elif !defined(NDEBUG)
7826
+# define ALWAYS(X) ((X)?1:(assert(0),0))
7827
+# define NEVER(X) ((X)?(assert(0),1):0)
7828
+#else
7829
+# define ALWAYS(X) (X)
7830
+# define NEVER(X) (X)
7831
+#endif
7832
+
7833
+/*
7834
+** Return true (non-zero) if the input is a integer that is too large
7835
+** to fit in 32-bits. This macro is used inside of various testcase()
7836
+** macros to verify that we have tested SQLite for large-file support.
7837
+*/
7838
+#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
7839
+
7840
+/*
7841
+** The macro unlikely() is a hint that surrounds a boolean
7842
+** expression that is usually false. Macro likely() surrounds
7843
+** a boolean expression that is usually true. These hints could,
7844
+** in theory, be used by the compiler to generate better code, but
7845
+** currently they are just comments for human readers.
7846
+*/
7847
+#define likely(X) (X)
7848
+#define unlikely(X) (X)
7849
+
78527850
/************** Include hash.h in the middle of sqliteInt.h ******************/
78537851
/************** Begin file hash.h ********************************************/
78547852
/*
78557853
** 2001 September 22
78567854
**
@@ -8272,10 +8270,35 @@
82728270
typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
82738271
#else
82748272
typedef u32 tRowcnt; /* 32-bit is the default */
82758273
#endif
82768274
8275
+/*
8276
+** Estimated quantities used for query planning are stored as 16-bit
8277
+** logarithms. For quantity X, the value stored is 10*log2(X). This
8278
+** gives a possible range of values of approximately 1.0e986 to 1e-986.
8279
+** But the allowed values are "grainy". Not every value is representable.
8280
+** For example, quantities 16 and 17 are both represented by a LogEst
8281
+** of 40. However, since LogEst quantatites are suppose to be estimates,
8282
+** not exact values, this imprecision is not a problem.
8283
+**
8284
+** "LogEst" is short for "Logarithimic Estimate".
8285
+**
8286
+** Examples:
8287
+** 1 -> 0 20 -> 43 10000 -> 132
8288
+** 2 -> 10 25 -> 46 25000 -> 146
8289
+** 3 -> 16 100 -> 66 1000000 -> 199
8290
+** 4 -> 20 1000 -> 99 1048576 -> 200
8291
+** 10 -> 33 1024 -> 100 4294967296 -> 320
8292
+**
8293
+** The LogEst can be negative to indicate fractional values.
8294
+** Examples:
8295
+**
8296
+** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
8297
+*/
8298
+typedef INT16_TYPE LogEst;
8299
+
82778300
/*
82788301
** Macros to determine whether the machine is big or little endian,
82798302
** evaluated at runtime.
82808303
*/
82818304
#ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10442,12 @@
1041910442
char *zDflt; /* Original text of the default value */
1042010443
char *zType; /* Data type for this column */
1042110444
char *zColl; /* Collating sequence. If NULL, use the default */
1042210445
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
1042310446
char affinity; /* One of the SQLITE_AFF_... values */
10424
- u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
10447
+ u8 szEst; /* Estimated size of this column. INT==1 */
10448
+ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
1042510449
};
1042610450
1042710451
/* Allowed values for Column.colFlags:
1042810452
*/
1042910453
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10607,11 @@
1058310607
tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
1058410608
int tnum; /* Root BTree node for this table (see note above) */
1058510609
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
1058610610
i16 nCol; /* Number of columns in this table */
1058710611
u16 nRef; /* Number of pointers to this Table */
10612
+ LogEst szTabRow; /* Estimated size of each table row in bytes */
1058810613
u8 tabFlags; /* Mask of TF_* values */
1058910614
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
1059010615
#ifndef SQLITE_OMIT_ALTERTABLE
1059110616
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
1059210617
#endif
@@ -10694,11 +10719,11 @@
1069410719
#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
1069510720
#define OE_SetNull 7 /* Set the foreign key value to NULL */
1069610721
#define OE_SetDflt 8 /* Set the foreign key value to its default */
1069710722
#define OE_Cascade 9 /* Cascade the changes */
1069810723
10699
-#define OE_Default 99 /* Do whatever the default action is */
10724
+#define OE_Default 10 /* Do whatever the default action is */
1070010725
1070110726
1070210727
/*
1070310728
** An instance of the following structure is passed as the first
1070410729
** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10806,11 @@
1078110806
Schema *pSchema; /* Schema containing this index */
1078210807
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
1078310808
char **azColl; /* Array of collation sequence names for index */
1078410809
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
1078510810
int tnum; /* DB Page containing root of this index */
10811
+ LogEst szIdxRow; /* Estimated average row size in bytes */
1078610812
u16 nColumn; /* Number of columns in table used by this index */
1078710813
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
1078810814
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
1078910815
unsigned bUnordered:1; /* Use this index for == or IN queries only */
1079010816
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11662,11 @@
1163611662
*/
1163711663
typedef struct DbFixer DbFixer;
1163811664
struct DbFixer {
1163911665
Parse *pParse; /* The parsing context. Error messages written here */
1164011666
Schema *pSchema; /* Fix items to this schema */
11667
+ int bVarOnly; /* Check for variable references only */
1164111668
const char *zDb; /* Make sure all objects are contained in this database */
1164211669
const char *zType; /* Type of the container - used for error messages */
1164311670
const Token *pName; /* Name of the container - used for error messages */
1164411671
};
1164511672
@@ -12174,11 +12201,11 @@
1217412201
# define sqlite3AuthContextPush(a,b,c)
1217512202
# define sqlite3AuthContextPop(a) ((void)(a))
1217612203
#endif
1217712204
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
1217812205
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12179
-SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12206
+SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
1218012207
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
1218112208
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
1218212209
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
1218312210
SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
1218412211
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12213,16 @@
1218612213
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
1218712214
SQLITE_PRIVATE int sqlite3Atoi(const char*);
1218812215
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
1218912216
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
1219012217
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
12218
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
12219
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
12220
+#ifndef SQLITE_OMIT_VIRTUALTABLE
12221
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
12222
+#endif
12223
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
1219112224
1219212225
/*
1219312226
** Routines to read and write variable-length integers. These used to
1219412227
** be defined locally, but now we use the varint routines in the util.c
1219512228
** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12335,11 @@
1230212335
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
1230312336
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
1230412337
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
1230512338
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
1230612339
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12307
-SQLITE_PRIVATE char sqlite3AffinityType(const char*);
12340
+SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
1230812341
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
1230912342
SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
1231012343
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
1231112344
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
1231212345
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -12435,14 +12468,14 @@
1243512468
SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
1243612469
SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
1243712470
SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
1243812471
#else
1243912472
#define sqlite3FkActions(a,b,c,d,e,f)
12440
- #define sqlite3FkCheck(a,b,c,d)
12473
+ #define sqlite3FkCheck(a,b,c,d,e,f)
1244112474
#define sqlite3FkDropTable(a,b,c)
12442
- #define sqlite3FkOldmask(a,b) 0
12443
- #define sqlite3FkRequired(a,b,c,d,e,f) 0
12475
+ #define sqlite3FkOldmask(a,b) 0
12476
+ #define sqlite3FkRequired(a,b,c,d) 0
1244412477
#endif
1244512478
#ifndef SQLITE_OMIT_FOREIGN_KEY
1244612479
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
1244712480
SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
1244812481
#else
@@ -14397,10 +14430,14 @@
1439714430
** is available. This routine returns 0 on success and
1439814431
** non-zero on any kind of error.
1439914432
**
1440014433
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
1440114434
** routine will always fail.
14435
+**
14436
+** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
14437
+** library function localtime_r() is used to assist in the calculation of
14438
+** local time.
1440214439
*/
1440314440
static int osLocaltime(time_t *t, struct tm *pTm){
1440414441
int rc;
1440514442
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
1440614443
&& (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
@@ -14453,10 +14490,15 @@
1445314490
memset(&sLocal, 0, sizeof(sLocal));
1445414491
1445514492
x = *p;
1445614493
computeYMD_HMS(&x);
1445714494
if( x.Y<1971 || x.Y>=2038 ){
14495
+ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
14496
+ ** works for years between 1970 and 2037. For dates outside this range,
14497
+ ** SQLite attempts to map the year into an equivalent year within this
14498
+ ** range, do the calculation, then map the year back.
14499
+ */
1445814500
x.Y = 2000;
1445914501
x.M = 1;
1446014502
x.D = 1;
1446114503
x.h = 0;
1446214504
x.m = 0;
@@ -22387,10 +22429,87 @@
2238722429
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
2238822430
if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
2238922431
}
2239022432
}
2239122433
#endif
22434
+
22435
+/*
22436
+** Find (an approximate) sum of two LogEst values. This computation is
22437
+** not a simple "+" operator because LogEst is stored as a logarithmic
22438
+** value.
22439
+**
22440
+*/
22441
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
22442
+ static const unsigned char x[] = {
22443
+ 10, 10, /* 0,1 */
22444
+ 9, 9, /* 2,3 */
22445
+ 8, 8, /* 4,5 */
22446
+ 7, 7, 7, /* 6,7,8 */
22447
+ 6, 6, 6, /* 9,10,11 */
22448
+ 5, 5, 5, /* 12-14 */
22449
+ 4, 4, 4, 4, /* 15-18 */
22450
+ 3, 3, 3, 3, 3, 3, /* 19-24 */
22451
+ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
22452
+ };
22453
+ if( a>=b ){
22454
+ if( a>b+49 ) return a;
22455
+ if( a>b+31 ) return a+1;
22456
+ return a+x[a-b];
22457
+ }else{
22458
+ if( b>a+49 ) return b;
22459
+ if( b>a+31 ) return b+1;
22460
+ return b+x[b-a];
22461
+ }
22462
+}
22463
+
22464
+/*
22465
+** Convert an integer into a LogEst. In other words, compute a
22466
+** good approximatation for 10*log2(x).
22467
+*/
22468
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
22469
+ static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
22470
+ LogEst y = 40;
22471
+ if( x<8 ){
22472
+ if( x<2 ) return 0;
22473
+ while( x<8 ){ y -= 10; x <<= 1; }
22474
+ }else{
22475
+ while( x>255 ){ y += 40; x >>= 4; }
22476
+ while( x>15 ){ y += 10; x >>= 1; }
22477
+ }
22478
+ return a[x&7] + y - 10;
22479
+}
22480
+
22481
+#ifndef SQLITE_OMIT_VIRTUALTABLE
22482
+/*
22483
+** Convert a double into a LogEst
22484
+** In other words, compute an approximation for 10*log2(x).
22485
+*/
22486
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
22487
+ u64 a;
22488
+ LogEst e;
22489
+ assert( sizeof(x)==8 && sizeof(a)==8 );
22490
+ if( x<=1 ) return 0;
22491
+ if( x<=2000000000 ) return sqlite3LogEst((u64)x);
22492
+ memcpy(&a, &x, 8);
22493
+ e = (a>>52) - 1022;
22494
+ return e*10;
22495
+}
22496
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
22497
+
22498
+/*
22499
+** Convert a LogEst into an integer.
22500
+*/
22501
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
22502
+ u64 n;
22503
+ if( x<10 ) return 1;
22504
+ n = x%10;
22505
+ x /= 10;
22506
+ if( n>=5 ) n -= 2;
22507
+ else if( n>=1 ) n -= 1;
22508
+ if( x>=3 ) return (n+8)<<(x-3);
22509
+ return (n+8)>>(3-x);
22510
+}
2239222511
2239322512
/************** End of util.c ************************************************/
2239422513
/************** Begin file hash.c ********************************************/
2239522514
/*
2239622515
** 2001 September 22
@@ -31382,11 +31501,11 @@
3138231501
#endif
3138331502
3138431503
#define osGetVersionExA ((BOOL(WINAPI*)( \
3138531504
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
3138631505
31387
-#if defined(SQLITE_WIN32_HAS_WIDE)
31506
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
3138831507
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
3138931508
#else
3139031509
{ "GetVersionExW", (SYSCALL)0, 0 },
3139131510
#endif
3139231511
@@ -32896,12 +33015,11 @@
3289633015
#endif
3289733016
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
3289833017
OSTRACE(("CLOSE file=%p\n", pFile->h));
3289933018
3290033019
#if SQLITE_MAX_MMAP_SIZE>0
32901
- rc = winUnmapfile(pFile);
32902
- if( rc!=SQLITE_OK ) return rc;
33020
+ winUnmapfile(pFile);
3290333021
#endif
3290433022
3290533023
do{
3290633024
rc = osCloseHandle(pFile->h);
3290733025
/* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -33703,11 +33821,11 @@
3370333821
}
3370433822
*(i64*)pArg = pFile->mmapSizeMax;
3370533823
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
3370633824
pFile->mmapSizeMax = newLimit;
3370733825
if( pFile->mmapSize>0 ){
33708
- (void)winUnmapfile(pFile);
33826
+ winUnmapfile(pFile);
3370933827
rc = winMapfile(pFile, -1);
3371033828
}
3371133829
}
3371233830
OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
3371333831
return rc;
@@ -33920,11 +34038,11 @@
3392034038
osGetCurrentProcessId(), deleteFlag));
3392134039
pp = &winShmNodeList;
3392234040
while( (p = *pp)!=0 ){
3392334041
if( p->nRef==0 ){
3392434042
int i;
33925
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
34043
+ if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
3392634044
for(i=0; i<p->nRegion; i++){
3392734045
BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
3392834046
OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
3392934047
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
3393034048
UNUSED_VARIABLE_VALUE(bRc);
@@ -34773,10 +34891,11 @@
3477334891
** API prior to using it.
3477434892
*/
3477534893
if( winIsDriveLetterAndColon(zDir) ){
3477634894
zConverted = winConvertFromUtf8Filename(zDir);
3477734895
if( !zConverted ){
34896
+ sqlite3_free(zBuf);
3477834897
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
3477934898
return SQLITE_IOERR_NOMEM;
3478034899
}
3478134900
if( winIsDir(zConverted) ){
3478234901
sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir);
@@ -34785,17 +34904,19 @@
3478534904
}
3478634905
sqlite3_free(zConverted);
3478734906
}else{
3478834907
zConverted = sqlite3MallocZero( nBuf+1 );
3478934908
if( !zConverted ){
34909
+ sqlite3_free(zBuf);
3479034910
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
3479134911
return SQLITE_IOERR_NOMEM;
3479234912
}
3479334913
if( cygwin_conv_path(
3479434914
osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
3479534915
zConverted, nBuf+1)<0 ){
3479634916
sqlite3_free(zConverted);
34917
+ sqlite3_free(zBuf);
3479734918
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
3479834919
return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
3479934920
"winGetTempname1", zDir);
3480034921
}
3480134922
if( winIsDir(zConverted) ){
@@ -34805,10 +34926,11 @@
3480534926
*/
3480634927
if( osIsNT() ){
3480734928
char *zUtf8 = winUnicodeToUtf8(zConverted);
3480834929
if( !zUtf8 ){
3480934930
sqlite3_free(zConverted);
34931
+ sqlite3_free(zBuf);
3481034932
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
3481134933
return SQLITE_IOERR_NOMEM;
3481234934
}
3481334935
sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8);
3481434936
sqlite3_free(zUtf8);
@@ -34820,11 +34942,10 @@
3482034942
break;
3482134943
}
3482234944
}
3482334945
sqlite3_free(zConverted);
3482434946
}
34825
- break;
3482634947
}
3482734948
}
3482834949
#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
3482934950
else if( osIsNT() ){
3483034951
char *zMulti;
@@ -35190,13 +35311,13 @@
3519035311
pFile->zDeleteOnClose = zConverted;
3519135312
}else
3519235313
#endif
3519335314
{
3519435315
sqlite3_free(zConverted);
35195
- sqlite3_free(zTmpname);
3519635316
}
3519735317
35318
+ sqlite3_free(zTmpname);
3519835319
pFile->pMethod = &winIoMethod;
3519935320
pFile->pVfs = pVfs;
3520035321
pFile->h = h;
3520135322
if( isReadonly ){
3520235323
pFile->ctrlFlags |= WINFILE_RDONLY;
@@ -48986,17 +49107,17 @@
4898649107
** page contain a special header (the "file header") that describes the file.
4898749108
** The format of the file header is as follows:
4898849109
**
4898949110
** OFFSET SIZE DESCRIPTION
4899049111
** 0 16 Header string: "SQLite format 3\000"
48991
-** 16 2 Page size in bytes.
49112
+** 16 2 Page size in bytes. (1 means 65536)
4899249113
** 18 1 File format write version
4899349114
** 19 1 File format read version
4899449115
** 20 1 Bytes of unused space at the end of each page
48995
-** 21 1 Max embedded payload fraction
48996
-** 22 1 Min embedded payload fraction
48997
-** 23 1 Min leaf payload fraction
49116
+** 21 1 Max embedded payload fraction (must be 64)
49117
+** 22 1 Min embedded payload fraction (must be 32)
49118
+** 23 1 Min leaf payload fraction (must be 32)
4899849119
** 24 4 File change counter
4899949120
** 28 4 Reserved for future use
4900049121
** 32 4 First freelist page
4900149122
** 36 4 Number of freelist pages in the file
4900249123
** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49127,14 @@
4900649127
** 48 4 Size of page cache
4900749128
** 52 4 Largest root-page (auto/incr_vacuum)
4900849129
** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
4900949130
** 60 4 User version
4901049131
** 64 4 Incremental vacuum mode
49011
-** 68 4 unused
49012
-** 72 4 unused
49013
-** 76 4 unused
49132
+** 68 4 Application-ID
49133
+** 72 20 unused
49134
+** 92 4 The version-valid-for number
49135
+** 96 4 SQLITE_VERSION_NUMBER
4901449136
**
4901549137
** All of the integer values are big-endian (most significant byte first).
4901649138
**
4901749139
** The file change counter is incremented when the database is changed
4901849140
** This counter allows other processes to know when the file has changed
@@ -51922,10 +52044,22 @@
5192252044
** MX_CELL_SIZE(pBt) bytes.
5192352045
*/
5192452046
static void allocateTempSpace(BtShared *pBt){
5192552047
if( !pBt->pTmpSpace ){
5192652048
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
52049
+
52050
+ /* One of the uses of pBt->pTmpSpace is to format cells before
52051
+ ** inserting them into a leaf page (function fillInCell()). If
52052
+ ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
52053
+ ** by the various routines that manipulate binary cells. Which
52054
+ ** can mean that fillInCell() only initializes the first 2 or 3
52055
+ ** bytes of pTmpSpace, but that the first 4 bytes are copied from
52056
+ ** it into a database page. This is not actually a problem, but it
52057
+ ** does cause a valgrind error when the 1 or 2 bytes of unitialized
52058
+ ** data is passed to system call write(). So to avoid this error,
52059
+ ** zero the first 4 bytes of temp space here. */
52060
+ if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4);
5192752061
}
5192852062
}
5192952063
5193052064
/*
5193152065
** Free the pBt->pTmpSpace allocation
@@ -52378,11 +52512,10 @@
5237852512
pBt->max1bytePayload = (u8)pBt->maxLocal;
5237952513
}
5238052514
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
5238152515
pBt->pPage1 = pPage1;
5238252516
pBt->nPage = nPage;
52383
-assert( pPage1->leaf==0 || pPage1->leaf==1 );
5238452517
return SQLITE_OK;
5238552518
5238652519
page1_init_failed:
5238752520
releasePage(pPage1);
5238852521
pBt->pPage1 = 0;
@@ -52538,11 +52671,11 @@
5253852671
** is requested, this is a no-op.
5253952672
*/
5254052673
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
5254152674
goto trans_begun;
5254252675
}
52543
- assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
52676
+ assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
5254452677
5254552678
/* Write transactions are not possible on a read-only database */
5254652679
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
5254752680
rc = SQLITE_READONLY;
5254852681
goto trans_begun;
@@ -60189,11 +60322,13 @@
6018960322
}
6019060323
6019160324
pRec->nField = p->iVal+1;
6019260325
return &pRec->aMem[p->iVal];
6019360326
}
60194
-#endif
60327
+#else
60328
+ UNUSED_PARAMETER(p);
60329
+#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
6019560330
return sqlite3ValueNew(db);
6019660331
}
6019760332
6019860333
/*
6019960334
** Extract a value from the supplied expression in the manner described
@@ -60203,11 +60338,11 @@
6020360338
** If pCtx is NULL and an error occurs after the sqlite3_value object
6020460339
** has been allocated, it is freed before returning. Or, if pCtx is not
6020560340
** NULL, it is assumed that the caller will free any allocated object
6020660341
** in all cases.
6020760342
*/
60208
-int valueFromExpr(
60343
+static int valueFromExpr(
6020960344
sqlite3 *db, /* The database connection */
6021060345
Expr *pExpr, /* The expression to evaluate */
6021160346
u8 enc, /* Encoding to use */
6021260347
u8 affinity, /* Affinity to use */
6021360348
sqlite3_value **ppVal, /* Write the new value here */
@@ -60360,10 +60495,11 @@
6036060495
int nVal; /* Bytes of space required for argv[0] */
6036160496
int nRet;
6036260497
sqlite3 *db;
6036360498
u8 *aRet;
6036460499
60500
+ UNUSED_PARAMETER( argc );
6036560501
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
6036660502
nSerial = sqlite3VarintLen(iSerial);
6036760503
nVal = sqlite3VdbeSerialTypeLen(iSerial);
6036860504
db = sqlite3_context_db_handle(context);
6036960505
@@ -62977,10 +63113,11 @@
6297763113
}
6297863114
fclose(out);
6297963115
}
6298063116
}
6298163117
#endif
63118
+ p->iCurrentTime = 0;
6298263119
p->magic = VDBE_MAGIC_INIT;
6298363120
return p->rc & db->errMask;
6298463121
}
6298563122
6298663123
/*
@@ -75299,10 +75436,14 @@
7529975436
sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
7530075437
"constant between 0.0 and 1.0");
7530175438
pNC->nErr++;
7530275439
}
7530375440
}else{
75441
+ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
75442
+ ** likelihood(X, 0.0625).
75443
+ ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
75444
+ ** likelihood(X,0.0625). */
7530475445
pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
7530575446
}
7530675447
}
7530775448
}
7530875449
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -76082,11 +76223,11 @@
7608276223
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
7608376224
}
7608476225
#ifndef SQLITE_OMIT_CAST
7608576226
if( op==TK_CAST ){
7608676227
assert( !ExprHasProperty(pExpr, EP_IntValue) );
76087
- return sqlite3AffinityType(pExpr->u.zToken);
76228
+ return sqlite3AffinityType(pExpr->u.zToken, 0);
7608876229
}
7608976230
#endif
7609076231
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
7609176232
&& pExpr->pTab!=0
7609276233
){
@@ -78502,11 +78643,11 @@
7850278643
case TK_CAST: {
7850378644
/* Expressions of the form: CAST(pLeft AS token) */
7850478645
int aff, to_op;
7850578646
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
7850678647
assert( !ExprHasProperty(pExpr, EP_IntValue) );
78507
- aff = sqlite3AffinityType(pExpr->u.zToken);
78648
+ aff = sqlite3AffinityType(pExpr->u.zToken, 0);
7850878649
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
7850978650
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
7851078651
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
7851178652
assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
7851278653
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79310,11 @@
7916979310
}
7917079311
#ifndef SQLITE_OMIT_CAST
7917179312
case TK_CAST: {
7917279313
/* Expressions of the form: CAST(pLeft AS token) */
7917379314
const char *zAff = "unk";
79174
- switch( sqlite3AffinityType(pExpr->u.zToken) ){
79315
+ switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
7917579316
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
7917679317
case SQLITE_AFF_NONE: zAff = "NONE"; break;
7917779318
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
7917879319
case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
7917979320
case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81173,11 +81314,11 @@
8117381314
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
8117481315
** created and used by SQLite versions 3.7.9 and later and with
8117581316
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
8117681317
** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
8117781318
** version of sqlite_stat3 and is only available when compiled with
81178
-** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is
81319
+** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
8117981320
** not possible to enable both STAT3 and STAT4 at the same time. If they
8118081321
** are both enabled, then STAT4 takes precedence.
8118181322
**
8118281323
** For most applications, sqlite_stat1 provides all the statisics required
8118381324
** for the query planner to make good choices.
@@ -81249,16 +81390,16 @@
8124981390
**
8125081391
** The sqlite_stat4 table contains multiple entries for each index.
8125181392
** The idx column names the index and the tbl column is the table of the
8125281393
** index. If the idx and tbl columns are the same, then the sample is
8125381394
** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
81254
-** binary encoding of a key from the index, with the trailing rowid
81255
-** omitted. The nEq column is a list of integers. The first integer
81256
-** is the approximate number of entries in the index whose left-most
81257
-** column exactly matches the left-most column of the sample. The second
81258
-** integer in nEq is the approximate number of entries in the index where
81259
-** the first two columns match the first two columns of the sample.
81395
+** binary encoding of a key from the index. The nEq column is a
81396
+** list of integers. The first integer is the approximate number
81397
+** of entries in the index whose left-most column exactly matches
81398
+** the left-most column of the sample. The second integer in nEq
81399
+** is the approximate number of entries in the index where the
81400
+** first two columns match the first two columns of the sample.
8126081401
** And so forth. nLt is another list of integers that show the approximate
8126181402
** number of entries that are strictly less than the sample. The first
8126281403
** integer in nLt contains the number of entries in the index where the
8126381404
** left-most column is less than the left-most column of the sample.
8126481405
** The K-th integer in the nLt entry is the number of index entries
@@ -81585,11 +81726,11 @@
8158581726
}
8158681727
8158781728
/*
8158881729
** Copy the contents of object (*pFrom) into (*pTo).
8158981730
*/
81590
-void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
81731
+static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
8159181732
pTo->iRowid = pFrom->iRowid;
8159281733
pTo->isPSample = pFrom->isPSample;
8159381734
pTo->iCol = pFrom->iCol;
8159481735
pTo->iHash = pFrom->iHash;
8159581736
memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
@@ -81730,10 +81871,15 @@
8173081871
){
8173181872
sampleInsert(p, &p->current, 0);
8173281873
}
8173381874
}
8173481875
#endif
81876
+
81877
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
81878
+ UNUSED_PARAMETER( p );
81879
+ UNUSED_PARAMETER( iChng );
81880
+#endif
8173581881
}
8173681882
8173781883
/*
8173881884
** Implementation of the stat_push SQL function: stat_push(P,R,C)
8173981885
** Arguments:
@@ -81755,10 +81901,12 @@
8175581901
8175681902
/* The three function arguments */
8175781903
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
8175881904
int iChng = sqlite3_value_int(argv[1]);
8175981905
81906
+ UNUSED_PARAMETER( argc );
81907
+ UNUSED_PARAMETER( context );
8176081908
assert( p->nCol>1 ); /* Includes rowid field */
8176181909
assert( iChng<p->nCol );
8176281910
8176381911
if( p->nRow==0 ){
8176481912
/* This is the first call to this function. Do initialization. */
@@ -81884,16 +82032,16 @@
8188482032
if( zRet==0 ){
8188582033
sqlite3_result_error_nomem(context);
8188682034
return;
8188782035
}
8188882036
81889
- sqlite3_snprintf(24, zRet, "%lld", p->nRow);
82037
+ sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
8189082038
z = zRet + sqlite3Strlen30(zRet);
8189182039
for(i=0; i<(p->nCol-1); i++){
81892
- i64 nDistinct = p->current.anDLt[i] + 1;
81893
- i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
81894
- sqlite3_snprintf(24, z, " %lld", iVal);
82040
+ u64 nDistinct = p->current.anDLt[i] + 1;
82041
+ u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
82042
+ sqlite3_snprintf(24, z, " %llu", iVal);
8189582043
z += sqlite3Strlen30(z);
8189682044
assert( p->current.anEq[i] );
8189782045
}
8189882046
assert( z[0]=='\0' && z>zRet );
8189982047
@@ -81930,20 +82078,23 @@
8193082078
sqlite3_result_error_nomem(context);
8193182079
}else{
8193282080
int i;
8193382081
char *z = zRet;
8193482082
for(i=0; i<p->nCol; i++){
81935
- sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
82083
+ sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
8193682084
z += sqlite3Strlen30(z);
8193782085
}
8193882086
assert( z[0]=='\0' && z>zRet );
8193982087
z[-1] = '\0';
8194082088
sqlite3_result_text(context, zRet, -1, sqlite3_free);
8194182089
}
8194282090
}
8194382091
}
8194482092
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
82093
+#ifndef SQLITE_DEBUG
82094
+ UNUSED_PARAMETER( argc );
82095
+#endif
8194582096
}
8194682097
static const FuncDef statGetFuncdef = {
8194782098
1+IsStat34, /* nArg */
8194882099
SQLITE_UTF8, /* funcFlags */
8194982100
0, /* pUserData */
@@ -81958,12 +82109,14 @@
8195882109
8195982110
static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
8196082111
assert( regOut!=regStat4 && regOut!=regStat4+1 );
8196182112
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
8196282113
sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
81963
-#else
82114
+#elif SQLITE_DEBUG
8196482115
assert( iParam==STAT_GET_STAT1 );
82116
+#else
82117
+ UNUSED_PARAMETER( iParam );
8196582118
#endif
8196682119
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
8196782120
sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
8196882121
sqlite3VdbeChangeP5(v, 1 + IsStat34);
8196982122
}
@@ -82391,22 +82544,20 @@
8239182544
** The first argument points to a nul-terminated string containing a
8239282545
** list of space separated integers. Read the first nOut of these into
8239382546
** the array aOut[].
8239482547
*/
8239582548
static void decodeIntArray(
82396
- char *zIntArray,
82397
- int nOut,
82398
- tRowcnt *aOut,
82399
- int *pbUnordered
82549
+ char *zIntArray, /* String containing int array to decode */
82550
+ int nOut, /* Number of slots in aOut[] */
82551
+ tRowcnt *aOut, /* Store integers here */
82552
+ Index *pIndex /* Handle extra flags for this index, if not NULL */
8240082553
){
8240182554
char *z = zIntArray;
8240282555
int c;
8240382556
int i;
8240482557
tRowcnt v;
8240582558
82406
- assert( pbUnordered==0 || *pbUnordered==0 );
82407
-
8240882559
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
8240982560
if( z==0 ) z = "";
8241082561
#else
8241182562
if( NEVER(z==0) ) z = "";
8241282563
#endif
@@ -82417,12 +82568,23 @@
8241782568
z++;
8241882569
}
8241982570
aOut[i] = v;
8242082571
if( *z==' ' ) z++;
8242182572
}
82422
- if( pbUnordered && strcmp(z, "unordered")==0 ){
82423
- *pbUnordered = 1;
82573
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
82574
+ assert( pIndex!=0 );
82575
+#else
82576
+ if( pIndex )
82577
+#endif
82578
+ {
82579
+ if( strcmp(z, "unordered")==0 ){
82580
+ pIndex->bUnordered = 1;
82581
+ }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
82582
+ int v32 = 0;
82583
+ sqlite3GetInt32(z+3, &v32);
82584
+ pIndex->szIdxRow = sqlite3LogEst(v32);
82585
+ }
8242482586
}
8242582587
}
8242682588
8242782589
/*
8242882590
** This callback is invoked once for each index when reading the
@@ -82457,16 +82619,17 @@
8245782619
pIndex = 0;
8245882620
}
8245982621
z = argv[2];
8246082622
8246182623
if( pIndex ){
82462
- int bUnordered = 0;
82463
- decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
82624
+ decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
8246482625
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
82465
- pIndex->bUnordered = bUnordered;
8246682626
}else{
82467
- decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
82627
+ Index fakeIdx;
82628
+ fakeIdx.szIdxRow = pTable->szTabRow;
82629
+ decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
82630
+ pTable->szTabRow = fakeIdx.szIdxRow;
8246882631
}
8246982632
8247082633
return 0;
8247182634
}
8247282635
@@ -83185,32 +83348,28 @@
8318583348
#endif /* SQLITE_OMIT_ATTACH */
8318683349
8318783350
/*
8318883351
** Initialize a DbFixer structure. This routine must be called prior
8318983352
** to passing the structure to one of the sqliteFixAAAA() routines below.
83190
-**
83191
-** The return value indicates whether or not fixation is required. TRUE
83192
-** means we do need to fix the database references, FALSE means we do not.
8319383353
*/
83194
-SQLITE_PRIVATE int sqlite3FixInit(
83354
+SQLITE_PRIVATE void sqlite3FixInit(
8319583355
DbFixer *pFix, /* The fixer to be initialized */
8319683356
Parse *pParse, /* Error messages will be written here */
8319783357
int iDb, /* This is the database that must be used */
8319883358
const char *zType, /* "view", "trigger", or "index" */
8319983359
const Token *pName /* Name of the view, trigger, or index */
8320083360
){
8320183361
sqlite3 *db;
8320283362
83203
- if( NEVER(iDb<0) || iDb==1 ) return 0;
8320483363
db = pParse->db;
8320583364
assert( db->nDb>iDb );
8320683365
pFix->pParse = pParse;
8320783366
pFix->zDb = db->aDb[iDb].zName;
8320883367
pFix->pSchema = db->aDb[iDb].pSchema;
8320983368
pFix->zType = zType;
8321083369
pFix->pName = pName;
83211
- return 1;
83370
+ pFix->bVarOnly = (iDb==1);
8321283371
}
8321383372
8321483373
/*
8321583374
** The following set of routines walk through the parse tree and assign
8321683375
** a specific database to all table references where the database name
@@ -83234,19 +83393,21 @@
8323483393
struct SrcList_item *pItem;
8323583394
8323683395
if( NEVER(pList==0) ) return 0;
8323783396
zDb = pFix->zDb;
8323883397
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83239
- if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83240
- sqlite3ErrorMsg(pFix->pParse,
83241
- "%s %T cannot reference objects in database %s",
83242
- pFix->zType, pFix->pName, pItem->zDatabase);
83243
- return 1;
83244
- }
83245
- sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83246
- pItem->zDatabase = 0;
83247
- pItem->pSchema = pFix->pSchema;
83398
+ if( pFix->bVarOnly==0 ){
83399
+ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83400
+ sqlite3ErrorMsg(pFix->pParse,
83401
+ "%s %T cannot reference objects in database %s",
83402
+ pFix->zType, pFix->pName, pItem->zDatabase);
83403
+ return 1;
83404
+ }
83405
+ sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83406
+ pItem->zDatabase = 0;
83407
+ pItem->pSchema = pFix->pSchema;
83408
+ }
8324883409
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
8324983410
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
8325083411
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
8325183412
#endif
8325283413
}
@@ -83264,13 +83425,25 @@
8326483425
if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
8326583426
return 1;
8326683427
}
8326783428
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
8326883429
return 1;
83430
+ }
83431
+ if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
83432
+ return 1;
8326983433
}
8327083434
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
8327183435
return 1;
83436
+ }
83437
+ if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
83438
+ return 1;
83439
+ }
83440
+ if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
83441
+ return 1;
83442
+ }
83443
+ if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
83444
+ return 1;
8327283445
}
8327383446
pSelect = pSelect->pPrior;
8327483447
}
8327583448
return 0;
8327683449
}
@@ -83277,10 +83450,18 @@
8327783450
SQLITE_PRIVATE int sqlite3FixExpr(
8327883451
DbFixer *pFix, /* Context of the fixation */
8327983452
Expr *pExpr /* The expression to be fixed to one database */
8328083453
){
8328183454
while( pExpr ){
83455
+ if( pExpr->op==TK_VARIABLE ){
83456
+ if( pFix->pParse->db->init.busy ){
83457
+ pExpr->op = TK_NULL;
83458
+ }else{
83459
+ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
83460
+ return 1;
83461
+ }
83462
+ }
8328283463
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
8328383464
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
8328483465
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
8328583466
}else{
8328683467
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84641,11 @@
8446084641
}
8446184642
pTable->zName = zName;
8446284643
pTable->iPKey = -1;
8446384644
pTable->pSchema = db->aDb[iDb].pSchema;
8446484645
pTable->nRef = 1;
84465
- pTable->nRowEst = 1000000;
84646
+ pTable->nRowEst = 1048576;
8446684647
assert( pParse->pNewTable==0 );
8446784648
pParse->pNewTable = pTable;
8446884649
8446984650
/* If this is the magic sqlite_sequence table used by autoincrement,
8447084651
** then record a pointer to this table in the main database structure
@@ -84607,10 +84788,11 @@
8460784788
/* If there is no type specified, columns have the default affinity
8460884789
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
8460984790
** be called next to set pCol->affinity correctly.
8461084791
*/
8461184792
pCol->affinity = SQLITE_AFF_NONE;
84793
+ pCol->szEst = 1;
8461284794
p->nCol++;
8461384795
}
8461484796
8461584797
/*
8461684798
** This routine is called by the parser while in the middle of
@@ -84648,26 +84830,30 @@
8464884830
** 'DOUB' | SQLITE_AFF_REAL
8464984831
**
8465084832
** If none of the substrings in the above table are found,
8465184833
** SQLITE_AFF_NUMERIC is returned.
8465284834
*/
84653
-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
84835
+SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
8465484836
u32 h = 0;
8465584837
char aff = SQLITE_AFF_NUMERIC;
84838
+ const char *zChar = 0;
8465684839
84657
- if( zIn ) while( zIn[0] ){
84840
+ if( zIn==0 ) return aff;
84841
+ while( zIn[0] ){
8465884842
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
8465984843
zIn++;
8466084844
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84661
- aff = SQLITE_AFF_TEXT;
84845
+ aff = SQLITE_AFF_TEXT;
84846
+ zChar = zIn;
8466284847
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
8466384848
aff = SQLITE_AFF_TEXT;
8466484849
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
8466584850
aff = SQLITE_AFF_TEXT;
8466684851
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
8466784852
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
8466884853
aff = SQLITE_AFF_NONE;
84854
+ if( zIn[0]=='(' ) zChar = zIn;
8466984855
#ifndef SQLITE_OMIT_FLOATING_POINT
8467084856
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
8467184857
&& aff==SQLITE_AFF_NUMERIC ){
8467284858
aff = SQLITE_AFF_REAL;
8467384859
}else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84867,32 @@
8468184867
aff = SQLITE_AFF_INTEGER;
8468284868
break;
8468384869
}
8468484870
}
8468584871
84872
+ /* If pszEst is not NULL, store an estimate of the field size. The
84873
+ ** estimate is scaled so that the size of an integer is 1. */
84874
+ if( pszEst ){
84875
+ *pszEst = 1; /* default size is approx 4 bytes */
84876
+ if( aff<=SQLITE_AFF_NONE ){
84877
+ if( zChar ){
84878
+ while( zChar[0] ){
84879
+ if( sqlite3Isdigit(zChar[0]) ){
84880
+ int v = 0;
84881
+ sqlite3GetInt32(zChar, &v);
84882
+ v = v/4 + 1;
84883
+ if( v>255 ) v = 255;
84884
+ *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
84885
+ break;
84886
+ }
84887
+ zChar++;
84888
+ }
84889
+ }else{
84890
+ *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
84891
+ }
84892
+ }
84893
+ }
8468684894
return aff;
8468784895
}
8468884896
8468984897
/*
8469084898
** This routine is called by the parser while in the middle of
@@ -84702,11 +84910,11 @@
8470284910
p = pParse->pNewTable;
8470384911
if( p==0 || NEVER(p->nCol<1) ) return;
8470484912
pCol = &p->aCol[p->nCol-1];
8470584913
assert( pCol->zType==0 );
8470684914
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84707
- pCol->affinity = sqlite3AffinityType(pCol->zType);
84915
+ pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
8470884916
}
8470984917
8471084918
/*
8471184919
** The expression is the default value for the most recently added column
8471284920
** of the table currently under construction.
@@ -85050,18 +85258,46 @@
8505085258
testcase( pCol->affinity==SQLITE_AFF_REAL );
8505185259
8505285260
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
8505385261
len = sqlite3Strlen30(zType);
8505485262
assert( pCol->affinity==SQLITE_AFF_NONE
85055
- || pCol->affinity==sqlite3AffinityType(zType) );
85263
+ || pCol->affinity==sqlite3AffinityType(zType, 0) );
8505685264
memcpy(&zStmt[k], zType, len);
8505785265
k += len;
8505885266
assert( k<=n );
8505985267
}
8506085268
sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
8506185269
return zStmt;
8506285270
}
85271
+
85272
+/*
85273
+** Estimate the total row width for a table.
85274
+*/
85275
+static void estimateTableWidth(Table *pTab){
85276
+ unsigned wTable = 0;
85277
+ const Column *pTabCol;
85278
+ int i;
85279
+ for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
85280
+ wTable += pTabCol->szEst;
85281
+ }
85282
+ if( pTab->iPKey<0 ) wTable++;
85283
+ pTab->szTabRow = sqlite3LogEst(wTable*4);
85284
+}
85285
+
85286
+/*
85287
+** Estimate the average size of a row for an index.
85288
+*/
85289
+static void estimateIndexWidth(Index *pIdx){
85290
+ unsigned wIndex = 1;
85291
+ int i;
85292
+ const Column *aCol = pIdx->pTable->aCol;
85293
+ for(i=0; i<pIdx->nColumn; i++){
85294
+ assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
85295
+ wIndex += aCol[pIdx->aiColumn[i]].szEst;
85296
+ }
85297
+ pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
85298
+}
8506385299
8506485300
/*
8506585301
** This routine is called to report the final ")" that terminates
8506685302
** a CREATE TABLE statement.
8506785303
**
@@ -85085,13 +85321,14 @@
8508585321
Parse *pParse, /* Parse context */
8508685322
Token *pCons, /* The ',' token after the last column defn. */
8508785323
Token *pEnd, /* The final ')' token in the CREATE TABLE */
8508885324
Select *pSelect /* Select from a "CREATE ... AS SELECT" */
8508985325
){
85090
- Table *p;
85091
- sqlite3 *db = pParse->db;
85092
- int iDb;
85326
+ Table *p; /* The new table */
85327
+ sqlite3 *db = pParse->db; /* The database connection */
85328
+ int iDb; /* Database in which the table lives */
85329
+ Index *pIdx; /* An implied index of the table */
8509385330
8509485331
if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
8509585332
return;
8509685333
}
8509785334
p = pParse->pNewTable;
@@ -85106,10 +85343,16 @@
8510685343
*/
8510785344
if( p->pCheck ){
8510885345
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
8510985346
}
8511085347
#endif /* !defined(SQLITE_OMIT_CHECK) */
85348
+
85349
+ /* Estimate the average row size for the table and for all implied indices */
85350
+ estimateTableWidth(p);
85351
+ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
85352
+ estimateIndexWidth(pIdx);
85353
+ }
8511185354
8511285355
/* If the db->init.busy is 1 it means we are reading the SQL off the
8511385356
** "sqlite_master" or "sqlite_temp_master" table on the disk.
8511485357
** So do not write to the disk again. Extract the root page number
8511585358
** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85546,12 @@
8530385546
sqlite3SelectDelete(db, pSelect);
8530485547
return;
8530585548
}
8530685549
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
8530785550
iDb = sqlite3SchemaToIndex(db, p->pSchema);
85308
- if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
85309
- && sqlite3FixSelect(&sFix, pSelect)
85310
- ){
85551
+ sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
85552
+ if( sqlite3FixSelect(&sFix, pSelect) ){
8531185553
sqlite3SelectDelete(db, pSelect);
8531285554
return;
8531385555
}
8531485556
8531585557
/* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86308,14 @@
8606686308
sqlite3 *db = pParse->db;
8606786309
Db *pDb; /* The specific table containing the indexed database */
8606886310
int iDb; /* Index of the database that is being written */
8606986311
Token *pName = 0; /* Unqualified name of the index to create */
8607086312
struct ExprList_item *pListItem; /* For looping over pList */
86071
- int nCol;
86072
- int nExtra = 0;
86073
- char *zExtra;
86313
+ const Column *pTabCol; /* A column in the table */
86314
+ int nCol; /* Number of columns */
86315
+ int nExtra = 0; /* Space allocated for zExtra[] */
86316
+ char *zExtra; /* Extra space after the Index object */
8607486317
8607586318
assert( pParse->nErr==0 ); /* Never called with prior errors */
8607686319
if( db->mallocFailed || IN_DECLARE_VTAB ){
8607786320
goto exit_create_index;
8607886321
}
@@ -86105,13 +86348,12 @@
8610586348
iDb = 1;
8610686349
}
8610786350
}
8610886351
#endif
8610986352
86110
- if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
86111
- sqlite3FixSrcList(&sFix, pTblName)
86112
- ){
86353
+ sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
86354
+ if( sqlite3FixSrcList(&sFix, pTblName) ){
8611386355
/* Because the parser constructs pTblName from a single identifier,
8611486356
** sqlite3FixSrcList can never fail. */
8611586357
assert(0);
8611686358
}
8611786359
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86538,10 @@
8629686538
** same column more than once cannot be an error because that would
8629786539
** break backwards compatibility - it needs to be a warning.
8629886540
*/
8629986541
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
8630086542
const char *zColName = pListItem->zName;
86301
- Column *pTabCol;
8630286543
int requestedSortOrder;
8630386544
char *zColl; /* Collation sequence name */
8630486545
8630586546
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
8630686547
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86574,11 @@
8633386574
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
8633486575
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
8633586576
if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
8633686577
}
8633786578
sqlite3DefaultRowEst(pIndex);
86579
+ if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
8633886580
8633986581
if( pTab==pParse->pNewTable ){
8634086582
/* This routine has been called to create an automatic index as a
8634186583
** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
8634286584
** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88480,11 @@
8823888480
** API function sqlite3_count_changes) to be set incorrectly. */
8823988481
if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
8824088482
&& 0==sqlite3FkRequired(pParse, pTab, 0, 0)
8824188483
){
8824288484
assert( !isView );
88485
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
8824388486
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
8824488487
pTab->zName, P4_STATIC);
8824588488
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
8824688489
assert( pIdx->pSchema==pTab->pSchema );
8824788490
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -90943,11 +91186,11 @@
9094391186
** generating any VDBE code. If one can be found, then jump over
9094491187
** the entire DELETE if there are no outstanding deferred constraints
9094591188
** when this statement is run. */
9094691189
FKey *p;
9094791190
for(p=pTab->pFKey; p; p=p->pNextFrom){
90948
- if( p->isDeferred ) break;
91191
+ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
9094991192
}
9095091193
if( !p ) return;
9095191194
iSkip = sqlite3VdbeMakeLabel(v);
9095291195
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
9095391196
}
@@ -90957,15 +91200,22 @@
9095791200
pParse->disableTriggers = 0;
9095891201
9095991202
/* If the DELETE has generated immediate foreign key constraint
9096091203
** violations, halt the VDBE and return an error at this point, before
9096191204
** any modifications to the schema are made. This is because statement
90962
- ** transactions are not able to rollback schema changes. */
90963
- sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
90964
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
90965
- OE_Abort, "foreign key constraint failed", P4_STATIC
90966
- );
91205
+ ** transactions are not able to rollback schema changes.
91206
+ **
91207
+ ** If the SQLITE_DeferFKs flag is set, then this is not required, as
91208
+ ** the statement transaction will not be rolled back even if FK
91209
+ ** constraints are violated.
91210
+ */
91211
+ if( (db->flags & SQLITE_DeferFKs)==0 ){
91212
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
91213
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
91214
+ OE_Abort, "foreign key constraint failed", P4_STATIC
91215
+ );
91216
+ }
9096791217
9096891218
if( iSkip ){
9096991219
sqlite3VdbeResolveLabel(v, iSkip);
9097091220
}
9097191221
}
@@ -93487,10 +93737,11 @@
9348793737
(char*)pKey, P4_KEYINFO_HANDOFF);
9348893738
VdbeComment((v, "%s", pSrcIdx->zName));
9348993739
pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
9349093740
sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
9349193741
(char*)pKey, P4_KEYINFO_HANDOFF);
93742
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
9349293743
VdbeComment((v, "%s", pDestIdx->zName));
9349393744
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
9349493745
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
9349593746
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
9349693747
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94962,193 +95213,382 @@
9496295213
#define PragTyp_MMAP_SIZE 23
9496395214
#define PragTyp_PAGE_SIZE 24
9496495215
#define PragTyp_SECURE_DELETE 25
9496595216
#define PragTyp_SHRINK_MEMORY 26
9496695217
#define PragTyp_SOFT_HEAP_LIMIT 27
94967
-#define PragTyp_SYNCHRONOUS 28
94968
-#define PragTyp_TABLE_INFO 29
94969
-#define PragTyp_TEMP_STORE 30
94970
-#define PragTyp_TEMP_STORE_DIRECTORY 31
94971
-#define PragTyp_WAL_AUTOCHECKPOINT 32
94972
-#define PragTyp_WAL_CHECKPOINT 33
94973
-#define PragTyp_ACTIVATE_EXTENSIONS 34
94974
-#define PragTyp_HEXKEY 35
94975
-#define PragTyp_KEY 36
94976
-#define PragTyp_REKEY 37
94977
-#define PragTyp_LOCK_STATUS 38
94978
-#define PragTyp_PARSER_TRACE 39
95218
+#define PragTyp_STATS 28
95219
+#define PragTyp_SYNCHRONOUS 29
95220
+#define PragTyp_TABLE_INFO 30
95221
+#define PragTyp_TEMP_STORE 31
95222
+#define PragTyp_TEMP_STORE_DIRECTORY 32
95223
+#define PragTyp_WAL_AUTOCHECKPOINT 33
95224
+#define PragTyp_WAL_CHECKPOINT 34
95225
+#define PragTyp_ACTIVATE_EXTENSIONS 35
95226
+#define PragTyp_HEXKEY 36
95227
+#define PragTyp_KEY 37
95228
+#define PragTyp_REKEY 38
95229
+#define PragTyp_LOCK_STATUS 39
95230
+#define PragTyp_PARSER_TRACE 40
95231
+#define PragFlag_NeedSchema 0x01
9497995232
static const struct sPragmaNames {
9498095233
const char *const zName; /* Name of pragma */
9498195234
u8 ePragTyp; /* PragTyp_XXX value */
95235
+ u8 mPragFlag; /* Zero or more PragFlag_XXX values */
9498295236
u32 iArg; /* Extra argument */
9498395237
} aPragmaNames[] = {
9498495238
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
94985
- { "activate_extensions", PragTyp_ACTIVATE_EXTENSIONS, 0 },
95239
+ { /* zName: */ "activate_extensions",
95240
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
95241
+ /* ePragFlag: */ 0,
95242
+ /* iArg: */ 0 },
9498695243
#endif
9498795244
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
94988
- { "application_id", PragTyp_HEADER_VALUE, 0 },
95245
+ { /* zName: */ "application_id",
95246
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95247
+ /* ePragFlag: */ 0,
95248
+ /* iArg: */ 0 },
9498995249
#endif
9499095250
#if !defined(SQLITE_OMIT_AUTOVACUUM)
94991
- { "auto_vacuum", PragTyp_AUTO_VACUUM, 0 },
95251
+ { /* zName: */ "auto_vacuum",
95252
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM,
95253
+ /* ePragFlag: */ PragFlag_NeedSchema,
95254
+ /* iArg: */ 0 },
9499295255
#endif
9499395256
#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
94994
- { "automatic_index", PragTyp_FLAG,
94995
- SQLITE_AutoIndex },
95257
+ { /* zName: */ "automatic_index",
95258
+ /* ePragTyp: */ PragTyp_FLAG,
95259
+ /* ePragFlag: */ 0,
95260
+ /* iArg: */ SQLITE_AutoIndex },
9499695261
#endif
94997
- { "busy_timeout", PragTyp_BUSY_TIMEOUT, 0 },
95262
+ { /* zName: */ "busy_timeout",
95263
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
95264
+ /* ePragFlag: */ 0,
95265
+ /* iArg: */ 0 },
9499895266
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
94999
- { "cache_size", PragTyp_CACHE_SIZE, 0 },
95267
+ { /* zName: */ "cache_size",
95268
+ /* ePragTyp: */ PragTyp_CACHE_SIZE,
95269
+ /* ePragFlag: */ PragFlag_NeedSchema,
95270
+ /* iArg: */ 0 },
9500095271
#endif
95001
- { "cache_spill", PragTyp_FLAG,
95002
- SQLITE_CacheSpill },
95003
- { "case_sensitive_like", PragTyp_CASE_SENSITIVE_LIKE, 0 },
95004
- { "checkpoint_fullfsync", PragTyp_FLAG,
95005
- SQLITE_CkptFullFSync },
95272
+ { /* zName: */ "cache_spill",
95273
+ /* ePragTyp: */ PragTyp_FLAG,
95274
+ /* ePragFlag: */ 0,
95275
+ /* iArg: */ SQLITE_CacheSpill },
95276
+ { /* zName: */ "case_sensitive_like",
95277
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
95278
+ /* ePragFlag: */ 0,
95279
+ /* iArg: */ 0 },
95280
+ { /* zName: */ "checkpoint_fullfsync",
95281
+ /* ePragTyp: */ PragTyp_FLAG,
95282
+ /* ePragFlag: */ 0,
95283
+ /* iArg: */ SQLITE_CkptFullFSync },
9500695284
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95007
- { "collation_list", PragTyp_COLLATION_LIST, 0 },
95285
+ { /* zName: */ "collation_list",
95286
+ /* ePragTyp: */ PragTyp_COLLATION_LIST,
95287
+ /* ePragFlag: */ 0,
95288
+ /* iArg: */ 0 },
9500895289
#endif
9500995290
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95010
- { "compile_options", PragTyp_COMPILE_OPTIONS, 0 },
95291
+ { /* zName: */ "compile_options",
95292
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
95293
+ /* ePragFlag: */ 0,
95294
+ /* iArg: */ 0 },
9501195295
#endif
95012
- { "count_changes", PragTyp_FLAG,
95013
- SQLITE_CountRows },
95296
+ { /* zName: */ "count_changes",
95297
+ /* ePragTyp: */ PragTyp_FLAG,
95298
+ /* ePragFlag: */ 0,
95299
+ /* iArg: */ SQLITE_CountRows },
9501495300
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95015
- { "data_store_directory", PragTyp_DATA_STORE_DIRECTORY, 0 },
95301
+ { /* zName: */ "data_store_directory",
95302
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
95303
+ /* ePragFlag: */ 0,
95304
+ /* iArg: */ 0 },
9501695305
#endif
9501795306
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95018
- { "database_list", PragTyp_DATABASE_LIST, 0 },
95307
+ { /* zName: */ "database_list",
95308
+ /* ePragTyp: */ PragTyp_DATABASE_LIST,
95309
+ /* ePragFlag: */ PragFlag_NeedSchema,
95310
+ /* iArg: */ 0 },
9501995311
#endif
9502095312
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95021
- { "default_cache_size", PragTyp_DEFAULT_CACHE_SIZE, 0 },
95313
+ { /* zName: */ "default_cache_size",
95314
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
95315
+ /* ePragFlag: */ PragFlag_NeedSchema,
95316
+ /* iArg: */ 0 },
9502295317
#endif
9502395318
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95024
- { "defer_foreign_keys", PragTyp_FLAG,
95025
- SQLITE_DeferFKs },
95319
+ { /* zName: */ "defer_foreign_keys",
95320
+ /* ePragTyp: */ PragTyp_FLAG,
95321
+ /* ePragFlag: */ 0,
95322
+ /* iArg: */ SQLITE_DeferFKs },
9502695323
#endif
95027
- { "empty_result_callbacks", PragTyp_FLAG,
95028
- SQLITE_NullCallback },
95324
+ { /* zName: */ "empty_result_callbacks",
95325
+ /* ePragTyp: */ PragTyp_FLAG,
95326
+ /* ePragFlag: */ 0,
95327
+ /* iArg: */ SQLITE_NullCallback },
9502995328
#if !defined(SQLITE_OMIT_UTF16)
95030
- { "encoding", PragTyp_ENCODING, 0 },
95329
+ { /* zName: */ "encoding",
95330
+ /* ePragTyp: */ PragTyp_ENCODING,
95331
+ /* ePragFlag: */ 0,
95332
+ /* iArg: */ 0 },
9503195333
#endif
9503295334
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95033
- { "foreign_key_check", PragTyp_FOREIGN_KEY_CHECK, 0 },
95335
+ { /* zName: */ "foreign_key_check",
95336
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
95337
+ /* ePragFlag: */ PragFlag_NeedSchema,
95338
+ /* iArg: */ 0 },
9503495339
#endif
9503595340
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
95036
- { "foreign_key_list", PragTyp_FOREIGN_KEY_LIST, 0 },
95341
+ { /* zName: */ "foreign_key_list",
95342
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
95343
+ /* ePragFlag: */ PragFlag_NeedSchema,
95344
+ /* iArg: */ 0 },
9503795345
#endif
9503895346
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95039
- { "foreign_keys", PragTyp_FLAG,
95040
- SQLITE_ForeignKeys },
95347
+ { /* zName: */ "foreign_keys",
95348
+ /* ePragTyp: */ PragTyp_FLAG,
95349
+ /* ePragFlag: */ 0,
95350
+ /* iArg: */ SQLITE_ForeignKeys },
9504195351
#endif
9504295352
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95043
- { "freelist_count", PragTyp_HEADER_VALUE, 0 },
95353
+ { /* zName: */ "freelist_count",
95354
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95355
+ /* ePragFlag: */ 0,
95356
+ /* iArg: */ 0 },
9504495357
#endif
95045
- { "full_column_names", PragTyp_FLAG,
95046
- SQLITE_FullColNames },
95047
- { "fullfsync", PragTyp_FLAG,
95048
- SQLITE_FullFSync },
95358
+ { /* zName: */ "full_column_names",
95359
+ /* ePragTyp: */ PragTyp_FLAG,
95360
+ /* ePragFlag: */ 0,
95361
+ /* iArg: */ SQLITE_FullColNames },
95362
+ { /* zName: */ "fullfsync",
95363
+ /* ePragTyp: */ PragTyp_FLAG,
95364
+ /* ePragFlag: */ 0,
95365
+ /* iArg: */ SQLITE_FullFSync },
9504995366
#if defined(SQLITE_HAS_CODEC)
95050
- { "hexkey", PragTyp_HEXKEY, 0 },
95367
+ { /* zName: */ "hexkey",
95368
+ /* ePragTyp: */ PragTyp_HEXKEY,
95369
+ /* ePragFlag: */ 0,
95370
+ /* iArg: */ 0 },
95371
+ { /* zName: */ "hexrekey",
95372
+ /* ePragTyp: */ PragTyp_HEXKEY,
95373
+ /* ePragFlag: */ 0,
95374
+ /* iArg: */ 0 },
9505195375
#endif
9505295376
#if !defined(SQLITE_OMIT_CHECK)
95053
- { "ignore_check_constraints", PragTyp_FLAG,
95054
- SQLITE_IgnoreChecks },
95377
+ { /* zName: */ "ignore_check_constraints",
95378
+ /* ePragTyp: */ PragTyp_FLAG,
95379
+ /* ePragFlag: */ 0,
95380
+ /* iArg: */ SQLITE_IgnoreChecks },
9505595381
#endif
9505695382
#if !defined(SQLITE_OMIT_AUTOVACUUM)
95057
- { "incremental_vacuum", PragTyp_INCREMENTAL_VACUUM, 0 },
95383
+ { /* zName: */ "incremental_vacuum",
95384
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
95385
+ /* ePragFlag: */ PragFlag_NeedSchema,
95386
+ /* iArg: */ 0 },
9505895387
#endif
9505995388
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95060
- { "index_info", PragTyp_INDEX_INFO, 0 },
95061
- { "index_list", PragTyp_INDEX_LIST, 0 },
95389
+ { /* zName: */ "index_info",
95390
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
95391
+ /* ePragFlag: */ PragFlag_NeedSchema,
95392
+ /* iArg: */ 0 },
95393
+ { /* zName: */ "index_list",
95394
+ /* ePragTyp: */ PragTyp_INDEX_LIST,
95395
+ /* ePragFlag: */ PragFlag_NeedSchema,
95396
+ /* iArg: */ 0 },
9506295397
#endif
9506395398
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95064
- { "integrity_check", PragTyp_INTEGRITY_CHECK, 0 },
95399
+ { /* zName: */ "integrity_check",
95400
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95401
+ /* ePragFlag: */ PragFlag_NeedSchema,
95402
+ /* iArg: */ 0 },
9506595403
#endif
9506695404
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95067
- { "journal_mode", PragTyp_JOURNAL_MODE, 0 },
95068
- { "journal_size_limit", PragTyp_JOURNAL_SIZE_LIMIT, 0 },
95405
+ { /* zName: */ "journal_mode",
95406
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE,
95407
+ /* ePragFlag: */ PragFlag_NeedSchema,
95408
+ /* iArg: */ 0 },
95409
+ { /* zName: */ "journal_size_limit",
95410
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
95411
+ /* ePragFlag: */ 0,
95412
+ /* iArg: */ 0 },
9506995413
#endif
9507095414
#if defined(SQLITE_HAS_CODEC)
95071
- { "key", PragTyp_KEY, 0 },
95415
+ { /* zName: */ "key",
95416
+ /* ePragTyp: */ PragTyp_KEY,
95417
+ /* ePragFlag: */ 0,
95418
+ /* iArg: */ 0 },
9507295419
#endif
95073
- { "legacy_file_format", PragTyp_FLAG,
95074
- SQLITE_LegacyFileFmt },
95420
+ { /* zName: */ "legacy_file_format",
95421
+ /* ePragTyp: */ PragTyp_FLAG,
95422
+ /* ePragFlag: */ 0,
95423
+ /* iArg: */ SQLITE_LegacyFileFmt },
9507595424
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95076
- { "lock_proxy_file", PragTyp_LOCK_PROXY_FILE, 0 },
95425
+ { /* zName: */ "lock_proxy_file",
95426
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
95427
+ /* ePragFlag: */ 0,
95428
+ /* iArg: */ 0 },
9507795429
#endif
9507895430
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95079
- { "lock_status", PragTyp_LOCK_STATUS, 0 },
95080
-#endif
95081
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95082
- { "locking_mode", PragTyp_LOCKING_MODE, 0 },
95083
- { "max_page_count", PragTyp_PAGE_COUNT, 0 },
95084
- { "mmap_size", PragTyp_MMAP_SIZE, 0 },
95085
- { "page_count", PragTyp_PAGE_COUNT, 0 },
95086
- { "page_size", PragTyp_PAGE_SIZE, 0 },
95087
-#endif
95088
-#if defined(SQLITE_DEBUG)
95089
- { "parser_trace", PragTyp_PARSER_TRACE, 0 },
95090
-#endif
95091
- { "query_only", PragTyp_FLAG,
95092
- SQLITE_QueryOnly },
95093
-#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95094
- { "quick_check", PragTyp_INTEGRITY_CHECK, 0 },
95095
-#endif
95096
- { "read_uncommitted", PragTyp_FLAG,
95097
- SQLITE_ReadUncommitted },
95098
- { "recursive_triggers", PragTyp_FLAG,
95099
- SQLITE_RecTriggers },
95100
-#if defined(SQLITE_HAS_CODEC)
95101
- { "rekey", PragTyp_REKEY, 0 },
95102
-#endif
95103
- { "reverse_unordered_selects", PragTyp_FLAG,
95104
- SQLITE_ReverseOrder },
95105
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95106
- { "schema_version", PragTyp_HEADER_VALUE, 0 },
95107
-#endif
95108
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95109
- { "secure_delete", PragTyp_SECURE_DELETE, 0 },
95110
-#endif
95111
- { "short_column_names", PragTyp_FLAG,
95112
- SQLITE_ShortColNames },
95113
- { "shrink_memory", PragTyp_SHRINK_MEMORY, 0 },
95114
- { "soft_heap_limit", PragTyp_SOFT_HEAP_LIMIT, 0 },
95115
-#if defined(SQLITE_DEBUG)
95116
- { "sql_trace", PragTyp_FLAG,
95117
- SQLITE_SqlTrace },
95118
-#endif
95119
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95120
- { "synchronous", PragTyp_SYNCHRONOUS, 0 },
95431
+ { /* zName: */ "lock_status",
95432
+ /* ePragTyp: */ PragTyp_LOCK_STATUS,
95433
+ /* ePragFlag: */ 0,
95434
+ /* iArg: */ 0 },
95435
+#endif
95436
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95437
+ { /* zName: */ "locking_mode",
95438
+ /* ePragTyp: */ PragTyp_LOCKING_MODE,
95439
+ /* ePragFlag: */ 0,
95440
+ /* iArg: */ 0 },
95441
+ { /* zName: */ "max_page_count",
95442
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
95443
+ /* ePragFlag: */ PragFlag_NeedSchema,
95444
+ /* iArg: */ 0 },
95445
+ { /* zName: */ "mmap_size",
95446
+ /* ePragTyp: */ PragTyp_MMAP_SIZE,
95447
+ /* ePragFlag: */ 0,
95448
+ /* iArg: */ 0 },
95449
+ { /* zName: */ "page_count",
95450
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
95451
+ /* ePragFlag: */ PragFlag_NeedSchema,
95452
+ /* iArg: */ 0 },
95453
+ { /* zName: */ "page_size",
95454
+ /* ePragTyp: */ PragTyp_PAGE_SIZE,
95455
+ /* ePragFlag: */ 0,
95456
+ /* iArg: */ 0 },
95457
+#endif
95458
+#if defined(SQLITE_DEBUG)
95459
+ { /* zName: */ "parser_trace",
95460
+ /* ePragTyp: */ PragTyp_PARSER_TRACE,
95461
+ /* ePragFlag: */ 0,
95462
+ /* iArg: */ 0 },
95463
+#endif
95464
+ { /* zName: */ "query_only",
95465
+ /* ePragTyp: */ PragTyp_FLAG,
95466
+ /* ePragFlag: */ 0,
95467
+ /* iArg: */ SQLITE_QueryOnly },
95468
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95469
+ { /* zName: */ "quick_check",
95470
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95471
+ /* ePragFlag: */ PragFlag_NeedSchema,
95472
+ /* iArg: */ 0 },
95473
+#endif
95474
+ { /* zName: */ "read_uncommitted",
95475
+ /* ePragTyp: */ PragTyp_FLAG,
95476
+ /* ePragFlag: */ 0,
95477
+ /* iArg: */ SQLITE_ReadUncommitted },
95478
+ { /* zName: */ "recursive_triggers",
95479
+ /* ePragTyp: */ PragTyp_FLAG,
95480
+ /* ePragFlag: */ 0,
95481
+ /* iArg: */ SQLITE_RecTriggers },
95482
+#if defined(SQLITE_HAS_CODEC)
95483
+ { /* zName: */ "rekey",
95484
+ /* ePragTyp: */ PragTyp_REKEY,
95485
+ /* ePragFlag: */ 0,
95486
+ /* iArg: */ 0 },
95487
+#endif
95488
+ { /* zName: */ "reverse_unordered_selects",
95489
+ /* ePragTyp: */ PragTyp_FLAG,
95490
+ /* ePragFlag: */ 0,
95491
+ /* iArg: */ SQLITE_ReverseOrder },
95492
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95493
+ { /* zName: */ "schema_version",
95494
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95495
+ /* ePragFlag: */ 0,
95496
+ /* iArg: */ 0 },
95497
+#endif
95498
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95499
+ { /* zName: */ "secure_delete",
95500
+ /* ePragTyp: */ PragTyp_SECURE_DELETE,
95501
+ /* ePragFlag: */ 0,
95502
+ /* iArg: */ 0 },
95503
+#endif
95504
+ { /* zName: */ "short_column_names",
95505
+ /* ePragTyp: */ PragTyp_FLAG,
95506
+ /* ePragFlag: */ 0,
95507
+ /* iArg: */ SQLITE_ShortColNames },
95508
+ { /* zName: */ "shrink_memory",
95509
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
95510
+ /* ePragFlag: */ 0,
95511
+ /* iArg: */ 0 },
95512
+ { /* zName: */ "soft_heap_limit",
95513
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
95514
+ /* ePragFlag: */ 0,
95515
+ /* iArg: */ 0 },
95516
+#if defined(SQLITE_DEBUG)
95517
+ { /* zName: */ "sql_trace",
95518
+ /* ePragTyp: */ PragTyp_FLAG,
95519
+ /* ePragFlag: */ 0,
95520
+ /* iArg: */ SQLITE_SqlTrace },
95521
+#endif
95522
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95523
+ { /* zName: */ "stats",
95524
+ /* ePragTyp: */ PragTyp_STATS,
95525
+ /* ePragFlag: */ PragFlag_NeedSchema,
95526
+ /* iArg: */ 0 },
95527
+#endif
95528
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95529
+ { /* zName: */ "synchronous",
95530
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS,
95531
+ /* ePragFlag: */ PragFlag_NeedSchema,
95532
+ /* iArg: */ 0 },
9512195533
#endif
9512295534
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95123
- { "table_info", PragTyp_TABLE_INFO, 0 },
95535
+ { /* zName: */ "table_info",
95536
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
95537
+ /* ePragFlag: */ PragFlag_NeedSchema,
95538
+ /* iArg: */ 0 },
9512495539
#endif
9512595540
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95126
- { "temp_store", PragTyp_TEMP_STORE, 0 },
95127
- { "temp_store_directory", PragTyp_TEMP_STORE_DIRECTORY, 0 },
95541
+ { /* zName: */ "temp_store",
95542
+ /* ePragTyp: */ PragTyp_TEMP_STORE,
95543
+ /* ePragFlag: */ 0,
95544
+ /* iArg: */ 0 },
95545
+ { /* zName: */ "temp_store_directory",
95546
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
95547
+ /* ePragFlag: */ 0,
95548
+ /* iArg: */ 0 },
9512895549
#endif
9512995550
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95130
- { "user_version", PragTyp_HEADER_VALUE, 0 },
95551
+ { /* zName: */ "user_version",
95552
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
95553
+ /* ePragFlag: */ 0,
95554
+ /* iArg: */ 0 },
9513195555
#endif
9513295556
#if defined(SQLITE_DEBUG)
95133
- { "vdbe_addoptrace", PragTyp_FLAG,
95134
- SQLITE_VdbeAddopTrace },
95135
- { "vdbe_debug", PragTyp_FLAG,
95136
- SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95137
- { "vdbe_listing", PragTyp_FLAG,
95138
- SQLITE_VdbeListing },
95139
- { "vdbe_trace", PragTyp_FLAG,
95140
- SQLITE_VdbeTrace },
95557
+ { /* zName: */ "vdbe_addoptrace",
95558
+ /* ePragTyp: */ PragTyp_FLAG,
95559
+ /* ePragFlag: */ 0,
95560
+ /* iArg: */ SQLITE_VdbeAddopTrace },
95561
+ { /* zName: */ "vdbe_debug",
95562
+ /* ePragTyp: */ PragTyp_FLAG,
95563
+ /* ePragFlag: */ 0,
95564
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95565
+ { /* zName: */ "vdbe_listing",
95566
+ /* ePragTyp: */ PragTyp_FLAG,
95567
+ /* ePragFlag: */ 0,
95568
+ /* iArg: */ SQLITE_VdbeListing },
95569
+ { /* zName: */ "vdbe_trace",
95570
+ /* ePragTyp: */ PragTyp_FLAG,
95571
+ /* ePragFlag: */ 0,
95572
+ /* iArg: */ SQLITE_VdbeTrace },
9514195573
#endif
9514295574
#if !defined(SQLITE_OMIT_WAL)
95143
- { "wal_autocheckpoint", PragTyp_WAL_AUTOCHECKPOINT, 0 },
95144
- { "wal_checkpoint", PragTyp_WAL_CHECKPOINT, 0 },
95575
+ { /* zName: */ "wal_autocheckpoint",
95576
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
95577
+ /* ePragFlag: */ 0,
95578
+ /* iArg: */ 0 },
95579
+ { /* zName: */ "wal_checkpoint",
95580
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
95581
+ /* ePragFlag: */ PragFlag_NeedSchema,
95582
+ /* iArg: */ 0 },
9514595583
#endif
95146
- { "writable_schema", PragTyp_FLAG,
95147
- SQLITE_WriteSchema|SQLITE_RecoveryMode },
95584
+ { /* zName: */ "writable_schema",
95585
+ /* ePragTyp: */ PragTyp_FLAG,
95586
+ /* ePragFlag: */ 0,
95587
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
9514895588
};
95149
-/* Number of pragmas: 55 on by default, 66 total. */
95589
+/* Number of pragmas: 56 on by default, 68 total. */
9515095590
/* End of the automatically generated pragma table.
9515195591
***************************************************************************/
9515295592
9515395593
/*
9515495594
** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95916,15 @@
9547695916
}else{
9547795917
lwr = mid + 1;
9547895918
}
9547995919
}
9548095920
if( lwr>upr ) goto pragma_out;
95921
+
95922
+ /* Make sure the database schema is loaded if the pragma requires that */
95923
+ if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
95924
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95925
+ }
9548195926
9548295927
/* Jump to the appropriate pragma handler */
9548395928
switch( aPragmaNames[mid].ePragTyp ){
9548495929
9548595930
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95955,10 @@
9551095955
{ OP_Integer, 0, 1, 0}, /* 6 */
9551195956
{ OP_Noop, 0, 0, 0},
9551295957
{ OP_ResultRow, 1, 1, 0},
9551395958
};
9551495959
int addr;
95515
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9551695960
sqlite3VdbeUsesBtree(v, iDb);
9551795961
if( !zRight ){
9551895962
sqlite3VdbeSetNumCols(v, 1);
9551995963
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
9552095964
pParse->nMem += 2;
@@ -95606,11 +96050,10 @@
9560696050
**
9560796051
** Return the number of pages in the specified database.
9560896052
*/
9560996053
case PragTyp_PAGE_COUNT: {
9561096054
int iReg;
95611
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9561296055
sqlite3CodeVerifySchema(pParse, iDb);
9561396056
iReg = ++pParse->nMem;
9561496057
if( sqlite3Tolower(zLeft[0])=='p' ){
9561596058
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
9561696059
}else{
@@ -95679,18 +96122,10 @@
9567996122
*/
9568096123
case PragTyp_JOURNAL_MODE: {
9568196124
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
9568296125
int ii; /* Loop counter */
9568396126
95684
- /* Force the schema to be loaded on all databases. This causes all
95685
- ** database files to be opened and the journal_modes set. This is
95686
- ** necessary because subsequent processing must know if the databases
95687
- ** are in WAL mode. */
95688
- if( sqlite3ReadSchema(pParse) ){
95689
- goto pragma_out;
95690
- }
95691
-
9569296127
sqlite3VdbeSetNumCols(v, 1);
9569396128
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
9569496129
9569596130
if( zRight==0 ){
9569696131
/* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96187,44 @@
9575296187
*/
9575396188
#ifndef SQLITE_OMIT_AUTOVACUUM
9575496189
case PragTyp_AUTO_VACUUM: {
9575596190
Btree *pBt = pDb->pBt;
9575696191
assert( pBt!=0 );
95757
- if( sqlite3ReadSchema(pParse) ){
95758
- goto pragma_out;
95759
- }
9576096192
if( !zRight ){
95761
- int auto_vacuum;
95762
- if( ALWAYS(pBt) ){
95763
- auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
95764
- }else{
95765
- auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
95766
- }
95767
- returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
96193
+ returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
9576896194
}else{
9576996195
int eAuto = getAutoVacuum(zRight);
9577096196
assert( eAuto>=0 && eAuto<=2 );
9577196197
db->nextAutovac = (u8)eAuto;
95772
- if( ALWAYS(eAuto>=0) ){
95773
- /* Call SetAutoVacuum() to set initialize the internal auto and
95774
- ** incr-vacuum flags. This is required in case this connection
95775
- ** creates the database file. It is important that it is created
95776
- ** as an auto-vacuum capable db.
95777
- */
95778
- rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
95779
- if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
95780
- /* When setting the auto_vacuum mode to either "full" or
95781
- ** "incremental", write the value of meta[6] in the database
95782
- ** file. Before writing to meta[6], check that meta[3] indicates
95783
- ** that this really is an auto-vacuum capable database.
95784
- */
95785
- static const VdbeOpList setMeta6[] = {
95786
- { OP_Transaction, 0, 1, 0}, /* 0 */
95787
- { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
95788
- { OP_If, 1, 0, 0}, /* 2 */
95789
- { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
95790
- { OP_Integer, 0, 1, 0}, /* 4 */
95791
- { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
95792
- };
95793
- int iAddr;
95794
- iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
95795
- sqlite3VdbeChangeP1(v, iAddr, iDb);
95796
- sqlite3VdbeChangeP1(v, iAddr+1, iDb);
95797
- sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
95798
- sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
95799
- sqlite3VdbeChangeP1(v, iAddr+5, iDb);
95800
- sqlite3VdbeUsesBtree(v, iDb);
95801
- }
96198
+ /* Call SetAutoVacuum() to set initialize the internal auto and
96199
+ ** incr-vacuum flags. This is required in case this connection
96200
+ ** creates the database file. It is important that it is created
96201
+ ** as an auto-vacuum capable db.
96202
+ */
96203
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
96204
+ if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
96205
+ /* When setting the auto_vacuum mode to either "full" or
96206
+ ** "incremental", write the value of meta[6] in the database
96207
+ ** file. Before writing to meta[6], check that meta[3] indicates
96208
+ ** that this really is an auto-vacuum capable database.
96209
+ */
96210
+ static const VdbeOpList setMeta6[] = {
96211
+ { OP_Transaction, 0, 1, 0}, /* 0 */
96212
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
96213
+ { OP_If, 1, 0, 0}, /* 2 */
96214
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
96215
+ { OP_Integer, 0, 1, 0}, /* 4 */
96216
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
96217
+ };
96218
+ int iAddr;
96219
+ iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
96220
+ sqlite3VdbeChangeP1(v, iAddr, iDb);
96221
+ sqlite3VdbeChangeP1(v, iAddr+1, iDb);
96222
+ sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
96223
+ sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
96224
+ sqlite3VdbeChangeP1(v, iAddr+5, iDb);
96225
+ sqlite3VdbeUsesBtree(v, iDb);
9580296226
}
9580396227
}
9580496228
break;
9580596229
}
9580696230
#endif
@@ -95811,13 +96235,10 @@
9581196235
** Do N steps of incremental vacuuming on a database.
9581296236
*/
9581396237
#ifndef SQLITE_OMIT_AUTOVACUUM
9581496238
case PragTyp_INCREMENTAL_VACUUM: {
9581596239
int iLimit, addr;
95816
- if( sqlite3ReadSchema(pParse) ){
95817
- goto pragma_out;
95818
- }
9581996240
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
9582096241
iLimit = 0x7fffffff;
9582196242
}
9582296243
sqlite3BeginWriteOperation(pParse, 0, iDb);
9582396244
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96262,10 @@
9584196262
** number of pages in the cache. If N is negative, then the
9584296263
** number of pages is adjusted so that the cache uses -N kibibytes
9584396264
** of memory.
9584496265
*/
9584596266
case PragTyp_CACHE_SIZE: {
95846
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9584796267
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
9584896268
if( !zRight ){
9584996269
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
9585096270
}else{
9585196271
int size = sqlite3Atoi(zRight);
@@ -96062,11 +96482,10 @@
9606296482
** the local value does not make changes to the disk file and the
9606396483
** default value will be restored the next time the database is
9606496484
** opened.
9606596485
*/
9606696486
case PragTyp_SYNCHRONOUS: {
96067
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9606896487
if( !zRight ){
9606996488
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
9607096489
}else{
9607196490
if( !db->autoCommit ){
9607296491
sqlite3ErrorMsg(pParse,
@@ -96124,11 +96543,10 @@
9612496543
** notnull: True if 'NOT NULL' is part of column declaration
9612596544
** dflt_value: The default value for the column, if any.
9612696545
*/
9612796546
case PragTyp_TABLE_INFO: if( zRight ){
9612896547
Table *pTab;
96129
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9613096548
pTab = sqlite3FindTable(db, zRight, zDb);
9613196549
if( pTab ){
9613296550
int i, k;
9613396551
int nHidden = 0;
9613496552
Column *pCol;
@@ -96170,15 +96588,44 @@
9617096588
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
9617196589
}
9617296590
}
9617396591
}
9617496592
break;
96593
+
96594
+ case PragTyp_STATS: {
96595
+ Index *pIdx;
96596
+ HashElem *i;
96597
+ v = sqlite3GetVdbe(pParse);
96598
+ sqlite3VdbeSetNumCols(v, 4);
96599
+ pParse->nMem = 4;
96600
+ sqlite3CodeVerifySchema(pParse, iDb);
96601
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
96602
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC);
96603
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC);
96604
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC);
96605
+ for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
96606
+ Table *pTab = sqliteHashData(i);
96607
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0);
96608
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
96609
+ sqlite3VdbeAddOp2(v, OP_Integer,
96610
+ (int)sqlite3LogEstToInt(pTab->szTabRow), 3);
96611
+ sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4);
96612
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96613
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
96614
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96615
+ sqlite3VdbeAddOp2(v, OP_Integer,
96616
+ (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
96617
+ sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
96618
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96619
+ }
96620
+ }
96621
+ }
96622
+ break;
9617596623
9617696624
case PragTyp_INDEX_INFO: if( zRight ){
9617796625
Index *pIdx;
9617896626
Table *pTab;
96179
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9618096627
pIdx = sqlite3FindIndex(db, zRight, zDb);
9618196628
if( pIdx ){
9618296629
int i;
9618396630
pTab = pIdx->pTable;
9618496631
sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96647,32 @@
9620096647
break;
9620196648
9620296649
case PragTyp_INDEX_LIST: if( zRight ){
9620396650
Index *pIdx;
9620496651
Table *pTab;
96205
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96652
+ int i;
9620696653
pTab = sqlite3FindTable(db, zRight, zDb);
9620796654
if( pTab ){
9620896655
v = sqlite3GetVdbe(pParse);
96209
- pIdx = pTab->pIndex;
96210
- if( pIdx ){
96211
- int i = 0;
96212
- sqlite3VdbeSetNumCols(v, 3);
96213
- pParse->nMem = 3;
96214
- sqlite3CodeVerifySchema(pParse, iDb);
96215
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96216
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96217
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96218
- while(pIdx){
96219
- sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96220
- sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96221
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96222
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
96223
- ++i;
96224
- pIdx = pIdx->pNext;
96225
- }
96656
+ sqlite3VdbeSetNumCols(v, 3);
96657
+ pParse->nMem = 3;
96658
+ sqlite3CodeVerifySchema(pParse, iDb);
96659
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96660
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96661
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96662
+ for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
96663
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96664
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96665
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96666
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
9622696667
}
9622796668
}
9622896669
}
9622996670
break;
9623096671
9623196672
case PragTyp_DATABASE_LIST: {
9623296673
int i;
96233
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9623496674
sqlite3VdbeSetNumCols(v, 3);
9623596675
pParse->nMem = 3;
9623696676
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
9623796677
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
9623896678
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96707,10 @@
9626796707
9626896708
#ifndef SQLITE_OMIT_FOREIGN_KEY
9626996709
case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
9627096710
FKey *pFK;
9627196711
Table *pTab;
96272
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9627396712
pTab = sqlite3FindTable(db, zRight, zDb);
9627496713
if( pTab ){
9627596714
v = sqlite3GetVdbe(pParse);
9627696715
pFK = pTab->pFKey;
9627796716
if( pFK ){
@@ -96329,11 +96768,10 @@
9632996768
int regRow; /* Registers to hold a row from pTab */
9633096769
int addrTop; /* Top of a loop checking foreign keys */
9633196770
int addrOk; /* Jump here if the key is OK */
9633296771
int *aiCols; /* child to parent column mapping */
9633396772
96334
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9633596773
regResult = pParse->nMem+1;
9633696774
pParse->nMem += 4;
9633796775
regKey = ++pParse->nMem;
9633896776
regRow = ++pParse->nMem;
9633996777
v = sqlite3GetVdbe(pParse);
@@ -96357,12 +96795,12 @@
9635796795
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
9635896796
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
9635996797
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
9636096798
P4_TRANSIENT);
9636196799
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96362
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
96363
- if( pParent==0 ) break;
96800
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb);
96801
+ if( pParent==0 ) continue;
9636496802
pIdx = 0;
9636596803
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
9636696804
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
9636796805
if( x==0 ){
9636896806
if( pIdx==0 ){
@@ -96375,22 +96813,24 @@
9637596813
}else{
9637696814
k = 0;
9637796815
break;
9637896816
}
9637996817
}
96818
+ assert( pParse->nErr>0 || pFK==0 );
9638096819
if( pFK ) break;
9638196820
if( pParse->nTab<i ) pParse->nTab = i;
9638296821
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
9638396822
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96384
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
96385
- assert( pParent!=0 );
96823
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb);
9638696824
pIdx = 0;
9638796825
aiCols = 0;
96388
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
96389
- assert( x==0 );
96826
+ if( pParent ){
96827
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
96828
+ assert( x==0 );
96829
+ }
9639096830
addrOk = sqlite3VdbeMakeLabel(v);
96391
- if( pIdx==0 ){
96831
+ if( pParent && pIdx==0 ){
9639296832
int iKey = pFK->aCol[0].iFrom;
9639396833
assert( iKey>=0 && iKey<pTab->nCol );
9639496834
if( iKey!=pTab->iPKey ){
9639596835
sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
9639696836
sqlite3ColumnDefault(v, pTab, iKey, regRow);
@@ -96404,17 +96844,19 @@
9640496844
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
9640596845
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
9640696846
}else{
9640796847
for(j=0; j<pFK->nCol; j++){
9640896848
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
96409
- aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
96849
+ aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
9641096850
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
9641196851
}
96412
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
96413
- sqlite3VdbeChangeP4(v, -1,
96414
- sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
96415
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
96852
+ if( pParent ){
96853
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
96854
+ sqlite3VdbeChangeP4(v, -1,
96855
+ sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
96856
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
96857
+ }
9641696858
}
9641796859
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
9641896860
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
9641996861
pFK->zTo, P4_TRANSIENT);
9642096862
sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
@@ -96490,11 +96932,10 @@
9649096932
assert( iDb>=0 );
9649196933
assert( iDb==0 || pId2->z );
9649296934
if( pId2->z==0 ) iDb = -1;
9649396935
9649496936
/* Initialize the VDBE program */
96495
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9649696937
pParse->nMem = 6;
9649796938
sqlite3VdbeSetNumCols(v, 1);
9649896939
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
9649996940
9650096941
/* Set the maximum error count */
@@ -96814,11 +97255,10 @@
9681497255
eMode = SQLITE_CHECKPOINT_FULL;
9681597256
}else if( sqlite3StrICmp(zRight, "restart")==0 ){
9681697257
eMode = SQLITE_CHECKPOINT_RESTART;
9681797258
}
9681897259
}
96819
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
9682097260
sqlite3VdbeSetNumCols(v, 3);
9682197261
pParse->nMem = 3;
9682297262
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
9682397263
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
9682497264
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97374,16 @@
9693497374
if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
9693597375
break;
9693697376
}
9693797377
case PragTyp_HEXKEY: {
9693897378
if( zRight ){
96939
- int i, h1, h2;
97379
+ u8 iByte;
97380
+ int i;
9694097381
char zKey[40];
96941
- for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
96942
- h1 += 9*(1&(h1>>6));
96943
- h2 += 9*(1&(h2>>6));
96944
- zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
97382
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
97383
+ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
97384
+ if( (i&1)!=0 ) zKey[i/2] = iByte;
9694597385
}
9694697386
if( (zLeft[3] & 0xf)==0xb ){
9694797387
sqlite3_key_v2(db, zDb, zKey, i/2);
9694897388
}else{
9694997389
sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99353,13 @@
9891399353
}
9891499354
9891599355
/*
9891699356
** Return a pointer to a string containing the 'declaration type' of the
9891799357
** expression pExpr. The string may be treated as static by the caller.
99358
+**
99359
+** Also try to estimate the size of the returned value and return that
99360
+** result in *pEstWidth.
9891899361
**
9891999362
** The declaration type is the exact datatype definition extracted from the
9892099363
** original CREATE TABLE statement if the expression is a column. The
9892199364
** declaration type for a ROWID field is INTEGER. Exactly when an expression
9892299365
** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99370,40 @@
9892799370
** SELECT (SELECT col FROM tbl;
9892899371
** SELECT (SELECT col FROM tbl);
9892999372
** SELECT abc FROM (SELECT col AS abc FROM tbl);
9893099373
**
9893199374
** The declaration type for any expression other than a column is NULL.
99375
+**
99376
+** This routine has either 3 or 6 parameters depending on whether or not
99377
+** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
9893299378
*/
98933
-static const char *columnType(
99379
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
99380
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
99381
+static const char *columnTypeImpl(
99382
+ NameContext *pNC,
99383
+ Expr *pExpr,
99384
+ const char **pzOrigDb,
99385
+ const char **pzOrigTab,
99386
+ const char **pzOrigCol,
99387
+ u8 *pEstWidth
99388
+){
99389
+ char const *zOrigDb = 0;
99390
+ char const *zOrigTab = 0;
99391
+ char const *zOrigCol = 0;
99392
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99393
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
99394
+static const char *columnTypeImpl(
9893499395
NameContext *pNC,
9893599396
Expr *pExpr,
98936
- const char **pzOriginDb,
98937
- const char **pzOriginTab,
98938
- const char **pzOriginCol
99397
+ u8 *pEstWidth
9893999398
){
99399
+#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
9894099400
char const *zType = 0;
98941
- char const *zOriginDb = 0;
98942
- char const *zOriginTab = 0;
98943
- char const *zOriginCol = 0;
9894499401
int j;
99402
+ u8 estWidth = 1;
99403
+
9894599404
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
98946
-
9894799405
switch( pExpr->op ){
9894899406
case TK_AGG_COLUMN:
9894999407
case TK_COLUMN: {
9895099408
/* The expression is a column. Locate the table the column is being
9895199409
** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99460,39 @@
9900299460
NameContext sNC;
9900399461
Expr *p = pS->pEList->a[iCol].pExpr;
9900499462
sNC.pSrcList = pS->pSrc;
9900599463
sNC.pNext = pNC;
9900699464
sNC.pParse = pNC->pParse;
99007
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99465
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
9900899466
}
9900999467
}else if( ALWAYS(pTab->pSchema) ){
9901099468
/* A real table */
9901199469
assert( !pS );
9901299470
if( iCol<0 ) iCol = pTab->iPKey;
9901399471
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
99472
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
9901499473
if( iCol<0 ){
9901599474
zType = "INTEGER";
99016
- zOriginCol = "rowid";
99475
+ zOrigCol = "rowid";
9901799476
}else{
9901899477
zType = pTab->aCol[iCol].zType;
99019
- zOriginCol = pTab->aCol[iCol].zName;
99478
+ zOrigCol = pTab->aCol[iCol].zName;
99479
+ estWidth = pTab->aCol[iCol].szEst;
9902099480
}
99021
- zOriginTab = pTab->zName;
99481
+ zOrigTab = pTab->zName;
9902299482
if( pNC->pParse ){
9902399483
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99024
- zOriginDb = pNC->pParse->db->aDb[iDb].zName;
99484
+ zOrigDb = pNC->pParse->db->aDb[iDb].zName;
9902599485
}
99486
+#else
99487
+ if( iCol<0 ){
99488
+ zType = "INTEGER";
99489
+ }else{
99490
+ zType = pTab->aCol[iCol].zType;
99491
+ estWidth = pTab->aCol[iCol].szEst;
99492
+ }
99493
+#endif
9902699494
}
9902799495
break;
9902899496
}
9902999497
#ifndef SQLITE_OMIT_SUBQUERY
9903099498
case TK_SELECT: {
@@ -99037,22 +99505,25 @@
9903799505
Expr *p = pS->pEList->a[0].pExpr;
9903899506
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
9903999507
sNC.pSrcList = pS->pSrc;
9904099508
sNC.pNext = pNC;
9904199509
sNC.pParse = pNC->pParse;
99042
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99510
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
9904399511
break;
9904499512
}
9904599513
#endif
9904699514
}
99047
-
99048
- if( pzOriginDb ){
99049
- assert( pzOriginTab && pzOriginCol );
99050
- *pzOriginDb = zOriginDb;
99051
- *pzOriginTab = zOriginTab;
99052
- *pzOriginCol = zOriginCol;
99515
+
99516
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
99517
+ if( pzOrigDb ){
99518
+ assert( pzOrigTab && pzOrigCol );
99519
+ *pzOrigDb = zOrigDb;
99520
+ *pzOrigTab = zOrigTab;
99521
+ *pzOrigCol = zOrigCol;
9905399522
}
99523
+#endif
99524
+ if( pEstWidth ) *pEstWidth = estWidth;
9905499525
return zType;
9905599526
}
9905699527
9905799528
/*
9905899529
** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99545,25 @@
9907499545
const char *zType;
9907599546
#ifdef SQLITE_ENABLE_COLUMN_METADATA
9907699547
const char *zOrigDb = 0;
9907799548
const char *zOrigTab = 0;
9907899549
const char *zOrigCol = 0;
99079
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
99550
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
9908099551
9908199552
/* The vdbe must make its own copy of the column-type and other
9908299553
** column specific strings, in case the schema is reset before this
9908399554
** virtual machine is deleted.
9908499555
*/
9908599556
sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
9908699557
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
9908799558
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
9908899559
#else
99089
- zType = columnType(&sNC, p, 0, 0, 0);
99560
+ zType = columnType(&sNC, p, 0, 0, 0, 0);
9909099561
#endif
9909199562
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
9909299563
}
99093
-#endif /* SQLITE_OMIT_DECLTYPE */
99564
+#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
9909499565
}
9909599566
9909699567
/*
9909799568
** Generate code that will tell the VDBE the names of columns
9909899569
** in the result set. This information is used to provide the
@@ -99277,39 +99748,41 @@
9927799748
** This routine requires that all identifiers in the SELECT
9927899749
** statement be resolved.
9927999750
*/
9928099751
static void selectAddColumnTypeAndCollation(
9928199752
Parse *pParse, /* Parsing contexts */
99282
- int nCol, /* Number of columns */
99283
- Column *aCol, /* List of columns */
99753
+ Table *pTab, /* Add column type information to this table */
9928499754
Select *pSelect /* SELECT used to determine types and collations */
9928599755
){
9928699756
sqlite3 *db = pParse->db;
9928799757
NameContext sNC;
9928899758
Column *pCol;
9928999759
CollSeq *pColl;
9929099760
int i;
9929199761
Expr *p;
9929299762
struct ExprList_item *a;
99763
+ u64 szAll = 0;
9929399764
9929499765
assert( pSelect!=0 );
9929599766
assert( (pSelect->selFlags & SF_Resolved)!=0 );
99296
- assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
99767
+ assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
9929799768
if( db->mallocFailed ) return;
9929899769
memset(&sNC, 0, sizeof(sNC));
9929999770
sNC.pSrcList = pSelect->pSrc;
9930099771
a = pSelect->pEList->a;
99301
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){
99772
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
9930299773
p = a[i].pExpr;
99303
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
99774
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
99775
+ szAll += pCol->szEst;
9930499776
pCol->affinity = sqlite3ExprAffinity(p);
9930599777
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
9930699778
pColl = sqlite3ExprCollSeq(pParse, p);
9930799779
if( pColl ){
9930899780
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
9930999781
}
9931099782
}
99783
+ pTab->szTabRow = sqlite3LogEst(szAll*4);
9931199784
}
9931299785
9931399786
/*
9931499787
** Given a SELECT statement, generate a Table structure that describes
9931599788
** the result set of that SELECT.
@@ -99333,13 +99806,13 @@
9933399806
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
9933499807
** is disabled */
9933599808
assert( db->lookaside.bEnabled==0 );
9933699809
pTab->nRef = 1;
9933799810
pTab->zName = 0;
99338
- pTab->nRowEst = 1000000;
99811
+ pTab->nRowEst = 1048576;
9933999812
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99340
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
99813
+ selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
9934199814
pTab->iPKey = -1;
9934299815
if( db->mallocFailed ){
9934399816
sqlite3DeleteTable(db, pTab);
9934499817
return 0;
9934599818
}
@@ -101247,15 +101720,15 @@
101247101720
assert( pFrom->pTab==0 );
101248101721
sqlite3WalkSelect(pWalker, pSel);
101249101722
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101250101723
if( pTab==0 ) return WRC_Abort;
101251101724
pTab->nRef = 1;
101252
- pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
101725
+ pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
101253101726
while( pSel->pPrior ){ pSel = pSel->pPrior; }
101254101727
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101255101728
pTab->iPKey = -1;
101256
- pTab->nRowEst = 1000000;
101729
+ pTab->nRowEst = 1048576;
101257101730
pTab->tabFlags |= TF_Ephemeral;
101258101731
#endif
101259101732
}else{
101260101733
/* An ordinary table or view name in the FROM clause */
101261101734
assert( pFrom->pTab==0 );
@@ -101535,11 +102008,11 @@
101535102008
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
101536102009
/* A sub-query in the FROM clause of a SELECT */
101537102010
Select *pSel = pFrom->pSelect;
101538102011
assert( pSel );
101539102012
while( pSel->pPrior ) pSel = pSel->pPrior;
101540
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
102013
+ selectAddColumnTypeAndCollation(pParse, pTab, pSel);
101541102014
}
101542102015
}
101543102016
}
101544102017
return WRC_Continue;
101545102018
}
@@ -102450,29 +102923,29 @@
102450102923
int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102451102924
102452102925
sqlite3CodeVerifySchema(pParse, iDb);
102453102926
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102454102927
102455
- /* Search for the index that has the least amount of columns. If
102456
- ** there is such an index, and it has less columns than the table
102457
- ** does, then we can assume that it consumes less space on disk and
102458
- ** will therefore be cheaper to scan to determine the query result.
102459
- ** In this case set iRoot to the root page number of the index b-tree
102460
- ** and pKeyInfo to the KeyInfo structure required to navigate the
102461
- ** index.
102928
+ /* Search for the index that has the lowest scan cost.
102462102929
**
102463102930
** (2011-04-15) Do not do a full scan of an unordered index.
102931
+ **
102932
+ ** (2013-10-03) Do not count the entires in a partial index.
102464102933
**
102465102934
** In practice the KeyInfo structure will not be used. It is only
102466102935
** passed to keep OP_OpenRead happy.
102467102936
*/
102468102937
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102469
- if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
102938
+ if( pIdx->bUnordered==0
102939
+ && pIdx->szIdxRow<pTab->szTabRow
102940
+ && pIdx->pPartIdxWhere==0
102941
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
102942
+ ){
102470102943
pBest = pIdx;
102471102944
}
102472102945
}
102473
- if( pBest && pBest->nColumn<pTab->nCol ){
102946
+ if( pBest ){
102474102947
iRoot = pBest->tnum;
102475102948
pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102476102949
}
102477102950
102478102951
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103519,12 @@
103046103519
}
103047103520
103048103521
/* Ensure the table name matches database name and that the table exists */
103049103522
if( db->mallocFailed ) goto trigger_cleanup;
103050103523
assert( pTableName->nSrc==1 );
103051
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
103052
- sqlite3FixSrcList(&sFix, pTableName) ){
103524
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
103525
+ if( sqlite3FixSrcList(&sFix, pTableName) ){
103053103526
goto trigger_cleanup;
103054103527
}
103055103528
pTab = sqlite3SrcListLookup(pParse, pTableName);
103056103529
if( !pTab ){
103057103530
/* The table does not exist. */
@@ -103189,12 +103662,14 @@
103189103662
pStepList->pTrig = pTrig;
103190103663
pStepList = pStepList->pNext;
103191103664
}
103192103665
nameToken.z = pTrig->zName;
103193103666
nameToken.n = sqlite3Strlen30(nameToken.z);
103194
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
103195
- && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
103667
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
103668
+ if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
103669
+ || sqlite3FixExpr(&sFix, pTrig->pWhen)
103670
+ ){
103196103671
goto triggerfinish_cleanup;
103197103672
}
103198103673
103199103674
/* if we are not initializing,
103200103675
** build the sqlite_master entry
@@ -104781,18 +105256,38 @@
104781105256
104782105257
return vacuumFinalize(db, pStmt, pzErrMsg);
104783105258
}
104784105259
104785105260
/*
104786
-** The non-standard VACUUM command is used to clean up the database,
105261
+** The VACUUM command is used to clean up the database,
104787105262
** collapse free space, etc. It is modelled after the VACUUM command
104788
-** in PostgreSQL.
105263
+** in PostgreSQL. The VACUUM command works as follows:
104789105264
**
104790
-** In version 1.0.x of SQLite, the VACUUM command would call
104791
-** gdbm_reorganize() on all the database tables. But beginning
104792
-** with 2.0.0, SQLite no longer uses GDBM so this command has
104793
-** become a no-op.
105265
+** (1) Create a new transient database file
105266
+** (2) Copy all content from the database being vacuumed into
105267
+** the new transient database file
105268
+** (3) Copy content from the transient database back into the
105269
+** original database.
105270
+**
105271
+** The transient database requires temporary disk space approximately
105272
+** equal to the size of the original database. The copy operation of
105273
+** step (3) requires additional temporary disk space approximately equal
105274
+** to the size of the original database for the rollback journal.
105275
+** Hence, temporary disk space that is approximately 2x the size of the
105276
+** orginal database is required. Every page of the database is written
105277
+** approximately 3 times: Once for step (2) and twice for step (3).
105278
+** Two writes per page are required in step (3) because the original
105279
+** database content must be written into the rollback journal prior to
105280
+** overwriting the database with the vacuumed content.
105281
+**
105282
+** Only 1x temporary space and only 1x writes would be required if
105283
+** the copy of step (3) were replace by deleting the original database
105284
+** and renaming the transient database as the original. But that will
105285
+** not work if other processes are attached to the original database.
105286
+** And a power loss in between deleting the original and renaming the
105287
+** transient would cause the database file to appear to be deleted
105288
+** following reboot.
104794105289
*/
104795105290
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
104796105291
Vdbe *v = sqlite3GetVdbe(pParse);
104797105292
if( v ){
104798105293
sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106701,10 @@
106206106701
typedef struct WhereLoopBuilder WhereLoopBuilder;
106207106702
typedef struct WhereScan WhereScan;
106208106703
typedef struct WhereOrCost WhereOrCost;
106209106704
typedef struct WhereOrSet WhereOrSet;
106210106705
106211
-/*
106212
-** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
106213
-** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
106214
-** (Virtual tables can return a larger cost, but let's assume they do not.)
106215
-** So all costs can be stored in a 16-bit integer without risk
106216
-** of overflow.
106217
-**
106218
-** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
106219
-** Instead, a close estimate is used. Any value of X=1 is stored as 0.
106220
-** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
106221
-** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
106222
-**
106223
-** The tool/wherecosttest.c source file implements a command-line program
106224
-** that will convert WhereCosts to integers, convert integers to WhereCosts
106225
-** and do addition and multiplication on WhereCost values. The wherecosttest
106226
-** command-line program is a useful utility to have around when working with
106227
-** this module.
106228
-*/
106229
-typedef short int WhereCost;
106230
-
106231106706
/*
106232106707
** This object contains information needed to implement a single nested
106233106708
** loop in WHERE clause.
106234106709
**
106235106710
** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106765,13 @@
106290106765
#ifdef SQLITE_DEBUG
106291106766
char cId; /* Symbolic ID of this loop for debugging use */
106292106767
#endif
106293106768
u8 iTab; /* Position in FROM clause of table for this loop */
106294106769
u8 iSortIdx; /* Sorting index number. 0==None */
106295
- WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
106296
- WhereCost rRun; /* Cost of running each loop */
106297
- WhereCost nOut; /* Estimated number of output rows */
106770
+ LogEst rSetup; /* One-time setup cost (ex: create transient index) */
106771
+ LogEst rRun; /* Cost of running each loop */
106772
+ LogEst nOut; /* Estimated number of output rows */
106298106773
union {
106299106774
struct { /* Information for internal btree tables */
106300106775
int nEq; /* Number of equality constraints */
106301106776
Index *pIndex; /* Index used, or NULL */
106302106777
} btree;
@@ -106322,12 +106797,12 @@
106322106797
** subquery on one operand of an OR operator in the WHERE clause.
106323106798
** See WhereOrSet for additional information
106324106799
*/
106325106800
struct WhereOrCost {
106326106801
Bitmask prereq; /* Prerequisites */
106327
- WhereCost rRun; /* Cost of running this subquery */
106328
- WhereCost nOut; /* Number of outputs for this subquery */
106802
+ LogEst rRun; /* Cost of running this subquery */
106803
+ LogEst nOut; /* Number of outputs for this subquery */
106329106804
};
106330106805
106331106806
/* The WhereOrSet object holds a set of possible WhereOrCosts that
106332106807
** correspond to the subquery(s) of OR-clause processing. Only the
106333106808
** best N_OR_COST elements are retained.
@@ -106361,12 +106836,12 @@
106361106836
** at the end is the choosen query plan.
106362106837
*/
106363106838
struct WherePath {
106364106839
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106365106840
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106366
- WhereCost nRow; /* Estimated number of rows generated by this path */
106367
- WhereCost rCost; /* Total cost of this path */
106841
+ LogEst nRow; /* Estimated number of rows generated by this path */
106842
+ LogEst rCost; /* Total cost of this path */
106368106843
u8 isOrdered; /* True if this path satisfies ORDER BY */
106369106844
u8 isOrderedValid; /* True if the isOrdered field is valid */
106370106845
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106371106846
};
106372106847
@@ -106428,11 +106903,11 @@
106428106903
union {
106429106904
int leftColumn; /* Column number of X in "X <op> <expr>" */
106430106905
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106431106906
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106432106907
} u;
106433
- WhereCost truthProb; /* Probability of truth for this expression */
106908
+ LogEst truthProb; /* Probability of truth for this expression */
106434106909
u16 eOperator; /* A WO_xx value describing <op> */
106435106910
u8 wtFlags; /* TERM_xxx bit flags. See below */
106436106911
u8 nChild; /* Number of children that must disable us */
106437106912
WhereClause *pWC; /* The clause this term is part of */
106438106913
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +107051,11 @@
106576107051
SrcList *pTabList; /* List of tables in the join */
106577107052
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
106578107053
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
106579107054
WhereLoop *pLoops; /* List of all WhereLoop objects */
106580107055
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
106581
- WhereCost nRowOut; /* Estimated number of output rows */
107056
+ LogEst nRowOut; /* Estimated number of output rows */
106582107057
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
106583107058
u8 bOBSat; /* ORDER BY satisfied by indices */
106584107059
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
106585107060
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
106586107061
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107111,15 @@
106636107111
#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
106637107112
#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
106638107113
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
106639107114
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
106640107115
106641
-
106642
-/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
106643
-** A rough approximation is used. The value returned is not exact.
106644
-*/
106645
-static u64 whereCostToInt(WhereCost x){
106646
- u64 n;
106647
- if( x<10 ) return 1;
106648
- n = x%10;
106649
- x /= 10;
106650
- if( n>=5 ) n -= 2;
106651
- else if( n>=1 ) n -= 1;
106652
- if( x>=3 ) return (n+8)<<(x-3);
106653
- return (n+8)>>(3-x);
106654
-}
106655
-
106656107116
/*
106657107117
** Return the estimated number of output rows from a WHERE clause
106658107118
*/
106659107119
SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
106660
- return whereCostToInt(pWInfo->nRowOut);
107120
+ return sqlite3LogEstToInt(pWInfo->nRowOut);
106661107121
}
106662107122
106663107123
/*
106664107124
** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
106665107125
** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107177,12 @@
106717107177
** so that pSet keeps the N_OR_COST best entries seen so far.
106718107178
*/
106719107179
static int whereOrInsert(
106720107180
WhereOrSet *pSet, /* The WhereOrSet to be updated */
106721107181
Bitmask prereq, /* Prerequisites of the new entry */
106722
- WhereCost rRun, /* Run-cost of the new entry */
106723
- WhereCost nOut /* Number of outputs for the new entry */
107182
+ LogEst rRun, /* Run-cost of the new entry */
107183
+ LogEst nOut /* Number of outputs for the new entry */
106724107184
){
106725107185
u16 i;
106726107186
WhereOrCost *p;
106727107187
for(i=pSet->n, p=pSet->a; i>0; i--, p++){
106728107188
if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107263,10 @@
106803107263
if( pWC->a!=pWC->aStatic ){
106804107264
sqlite3DbFree(db, pWC->a);
106805107265
}
106806107266
}
106807107267
106808
-/* Forward declaration */
106809
-static WhereCost whereCost(tRowcnt x);
106810
-
106811107268
/*
106812107269
** Add a single new WhereTerm entry to the WhereClause object pWC.
106813107270
** The new WhereTerm object is constructed from Expr p and with wtFlags.
106814107271
** The index in pWC->a[] of the new WhereTerm is returned on success.
106815107272
** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107305,11 @@
106848107305
}
106849107306
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
106850107307
}
106851107308
pTerm = &pWC->a[idx = pWC->nTerm++];
106852107309
if( p && ExprHasProperty(p, EP_Unlikely) ){
106853
- pTerm->truthProb = whereCost(p->iTable) - 99;
107310
+ pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
106854107311
}else{
106855107312
pTerm->truthProb = -1;
106856107313
}
106857107314
pTerm->pExpr = sqlite3ExprSkipCollate(p);
106858107315
pTerm->wtFlags = wtFlags;
@@ -108112,79 +108569,16 @@
108112108569
}
108113108570
108114108571
return 0;
108115108572
}
108116108573
108117
-/*
108118
-** Find (an approximate) sum of two WhereCosts. This computation is
108119
-** not a simple "+" operator because WhereCost is stored as a logarithmic
108120
-** value.
108121
-**
108122
-*/
108123
-static WhereCost whereCostAdd(WhereCost a, WhereCost b){
108124
- static const unsigned char x[] = {
108125
- 10, 10, /* 0,1 */
108126
- 9, 9, /* 2,3 */
108127
- 8, 8, /* 4,5 */
108128
- 7, 7, 7, /* 6,7,8 */
108129
- 6, 6, 6, /* 9,10,11 */
108130
- 5, 5, 5, /* 12-14 */
108131
- 4, 4, 4, 4, /* 15-18 */
108132
- 3, 3, 3, 3, 3, 3, /* 19-24 */
108133
- 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
108134
- };
108135
- if( a>=b ){
108136
- if( a>b+49 ) return a;
108137
- if( a>b+31 ) return a+1;
108138
- return a+x[a-b];
108139
- }else{
108140
- if( b>a+49 ) return b;
108141
- if( b>a+31 ) return b+1;
108142
- return b+x[b-a];
108143
- }
108144
-}
108145
-
108146
-/*
108147
-** Convert an integer into a WhereCost. In other words, compute a
108148
-** good approximatation for 10*log2(x).
108149
-*/
108150
-static WhereCost whereCost(tRowcnt x){
108151
- static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
108152
- WhereCost y = 40;
108153
- if( x<8 ){
108154
- if( x<2 ) return 0;
108155
- while( x<8 ){ y -= 10; x <<= 1; }
108156
- }else{
108157
- while( x>255 ){ y += 40; x >>= 4; }
108158
- while( x>15 ){ y += 10; x >>= 1; }
108159
- }
108160
- return a[x&7] + y - 10;
108161
-}
108162
-
108163
-#ifndef SQLITE_OMIT_VIRTUALTABLE
108164
-/*
108165
-** Convert a double (as received from xBestIndex of a virtual table)
108166
-** into a WhereCost. In other words, compute an approximation for
108167
-** 10*log2(x).
108168
-*/
108169
-static WhereCost whereCostFromDouble(double x){
108170
- u64 a;
108171
- WhereCost e;
108172
- assert( sizeof(x)==8 && sizeof(a)==8 );
108173
- if( x<=1 ) return 0;
108174
- if( x<=2000000000 ) return whereCost((tRowcnt)x);
108175
- memcpy(&a, &x, 8);
108176
- e = (a>>52) - 1022;
108177
- return e*10;
108178
-}
108179
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
108180108574
108181108575
/*
108182108576
** Estimate the logarithm of the input value to base 2.
108183108577
*/
108184
-static WhereCost estLog(WhereCost N){
108185
- WhereCost x = whereCost(N);
108578
+static LogEst estLog(LogEst N){
108579
+ LogEst x = sqlite3LogEst(N);
108186108580
return x>33 ? x - 33 : 0;
108187108581
}
108188108582
108189108583
/*
108190108584
** Two routines for printing the content of an sqlite3_index_info
@@ -108596,10 +108990,13 @@
108596108990
int iMin = 0; /* Smallest sample not yet tested */
108597108991
int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
108598108992
int iTest; /* Next sample to test */
108599108993
int res; /* Result of comparison operation */
108600108994
108995
+#ifndef SQLITE_DEBUG
108996
+ UNUSED_PARAMETER( pParse );
108997
+#endif
108601108998
assert( pRec!=0 || pParse->db->mallocFailed );
108602108999
if( pRec==0 ) return;
108603109000
iCol = pRec->nField - 1;
108604109001
assert( pIdx->nSample>0 );
108605109002
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
@@ -108693,11 +109090,11 @@
108693109090
**
108694109091
** ... FROM t1 WHERE a > ? AND a < ? ...
108695109092
**
108696109093
** then nEq is set to 0.
108697109094
**
108698
-** When this function is called, *pnOut is set to the whereCost() of the
109095
+** When this function is called, *pnOut is set to the sqlite3LogEst() of the
108699109096
** number of rows that the index scan is expected to visit without
108700109097
** considering the range constraints. If nEq is 0, this is the number of
108701109098
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
108702109099
** to account for the range contraints pLower and pUpper.
108703109100
**
@@ -108709,19 +109106,19 @@
108709109106
static int whereRangeScanEst(
108710109107
Parse *pParse, /* Parsing & code generating context */
108711109108
WhereLoopBuilder *pBuilder,
108712109109
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
108713109110
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
108714
- WhereCost *pnOut /* IN/OUT: Number of rows visited */
109111
+ WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
108715109112
){
108716109113
int rc = SQLITE_OK;
108717
- int nOut = (int)*pnOut;
108718
- WhereCost nNew;
109114
+ int nOut = pLoop->nOut;
109115
+ LogEst nNew;
108719109116
108720109117
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108721
- Index *p = pBuilder->pNew->u.btree.pIndex;
108722
- int nEq = pBuilder->pNew->u.btree.nEq;
109118
+ Index *p = pLoop->u.btree.pIndex;
109119
+ int nEq = pLoop->u.btree.nEq;
108723109120
108724109121
if( p->nSample>0
108725109122
&& nEq==pBuilder->nRecValid
108726109123
&& nEq<p->nSampleCol
108727109124
&& OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109195,18 @@
108798109195
}
108799109196
108800109197
pBuilder->pRec = pRec;
108801109198
if( rc==SQLITE_OK ){
108802109199
if( iUpper>iLower ){
108803
- nNew = whereCost(iUpper - iLower);
109200
+ nNew = sqlite3LogEst(iUpper - iLower);
108804109201
}else{
108805
- nNew = 10; assert( 10==whereCost(2) );
109202
+ nNew = 10; assert( 10==sqlite3LogEst(2) );
108806109203
}
108807109204
if( nNew<nOut ){
108808109205
nOut = nNew;
108809109206
}
108810
- *pnOut = (WhereCost)nOut;
109207
+ pLoop->nOut = (LogEst)nOut;
108811109208
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
108812109209
(u32)iLower, (u32)iUpper, nOut));
108813109210
return SQLITE_OK;
108814109211
}
108815109212
}
@@ -108820,20 +109217,20 @@
108820109217
assert( pLower || pUpper );
108821109218
/* TUNING: Each inequality constraint reduces the search space 4-fold.
108822109219
** A BETWEEN operator, therefore, reduces the search space 16-fold */
108823109220
nNew = nOut;
108824109221
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
108825
- nNew -= 20; assert( 20==whereCost(4) );
109222
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
108826109223
nOut--;
108827109224
}
108828109225
if( pUpper ){
108829
- nNew -= 20; assert( 20==whereCost(4) );
109226
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
108830109227
nOut--;
108831109228
}
108832109229
if( nNew<10 ) nNew = 10;
108833109230
if( nNew<nOut ) nOut = nNew;
108834
- *pnOut = (WhereCost)nOut;
109231
+ pLoop->nOut = (LogEst)nOut;
108835109232
return rc;
108836109233
}
108837109234
108838109235
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108839109236
/*
@@ -110441,11 +110838,11 @@
110441110838
**
110442110839
** In the current implementation, the first extra WHERE clause term reduces
110443110840
** the number of output rows by a factor of 10 and each additional term
110444110841
** reduces the number of output rows by sqrt(2).
110445110842
*/
110446
-static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){
110843
+static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
110447110844
WhereTerm *pTerm, *pX;
110448110845
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
110449110846
int i, j;
110450110847
110451110848
if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
@@ -110473,11 +110870,11 @@
110473110870
*/
110474110871
static int whereLoopAddBtreeIndex(
110475110872
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110476110873
struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110477110874
Index *pProbe, /* An index on pSrc */
110478
- WhereCost nInMul /* log(Number of iterations due to IN) */
110875
+ LogEst nInMul /* log(Number of iterations due to IN) */
110479110876
){
110480110877
WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110481110878
Parse *pParse = pWInfo->pParse; /* Parsing context */
110482110879
sqlite3 *db = pParse->db; /* Database connection malloc context */
110483110880
WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110883,15 @@
110486110883
WhereScan scan; /* Iterator for WHERE terms */
110487110884
Bitmask saved_prereq; /* Original value of pNew->prereq */
110488110885
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110489110886
int saved_nEq; /* Original value of pNew->u.btree.nEq */
110490110887
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110491
- WhereCost saved_nOut; /* Original value of pNew->nOut */
110888
+ LogEst saved_nOut; /* Original value of pNew->nOut */
110492110889
int iCol; /* Index of the column in the table */
110493110890
int rc = SQLITE_OK; /* Return code */
110494
- WhereCost nRowEst; /* Estimated index selectivity */
110495
- WhereCost rLogSize; /* Logarithm of table size */
110891
+ LogEst nRowEst; /* Estimated index selectivity */
110892
+ LogEst rLogSize; /* Logarithm of table size */
110496110893
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110497110894
110498110895
pNew = pBuilder->pNew;
110499110896
if( db->mallocFailed ) return SQLITE_NOMEM;
110500110897
@@ -110510,11 +110907,11 @@
110510110907
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110511110908
110512110909
assert( pNew->u.btree.nEq<=pProbe->nColumn );
110513110910
if( pNew->u.btree.nEq < pProbe->nColumn ){
110514110911
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110515
- nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110912
+ nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110516110913
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110517110914
}else{
110518110915
iCol = -1;
110519110916
nRowEst = 0;
110520110917
}
@@ -110524,11 +110921,11 @@
110524110921
saved_nLTerm = pNew->nLTerm;
110525110922
saved_wsFlags = pNew->wsFlags;
110526110923
saved_prereq = pNew->prereq;
110527110924
saved_nOut = pNew->nOut;
110528110925
pNew->rSetup = 0;
110529
- rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
110926
+ rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
110530110927
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110531110928
int nIn = 0;
110532110929
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110533110930
int nRecValid = pBuilder->nRecValid;
110534110931
#endif
@@ -110551,14 +110948,14 @@
110551110948
if( pTerm->eOperator & WO_IN ){
110552110949
Expr *pExpr = pTerm->pExpr;
110553110950
pNew->wsFlags |= WHERE_COLUMN_IN;
110554110951
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110555110952
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110556
- nIn = 46; assert( 46==whereCost(25) );
110953
+ nIn = 46; assert( 46==sqlite3LogEst(25) );
110557110954
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110558110955
/* "x IN (value, value, ...)" */
110559
- nIn = whereCost(pExpr->x.pList->nExpr);
110956
+ nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
110560110957
}
110561110958
pNew->rRun += nIn;
110562110959
pNew->u.btree.nEq++;
110563110960
pNew->nOut = nRowEst + nInMul + nIn;
110564110961
}else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110973,11 @@
110576110973
pNew->nOut = nRowEst + nInMul;
110577110974
}else if( pTerm->eOperator & (WO_ISNULL) ){
110578110975
pNew->wsFlags |= WHERE_COLUMN_NULL;
110579110976
pNew->u.btree.nEq++;
110580110977
/* TUNING: IS NULL selects 2 rows */
110581
- nIn = 10; assert( 10==whereCost(2) );
110978
+ nIn = 10; assert( 10==sqlite3LogEst(2) );
110582110979
pNew->nOut = nRowEst + nInMul + nIn;
110583110980
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110584110981
testcase( pTerm->eOperator & WO_GT );
110585110982
testcase( pTerm->eOperator & WO_GE );
110586110983
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110993,11 @@
110596110993
pNew->aLTerm[pNew->nLTerm-2] : 0;
110597110994
}
110598110995
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110599110996
/* Adjust nOut and rRun for STAT3 range values */
110600110997
assert( pNew->nOut==saved_nOut );
110601
- whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
110998
+ whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
110602110999
}
110603111000
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110604111001
if( nInMul==0
110605111002
&& pProbe->nSample
110606111003
&& pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,23 +111013,23 @@
110616111013
&& !ExprHasProperty(pExpr, EP_xIsSelect) ){
110617111014
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
110618111015
}
110619111016
assert( nOut==0 || rc==SQLITE_OK );
110620111017
if( nOut ){
110621
- nOut = whereCost(nOut);
110622
- pNew->nOut = MIN(nOut, saved_nOut);
111018
+ pNew->nOut = sqlite3LogEst(nOut);
111019
+ if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
110623111020
}
110624111021
}
110625111022
#endif
110626111023
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
110627111024
/* Each row involves a step of the index, then a binary search of
110628111025
** the main table */
110629
- pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
111026
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
110630111027
}
110631111028
/* Step cost for each output row */
110632
- pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
110633
- whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
111029
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
111030
+ whereLoopOutputAdjust(pBuilder->pWC, pNew);
110634111031
rc = whereLoopInsert(pBuilder, pNew);
110635111032
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
110636111033
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
110637111034
){
110638111035
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
@@ -110727,18 +111124,20 @@
110727111124
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
110728111125
WhereLoop *pNew; /* Template WhereLoop object */
110729111126
int rc = SQLITE_OK; /* Return code */
110730111127
int iSortIdx = 1; /* Index number */
110731111128
int b; /* A boolean value */
110732
- WhereCost rSize; /* number of rows in the table */
110733
- WhereCost rLogSize; /* Logarithm of the number of rows in the table */
111129
+ LogEst rSize; /* number of rows in the table */
111130
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
110734111131
WhereClause *pWC; /* The parsed WHERE clause */
111132
+ Table *pTab; /* Table being queried */
110735111133
110736111134
pNew = pBuilder->pNew;
110737111135
pWInfo = pBuilder->pWInfo;
110738111136
pTabList = pWInfo->pTabList;
110739111137
pSrc = pTabList->a + pNew->iTab;
111138
+ pTab = pSrc->pTab;
110740111139
pWC = pBuilder->pWC;
110741111140
assert( !IsVirtual(pSrc->pTab) );
110742111141
110743111142
if( pSrc->pIndex ){
110744111143
/* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111151,22 @@
110752111151
memset(&sPk, 0, sizeof(Index));
110753111152
sPk.nColumn = 1;
110754111153
sPk.aiColumn = &aiColumnPk;
110755111154
sPk.aiRowEst = aiRowEstPk;
110756111155
sPk.onError = OE_Replace;
110757
- sPk.pTable = pSrc->pTab;
110758
- aiRowEstPk[0] = pSrc->pTab->nRowEst;
111156
+ sPk.pTable = pTab;
111157
+ aiRowEstPk[0] = pTab->nRowEst;
110759111158
aiRowEstPk[1] = 1;
110760111159
pFirst = pSrc->pTab->pIndex;
110761111160
if( pSrc->notIndexed==0 ){
110762111161
/* The real indices of the table are only considered if the
110763111162
** NOT INDEXED qualifier is omitted from the FROM clause */
110764111163
sPk.pNext = pFirst;
110765111164
}
110766111165
pProbe = &sPk;
110767111166
}
110768
- rSize = whereCost(pSrc->pTab->nRowEst);
111167
+ rSize = sqlite3LogEst(pTab->nRowEst);
110769111168
rLogSize = estLog(rSize);
110770111169
110771111170
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
110772111171
/* Automatic indexes */
110773111172
if( !pBuilder->pOrSet
@@ -110788,17 +111187,17 @@
110788111187
pNew->nLTerm = 1;
110789111188
pNew->aLTerm[0] = pTerm;
110790111189
/* TUNING: One-time cost for computing the automatic index is
110791111190
** approximately 7*N*log2(N) where N is the number of rows in
110792111191
** the table being indexed. */
110793
- pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
111192
+ pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
110794111193
/* TUNING: Each index lookup yields 20 rows in the table. This
110795111194
** is more than the usual guess of 10 rows, since we have no way
110796111195
** of knowning how selective the index will ultimately be. It would
110797111196
** not be unreasonable to make this value much larger. */
110798
- pNew->nOut = 43; assert( 43==whereCost(20) );
110799
- pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
111197
+ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
111198
+ pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
110800111199
pNew->wsFlags = WHERE_AUTO_INDEX;
110801111200
pNew->prereq = mExtra | pTerm->prereqRight;
110802111201
rc = whereLoopInsert(pBuilder, pNew);
110803111202
}
110804111203
}
@@ -110828,15 +111227,13 @@
110828111227
110829111228
/* Full table scan */
110830111229
pNew->iSortIdx = b ? iSortIdx : 0;
110831111230
/* TUNING: Cost of full table scan is 3*(N + log2(N)).
110832111231
** + The extra 3 factor is to encourage the use of indexed lookups
110833
- ** over full scans. A smaller constant 2 is used for covering
110834
- ** index scans so that a covering index scan will be favored over
110835
- ** a table scan. */
110836
- pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
110837
- whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
111232
+ ** over full scans. FIXME */
111233
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
111234
+ whereLoopOutputAdjust(pWC, pNew);
110838111235
rc = whereLoopInsert(pBuilder, pNew);
110839111236
pNew->nOut = rSize;
110840111237
if( rc ) break;
110841111238
}else{
110842111239
Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
@@ -110844,33 +111241,32 @@
110844111241
110845111242
/* Full scan via index */
110846111243
if( b
110847111244
|| ( m==0
110848111245
&& pProbe->bUnordered==0
111246
+ && pProbe->szIdxRow<pTab->szTabRow
110849111247
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
110850111248
&& sqlite3GlobalConfig.bUseCis
110851111249
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
110852111250
)
110853111251
){
110854111252
pNew->iSortIdx = b ? iSortIdx : 0;
110855111253
if( m==0 ){
110856
- /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
110857
- ** + The extra 2 factor is to encourage the use of indexed lookups
110858
- ** over index scans. A table scan uses a factor of 3 so that
110859
- ** index scans are favored over table scans.
110860
- ** + If this covering index might also help satisfy the ORDER BY
110861
- ** clause, then the cost is fudged down slightly so that this
110862
- ** index is favored above other indices that have no hope of
110863
- ** helping with the ORDER BY. */
110864
- pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
111254
+ /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
111255
+ ** + The extra factor K of between 1.1 and 3.0 that depends
111256
+ ** on the relative sizes of the table and the index. K
111257
+ ** is smaller for smaller indices, thus favoring them.
111258
+ */
111259
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
111260
+ (15*pProbe->szIdxRow)/pTab->szTabRow;
110865111261
}else{
110866111262
assert( b!=0 );
110867111263
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
110868111264
** which we will simplify to just N*log2(N) */
110869111265
pNew->rRun = rSize + rLogSize;
110870111266
}
110871
- whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
111267
+ whereLoopOutputAdjust(pWC, pNew);
110872111268
rc = whereLoopInsert(pBuilder, pNew);
110873111269
pNew->nOut = rSize;
110874111270
if( rc ) break;
110875111271
}
110876111272
}
@@ -111037,13 +111433,13 @@
111037111433
pIdxInfo->needToFreeIdxStr = 0;
111038111434
pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111039111435
pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111040111436
&& pIdxInfo->orderByConsumed);
111041111437
pNew->rSetup = 0;
111042
- pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
111438
+ pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
111043111439
/* TUNING: Every virtual table query returns 25 rows */
111044
- pNew->nOut = 46; assert( 46==whereCost(25) );
111440
+ pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
111045111441
whereLoopInsert(pBuilder, pNew);
111046111442
if( pNew->u.vtab.needFree ){
111047111443
sqlite3_free(pNew->u.vtab.idxStr);
111048111444
pNew->u.vtab.needFree = 0;
111049111445
}
@@ -111076,10 +111472,12 @@
111076111472
pWC = pBuilder->pWC;
111077111473
if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111078111474
pWCEnd = pWC->a + pWC->nTerm;
111079111475
pNew = pBuilder->pNew;
111080111476
memset(&sSum, 0, sizeof(sSum));
111477
+ pItem = pWInfo->pTabList->a + pNew->iTab;
111478
+ iCur = pItem->iCursor;
111081111479
111082111480
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111083111481
if( (pTerm->eOperator & WO_OR)!=0
111084111482
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111085111483
){
@@ -111087,12 +111485,10 @@
111087111485
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111088111486
WhereTerm *pOrTerm;
111089111487
int once = 1;
111090111488
int i, j;
111091111489
111092
- pItem = pWInfo->pTabList->a + pNew->iTab;
111093
- iCur = pItem->iCursor;
111094111490
sSubBuild = *pBuilder;
111095111491
sSubBuild.pOrderBy = 0;
111096111492
sSubBuild.pOrSet = &sCur;
111097111493
111098111494
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111525,12 @@
111129111525
whereOrMove(&sPrev, &sSum);
111130111526
sSum.n = 0;
111131111527
for(i=0; i<sPrev.n; i++){
111132111528
for(j=0; j<sCur.n; j++){
111133111529
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111134
- whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111135
- whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111530
+ sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111531
+ sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111136111532
}
111137111533
}
111138111534
}
111139111535
}
111140111536
pNew->nLTerm = 1;
@@ -111468,23 +111864,23 @@
111468111864
** costs if nRowEst==0.
111469111865
**
111470111866
** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111471111867
** error occurs.
111472111868
*/
111473
-static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
111869
+static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
111474111870
int mxChoice; /* Maximum number of simultaneous paths tracked */
111475111871
int nLoop; /* Number of terms in the join */
111476111872
Parse *pParse; /* Parsing context */
111477111873
sqlite3 *db; /* The database connection */
111478111874
int iLoop; /* Loop counter over the terms of the join */
111479111875
int ii, jj; /* Loop counters */
111480111876
int mxI = 0; /* Index of next entry to replace */
111481
- WhereCost rCost; /* Cost of a path */
111482
- WhereCost nOut; /* Number of outputs */
111483
- WhereCost mxCost = 0; /* Maximum cost of a set of paths */
111484
- WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
111485
- WhereCost rSortCost; /* Cost to do a sort */
111877
+ LogEst rCost; /* Cost of a path */
111878
+ LogEst nOut; /* Number of outputs */
111879
+ LogEst mxCost = 0; /* Maximum cost of a set of paths */
111880
+ LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
111881
+ LogEst rSortCost; /* Cost to do a sort */
111486111882
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111487111883
WherePath *aFrom; /* All nFrom paths at the previous level */
111488111884
WherePath *aTo; /* The nTo best paths at the current level */
111489111885
WherePath *pFrom; /* An element of aFrom[] that we are working on */
111490111886
WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111913,23 @@
111517111913
/* Seed the search with a single WherePath containing zero WhereLoops.
111518111914
**
111519111915
** TUNING: Do not let the number of iterations go above 25. If the cost
111520111916
** of computing an automatic index is not paid back within the first 25
111521111917
** rows, then do not use the automatic index. */
111522
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
111918
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
111523111919
nFrom = 1;
111524111920
111525111921
/* Precompute the cost of sorting the final result set, if the caller
111526111922
** to sqlite3WhereBegin() was concerned about sorting */
111527111923
rSortCost = 0;
111528111924
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111529111925
aFrom[0].isOrderedValid = 1;
111530111926
}else{
111531
- /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
111532
- ** number of output rows. */
111927
+ /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
111928
+ ** number of output rows. The 48 is the expected size of a row to sort.
111929
+ ** FIXME: compute a better estimate of the 48 multiplier based on the
111930
+ ** result set expressions. */
111533111931
rSortCost = nRowEst + estLog(nRowEst);
111534111932
WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111535111933
}
111536111934
111537111935
/* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111945,12 @@
111547111945
u8 isOrdered = pFrom->isOrdered;
111548111946
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111549111947
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111550111948
/* At this point, pWLoop is a candidate to be the next loop.
111551111949
** Compute its cost */
111552
- rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111553
- rCost = whereCostAdd(rCost, pFrom->rCost);
111950
+ rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111951
+ rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
111554111952
nOut = pFrom->nRow + pWLoop->nOut;
111555111953
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111556111954
if( !isOrderedValid ){
111557111955
switch( wherePathSatisfiesOrderBy(pWInfo,
111558111956
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111960,11 @@
111562111960
isOrderedValid = 1;
111563111961
break;
111564111962
case 0: /* No. pFrom+pWLoop will require a separate sort */
111565111963
isOrdered = 0;
111566111964
isOrderedValid = 1;
111567
- rCost = whereCostAdd(rCost, rSortCost);
111965
+ rCost = sqlite3LogEstAdd(rCost, rSortCost);
111568111966
break;
111569111967
default: /* Cannot tell yet. Try again on the next iteration */
111570111968
break;
111571111969
}
111572111970
}else{
@@ -111769,11 +112167,11 @@
111769112167
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
111770112168
pLoop->aLTerm[0] = pTerm;
111771112169
pLoop->nLTerm = 1;
111772112170
pLoop->u.btree.nEq = 1;
111773112171
/* TUNING: Cost of a rowid lookup is 10 */
111774
- pLoop->rRun = 33; /* 33==whereCost(10) */
112172
+ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
111775112173
}else{
111776112174
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111777112175
assert( pLoop->aLTermSpace==pLoop->aLTerm );
111778112176
assert( ArraySize(pLoop->aLTermSpace)==4 );
111779112177
if( pIdx->onError==OE_None
@@ -111792,16 +112190,16 @@
111792112190
}
111793112191
pLoop->nLTerm = j;
111794112192
pLoop->u.btree.nEq = j;
111795112193
pLoop->u.btree.pIndex = pIdx;
111796112194
/* TUNING: Cost of a unique index lookup is 15 */
111797
- pLoop->rRun = 39; /* 39==whereCost(15) */
112195
+ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
111798112196
break;
111799112197
}
111800112198
}
111801112199
if( pLoop->wsFlags ){
111802
- pLoop->nOut = (WhereCost)1;
112200
+ pLoop->nOut = (LogEst)1;
111803112201
pWInfo->a[0].pWLoop = pLoop;
111804112202
pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
111805112203
pWInfo->a[0].iTabCur = iCur;
111806112204
pWInfo->nRowOut = 1;
111807112205
if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112563,11 @@
112165112563
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112166112564
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112167112565
112168112566
/* If the caller is an UPDATE or DELETE statement that is requesting
112169112567
** to use a one-pass algorithm, determine if this is appropriate.
112170
- ** The one-pass algorithm only works if the WHERE clause constraints
112568
+ ** The one-pass algorithm only works if the WHERE clause constrains
112171112569
** the statement to update a single row.
112172112570
*/
112173112571
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112174112572
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112175112573
&& (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121981,16 @@
121583121981
** verifying the operation of the SQLite core.
121584121982
*/
121585121983
int inTransaction; /* True after xBegin but before xCommit/xRollback */
121586121984
int mxSavepoint; /* Largest valid xSavepoint integer */
121587121985
#endif
121986
+
121987
+#ifdef SQLITE_TEST
121988
+ /* True to disable the incremental doclist optimization. This is controled
121989
+ ** by special insert command 'test-no-incr-doclist'. */
121990
+ int bNoIncrDoclist;
121991
+#endif
121588121992
};
121589121993
121590121994
/*
121591121995
** When the core wants to read from the virtual table, it creates a
121592121996
** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +122012,12 @@
121608122012
int nDoclist; /* Size of buffer at aDoclist */
121609122013
u8 bDesc; /* True to sort in descending order */
121610122014
int eEvalmode; /* An FTS3_EVAL_XX constant */
121611122015
int nRowAvg; /* Average size of database rows, in pages */
121612122016
sqlite3_int64 nDoc; /* Documents in table */
121613
-
122017
+ i64 iMinDocid; /* Minimum docid to return */
122018
+ i64 iMaxDocid; /* Maximum docid to return */
121614122019
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
121615122020
u32 *aMatchinfo; /* Information about most recent match */
121616122021
int nMatchinfo; /* Number of elements in aMatchinfo[] */
121617122022
char *zMatchinfo; /* Matchinfo specification */
121618122023
};
@@ -121638,10 +122043,19 @@
121638122043
*/
121639122044
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
121640122045
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
121641122046
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
121642122047
122048
+/*
122049
+** The lower 16-bits of the sqlite3_index_info.idxNum value set by
122050
+** the xBestIndex() method contains the Fts3Cursor.eSearch value described
122051
+** above. The upper 16-bits contain a combination of the following
122052
+** bits, used to describe extra constraints on full-text searches.
122053
+*/
122054
+#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
122055
+#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
122056
+#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
121643122057
121644122058
struct Fts3Doclist {
121645122059
char *aAll; /* Array containing doclist (or NULL) */
121646122060
int nAll; /* Size of a[] in bytes */
121647122061
char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123472,31 @@
123058123472
*/
123059123473
static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123060123474
Fts3Table *p = (Fts3Table *)pVTab;
123061123475
int i; /* Iterator variable */
123062123476
int iCons = -1; /* Index of constraint to use */
123477
+
123063123478
int iLangidCons = -1; /* Index of langid=x constraint, if present */
123479
+ int iDocidGe = -1; /* Index of docid>=x constraint, if present */
123480
+ int iDocidLe = -1; /* Index of docid<=x constraint, if present */
123481
+ int iIdx;
123064123482
123065123483
/* By default use a full table scan. This is an expensive option,
123066123484
** so search through the constraints to see if a more efficient
123067123485
** strategy is possible.
123068123486
*/
123069123487
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123070123488
pInfo->estimatedCost = 5000000;
123071123489
for(i=0; i<pInfo->nConstraint; i++){
123490
+ int bDocid; /* True if this constraint is on docid */
123072123491
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123073123492
if( pCons->usable==0 ) continue;
123493
+
123494
+ bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
123074123495
123075123496
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123076
- if( iCons<0
123077
- && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123078
- && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
123079
- ){
123497
+ if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
123080123498
pInfo->idxNum = FTS3_DOCID_SEARCH;
123081123499
pInfo->estimatedCost = 1.0;
123082123500
iCons = i;
123083123501
}
123084123502
@@ -123103,18 +123521,42 @@
123103123521
if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123104123522
&& pCons->iColumn==p->nColumn + 2
123105123523
){
123106123524
iLangidCons = i;
123107123525
}
123526
+
123527
+ if( bDocid ){
123528
+ switch( pCons->op ){
123529
+ case SQLITE_INDEX_CONSTRAINT_GE:
123530
+ case SQLITE_INDEX_CONSTRAINT_GT:
123531
+ iDocidGe = i;
123532
+ break;
123533
+
123534
+ case SQLITE_INDEX_CONSTRAINT_LE:
123535
+ case SQLITE_INDEX_CONSTRAINT_LT:
123536
+ iDocidLe = i;
123537
+ break;
123538
+ }
123539
+ }
123108123540
}
123109123541
123542
+ iIdx = 1;
123110123543
if( iCons>=0 ){
123111
- pInfo->aConstraintUsage[iCons].argvIndex = 1;
123544
+ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
123112123545
pInfo->aConstraintUsage[iCons].omit = 1;
123113123546
}
123114123547
if( iLangidCons>=0 ){
123115
- pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
123548
+ pInfo->idxNum |= FTS3_HAVE_LANGID;
123549
+ pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
123550
+ }
123551
+ if( iDocidGe>=0 ){
123552
+ pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
123553
+ pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
123554
+ }
123555
+ if( iDocidLe>=0 ){
123556
+ pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
123557
+ pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
123116123558
}
123117123559
123118123560
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123119123561
** docid) order. Both ascending and descending are possible.
123120123562
*/
@@ -124556,10 +124998,37 @@
124556124998
rc = fts3EvalNext((Fts3Cursor *)pCursor);
124557124999
}
124558125000
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
124559125001
return rc;
124560125002
}
125003
+
125004
+/*
125005
+** The following are copied from sqliteInt.h.
125006
+**
125007
+** Constants for the largest and smallest possible 64-bit signed integers.
125008
+** These macros are designed to work correctly on both 32-bit and 64-bit
125009
+** compilers.
125010
+*/
125011
+#ifndef SQLITE_AMALGAMATION
125012
+# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
125013
+# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
125014
+#endif
125015
+
125016
+/*
125017
+** If the numeric type of argument pVal is "integer", then return it
125018
+** converted to a 64-bit signed integer. Otherwise, return a copy of
125019
+** the second parameter, iDefault.
125020
+*/
125021
+static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
125022
+ if( pVal ){
125023
+ int eType = sqlite3_value_numeric_type(pVal);
125024
+ if( eType==SQLITE_INTEGER ){
125025
+ return sqlite3_value_int64(pVal);
125026
+ }
125027
+ }
125028
+ return iDefault;
125029
+}
124561125030
124562125031
/*
124563125032
** This is the xFilter interface for the virtual table. See
124564125033
** the virtual table xFilter method documentation for additional
124565125034
** information.
@@ -124582,44 +125051,62 @@
124582125051
int nVal, /* Number of elements in apVal */
124583125052
sqlite3_value **apVal /* Arguments for the indexing scheme */
124584125053
){
124585125054
int rc;
124586125055
char *zSql; /* SQL statement used to access %_content */
125056
+ int eSearch;
124587125057
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
124588125058
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
125059
+
125060
+ sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
125061
+ sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
125062
+ sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
125063
+ sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
125064
+ int iIdx;
124589125065
124590125066
UNUSED_PARAMETER(idxStr);
124591125067
UNUSED_PARAMETER(nVal);
124592125068
124593
- assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124594
- assert( nVal==0 || nVal==1 || nVal==2 );
124595
- assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
125069
+ eSearch = (idxNum & 0x0000FFFF);
125070
+ assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124596125071
assert( p->pSegments==0 );
125072
+
125073
+ /* Collect arguments into local variables */
125074
+ iIdx = 0;
125075
+ if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
125076
+ if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
125077
+ if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
125078
+ if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
125079
+ assert( iIdx==nVal );
124597125080
124598125081
/* In case the cursor has been used before, clear it now. */
124599125082
sqlite3_finalize(pCsr->pStmt);
124600125083
sqlite3_free(pCsr->aDoclist);
124601125084
sqlite3Fts3ExprFree(pCsr->pExpr);
124602125085
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
124603125086
125087
+ /* Set the lower and upper bounds on docids to return */
125088
+ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
125089
+ pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
125090
+
124604125091
if( idxStr ){
124605125092
pCsr->bDesc = (idxStr[0]=='D');
124606125093
}else{
124607125094
pCsr->bDesc = p->bDescIdx;
124608125095
}
124609
- pCsr->eSearch = (i16)idxNum;
125096
+ pCsr->eSearch = (i16)eSearch;
124610125097
124611
- if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
124612
- int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
124613
- const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
125098
+ if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
125099
+ int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
125100
+ const char *zQuery = (const char *)sqlite3_value_text(pCons);
124614125101
124615
- if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
125102
+ if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
124616125103
return SQLITE_NOMEM;
124617125104
}
124618125105
124619125106
pCsr->iLangid = 0;
124620
- if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
125107
+ if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
124621125108
124622125109
assert( p->base.zErrMsg==0 );
124623125110
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
124624125111
p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
124625125112
&p->base.zErrMsg
@@ -124638,11 +125125,11 @@
124638125125
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
124639125126
** statement loops through all rows of the %_content table. For a
124640125127
** full-text query or docid lookup, the statement retrieves a single
124641125128
** row by docid.
124642125129
*/
124643
- if( idxNum==FTS3_FULLSCAN_SEARCH ){
125130
+ if( eSearch==FTS3_FULLSCAN_SEARCH ){
124644125131
zSql = sqlite3_mprintf(
124645125132
"SELECT %s ORDER BY rowid %s",
124646125133
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
124647125134
);
124648125135
if( zSql ){
@@ -124649,14 +125136,14 @@
124649125136
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
124650125137
sqlite3_free(zSql);
124651125138
}else{
124652125139
rc = SQLITE_NOMEM;
124653125140
}
124654
- }else if( idxNum==FTS3_DOCID_SEARCH ){
125141
+ }else if( eSearch==FTS3_DOCID_SEARCH ){
124655125142
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
124656125143
if( rc==SQLITE_OK ){
124657
- rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
125144
+ rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
124658125145
}
124659125146
}
124660125147
if( rc!=SQLITE_OK ) return rc;
124661125148
124662125149
return fts3NextMethod(pCursor);
@@ -125543,10 +126030,16 @@
125543126030
}
125544126031
125545126032
return SQLITE_OK;
125546126033
}
125547126034
126035
+/*
126036
+** Maximum number of tokens a phrase may have to be considered for the
126037
+** incremental doclists strategy.
126038
+*/
126039
+#define MAX_INCR_PHRASE_TOKENS 4
126040
+
125548126041
/*
125549126042
** This function is called for each Fts3Phrase in a full-text query
125550126043
** expression to initialize the mechanism for returning rows. Once this
125551126044
** function has been called successfully on an Fts3Phrase, it may be
125552126045
** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +126049,47 @@
125556126049
** memory within this call.
125557126050
**
125558126051
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
125559126052
*/
125560126053
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
125561
- int rc; /* Error code */
125562
- Fts3PhraseToken *pFirst = &p->aToken[0];
125563126054
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125564
-
125565
- if( pCsr->bDesc==pTab->bDescIdx
125566
- && bOptOk==1
125567
- && p->nToken==1
125568
- && pFirst->pSegcsr
125569
- && pFirst->pSegcsr->bLookup
125570
- && pFirst->bFirst==0
125571
- ){
126055
+ int rc = SQLITE_OK; /* Error code */
126056
+ int i;
126057
+
126058
+ /* Determine if doclists may be loaded from disk incrementally. This is
126059
+ ** possible if the bOptOk argument is true, the FTS doclists will be
126060
+ ** scanned in forward order, and the phrase consists of
126061
+ ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
126062
+ ** tokens or prefix tokens that cannot use a prefix-index. */
126063
+ int bHaveIncr = 0;
126064
+ int bIncrOk = (bOptOk
126065
+ && pCsr->bDesc==pTab->bDescIdx
126066
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
126067
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
126068
+#ifdef SQLITE_TEST
126069
+ && pTab->bNoIncrDoclist==0
126070
+#endif
126071
+ );
126072
+ for(i=0; bIncrOk==1 && i<p->nToken; i++){
126073
+ Fts3PhraseToken *pToken = &p->aToken[i];
126074
+ if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
126075
+ bIncrOk = 0;
126076
+ }
126077
+ if( pToken->pSegcsr ) bHaveIncr = 1;
126078
+ }
126079
+
126080
+ if( bIncrOk && bHaveIncr ){
125572126081
/* Use the incremental approach. */
125573126082
int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
125574
- rc = sqlite3Fts3MsrIncrStart(
125575
- pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
126083
+ for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126084
+ Fts3PhraseToken *pToken = &p->aToken[i];
126085
+ Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
126086
+ if( pSegcsr ){
126087
+ rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
126088
+ }
126089
+ }
125576126090
p->bIncr = 1;
125577
-
125578126091
}else{
125579126092
/* Load the full doclist for the phrase into memory. */
125580126093
rc = fts3EvalPhraseLoad(pCsr, p);
125581126094
p->bIncr = 0;
125582126095
}
@@ -125680,10 +126193,220 @@
125680126193
}
125681126194
}
125682126195
125683126196
*ppIter = p;
125684126197
}
126198
+
126199
+/*
126200
+** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
126201
+** to true if EOF is reached.
126202
+*/
126203
+static void fts3EvalDlPhraseNext(
126204
+ Fts3Table *pTab,
126205
+ Fts3Doclist *pDL,
126206
+ u8 *pbEof
126207
+){
126208
+ char *pIter; /* Used to iterate through aAll */
126209
+ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
126210
+
126211
+ if( pDL->pNextDocid ){
126212
+ pIter = pDL->pNextDocid;
126213
+ }else{
126214
+ pIter = pDL->aAll;
126215
+ }
126216
+
126217
+ if( pIter>=pEnd ){
126218
+ /* We have already reached the end of this doclist. EOF. */
126219
+ *pbEof = 1;
126220
+ }else{
126221
+ sqlite3_int64 iDelta;
126222
+ pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
126223
+ if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
126224
+ pDL->iDocid += iDelta;
126225
+ }else{
126226
+ pDL->iDocid -= iDelta;
126227
+ }
126228
+ pDL->pList = pIter;
126229
+ fts3PoslistCopy(0, &pIter);
126230
+ pDL->nList = (int)(pIter - pDL->pList);
126231
+
126232
+ /* pIter now points just past the 0x00 that terminates the position-
126233
+ ** list for document pDL->iDocid. However, if this position-list was
126234
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
126235
+ ** point to the start of the next docid value. The following line deals
126236
+ ** with this case by advancing pIter past the zero-padding added by
126237
+ ** fts3EvalNearTrim(). */
126238
+ while( pIter<pEnd && *pIter==0 ) pIter++;
126239
+
126240
+ pDL->pNextDocid = pIter;
126241
+ assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
126242
+ *pbEof = 0;
126243
+ }
126244
+}
126245
+
126246
+/*
126247
+** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
126248
+*/
126249
+typedef struct TokenDoclist TokenDoclist;
126250
+struct TokenDoclist {
126251
+ int bIgnore;
126252
+ sqlite3_int64 iDocid;
126253
+ char *pList;
126254
+ int nList;
126255
+};
126256
+
126257
+/*
126258
+** Token pToken is an incrementally loaded token that is part of a
126259
+** multi-token phrase. Advance it to the next matching document in the
126260
+** database and populate output variable *p with the details of the new
126261
+** entry. Or, if the iterator has reached EOF, set *pbEof to true.
126262
+**
126263
+** If an error occurs, return an SQLite error code. Otherwise, return
126264
+** SQLITE_OK.
126265
+*/
126266
+static int incrPhraseTokenNext(
126267
+ Fts3Table *pTab, /* Virtual table handle */
126268
+ Fts3Phrase *pPhrase, /* Phrase to advance token of */
126269
+ int iToken, /* Specific token to advance */
126270
+ TokenDoclist *p, /* OUT: Docid and doclist for new entry */
126271
+ u8 *pbEof /* OUT: True if iterator is at EOF */
126272
+){
126273
+ int rc = SQLITE_OK;
126274
+
126275
+ if( pPhrase->iDoclistToken==iToken ){
126276
+ assert( p->bIgnore==0 );
126277
+ assert( pPhrase->aToken[iToken].pSegcsr==0 );
126278
+ fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
126279
+ p->pList = pPhrase->doclist.pList;
126280
+ p->nList = pPhrase->doclist.nList;
126281
+ p->iDocid = pPhrase->doclist.iDocid;
126282
+ }else{
126283
+ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
126284
+ assert( pToken->pDeferred==0 );
126285
+ assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
126286
+ if( pToken->pSegcsr ){
126287
+ assert( p->bIgnore==0 );
126288
+ rc = sqlite3Fts3MsrIncrNext(
126289
+ pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
126290
+ );
126291
+ if( p->pList==0 ) *pbEof = 1;
126292
+ }else{
126293
+ p->bIgnore = 1;
126294
+ }
126295
+ }
126296
+
126297
+ return rc;
126298
+}
126299
+
126300
+
126301
+/*
126302
+** The phrase iterator passed as the second argument:
126303
+**
126304
+** * features at least one token that uses an incremental doclist, and
126305
+**
126306
+** * does not contain any deferred tokens.
126307
+**
126308
+** Advance it to the next matching documnent in the database and populate
126309
+** the Fts3Doclist.pList and nList fields.
126310
+**
126311
+** If there is no "next" entry and no error occurs, then *pbEof is set to
126312
+** 1 before returning. Otherwise, if no error occurs and the iterator is
126313
+** successfully advanced, *pbEof is set to 0.
126314
+**
126315
+** If an error occurs, return an SQLite error code. Otherwise, return
126316
+** SQLITE_OK.
126317
+*/
126318
+static int fts3EvalIncrPhraseNext(
126319
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
126320
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
126321
+ u8 *pbEof /* OUT: Set to 1 if EOF */
126322
+){
126323
+ int rc = SQLITE_OK;
126324
+ Fts3Doclist *pDL = &p->doclist;
126325
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126326
+ u8 bEof = 0;
126327
+
126328
+ /* This is only called if it is guaranteed that the phrase has at least
126329
+ ** one incremental token. In which case the bIncr flag is set. */
126330
+ assert( p->bIncr==1 );
126331
+
126332
+ if( p->nToken==1 && p->bIncr ){
126333
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
126334
+ &pDL->iDocid, &pDL->pList, &pDL->nList
126335
+ );
126336
+ if( pDL->pList==0 ) bEof = 1;
126337
+ }else{
126338
+ int bDescDoclist = pCsr->bDesc;
126339
+ struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
126340
+
126341
+ memset(a, 0, sizeof(a));
126342
+ assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
126343
+ assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
126344
+
126345
+ while( bEof==0 ){
126346
+ int bMaxSet = 0;
126347
+ sqlite3_int64 iMax = 0; /* Largest docid for all iterators */
126348
+ int i; /* Used to iterate through tokens */
126349
+
126350
+ /* Advance the iterator for each token in the phrase once. */
126351
+ for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
126352
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126353
+ if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
126354
+ iMax = a[i].iDocid;
126355
+ bMaxSet = 1;
126356
+ }
126357
+ }
126358
+ assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
126359
+ assert( rc!=SQLITE_OK || bMaxSet );
126360
+
126361
+ /* Keep advancing iterators until they all point to the same document */
126362
+ for(i=0; i<p->nToken; i++){
126363
+ while( rc==SQLITE_OK && bEof==0
126364
+ && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
126365
+ ){
126366
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126367
+ if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
126368
+ iMax = a[i].iDocid;
126369
+ i = 0;
126370
+ }
126371
+ }
126372
+ }
126373
+
126374
+ /* Check if the current entries really are a phrase match */
126375
+ if( bEof==0 ){
126376
+ int nList = 0;
126377
+ int nByte = a[p->nToken-1].nList;
126378
+ char *aDoclist = sqlite3_malloc(nByte+1);
126379
+ if( !aDoclist ) return SQLITE_NOMEM;
126380
+ memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
126381
+
126382
+ for(i=0; i<(p->nToken-1); i++){
126383
+ if( a[i].bIgnore==0 ){
126384
+ char *pL = a[i].pList;
126385
+ char *pR = aDoclist;
126386
+ char *pOut = aDoclist;
126387
+ int nDist = p->nToken-1-i;
126388
+ int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
126389
+ if( res==0 ) break;
126390
+ nList = (int)(pOut - aDoclist);
126391
+ }
126392
+ }
126393
+ if( i==(p->nToken-1) ){
126394
+ pDL->iDocid = iMax;
126395
+ pDL->pList = aDoclist;
126396
+ pDL->nList = nList;
126397
+ pDL->bFreeList = 1;
126398
+ break;
126399
+ }
126400
+ sqlite3_free(aDoclist);
126401
+ }
126402
+ }
126403
+ }
126404
+
126405
+ *pbEof = bEof;
126406
+ return rc;
126407
+}
125685126408
125686126409
/*
125687126410
** Attempt to move the phrase iterator to point to the next matching docid.
125688126411
** If an error occurs, return an SQLite error code. Otherwise, return
125689126412
** SQLITE_OK.
@@ -125700,59 +126423,18 @@
125700126423
int rc = SQLITE_OK;
125701126424
Fts3Doclist *pDL = &p->doclist;
125702126425
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125703126426
125704126427
if( p->bIncr ){
125705
- assert( p->nToken==1 );
125706
- assert( pDL->pNextDocid==0 );
125707
- rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
125708
- &pDL->iDocid, &pDL->pList, &pDL->nList
125709
- );
125710
- if( rc==SQLITE_OK && !pDL->pList ){
125711
- *pbEof = 1;
125712
- }
126428
+ rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
125713126429
}else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
125714126430
sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
125715126431
&pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
125716126432
);
125717126433
pDL->pList = pDL->pNextDocid;
125718126434
}else{
125719
- char *pIter; /* Used to iterate through aAll */
125720
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
125721
- if( pDL->pNextDocid ){
125722
- pIter = pDL->pNextDocid;
125723
- }else{
125724
- pIter = pDL->aAll;
125725
- }
125726
-
125727
- if( pIter>=pEnd ){
125728
- /* We have already reached the end of this doclist. EOF. */
125729
- *pbEof = 1;
125730
- }else{
125731
- sqlite3_int64 iDelta;
125732
- pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
125733
- if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
125734
- pDL->iDocid += iDelta;
125735
- }else{
125736
- pDL->iDocid -= iDelta;
125737
- }
125738
- pDL->pList = pIter;
125739
- fts3PoslistCopy(0, &pIter);
125740
- pDL->nList = (int)(pIter - pDL->pList);
125741
-
125742
- /* pIter now points just past the 0x00 that terminates the position-
125743
- ** list for document pDL->iDocid. However, if this position-list was
125744
- ** edited in place by fts3EvalNearTrim(), then pIter may not actually
125745
- ** point to the start of the next docid value. The following line deals
125746
- ** with this case by advancing pIter past the zero-padding added by
125747
- ** fts3EvalNearTrim(). */
125748
- while( pIter<pEnd && *pIter==0 ) pIter++;
125749
-
125750
- pDL->pNextDocid = pIter;
125751
- assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
125752
- *pbEof = 0;
125753
- }
126435
+ fts3EvalDlPhraseNext(pTab, pDL, pbEof);
125754126436
}
125755126437
125756126438
return rc;
125757126439
}
125758126440
@@ -125773,11 +126455,10 @@
125773126455
** code before returning.
125774126456
*/
125775126457
static void fts3EvalStartReaders(
125776126458
Fts3Cursor *pCsr, /* FTS Cursor handle */
125777126459
Fts3Expr *pExpr, /* Expression to initialize phrases in */
125778
- int bOptOk, /* True to enable incremental loading */
125779126460
int *pRc /* IN/OUT: Error code */
125780126461
){
125781126462
if( pExpr && SQLITE_OK==*pRc ){
125782126463
if( pExpr->eType==FTSQUERY_PHRASE ){
125783126464
int i;
@@ -125784,14 +126465,14 @@
125784126465
int nToken = pExpr->pPhrase->nToken;
125785126466
for(i=0; i<nToken; i++){
125786126467
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
125787126468
}
125788126469
pExpr->bDeferred = (i==nToken);
125789
- *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
126470
+ *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
125790126471
}else{
125791
- fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
125792
- fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
126472
+ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
126473
+ fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
125793126474
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
125794126475
}
125795126476
}
125796126477
}
125797126478
@@ -126029,11 +126710,11 @@
126029126710
/* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126030126711
** for-loop. Except, limit the value to 2^24 to prevent it from
126031126712
** overflowing the 32-bit integer it is stored in. */
126032126713
if( ii<12 ) nLoad4 = nLoad4*4;
126033126714
126034
- if( ii==0 || pTC->pPhrase->nToken>1 ){
126715
+ if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
126035126716
/* Either this is the cheapest token in the entire query, or it is
126036126717
** part of a multi-token phrase. Either way, the entire doclist will
126037126718
** (eventually) be loaded into memory. It may as well be now. */
126038126719
Fts3PhraseToken *pToken = pTC->pToken;
126039126720
int nList = 0;
@@ -126109,11 +126790,11 @@
126109126790
sqlite3_free(aTC);
126110126791
}
126111126792
}
126112126793
#endif
126113126794
126114
- fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
126795
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
126115126796
return rc;
126116126797
}
126117126798
126118126799
/*
126119126800
** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127273,20 @@
126592127273
pCsr->isRequireSeek = 1;
126593127274
pCsr->isMatchinfoNeeded = 1;
126594127275
pCsr->iPrevId = pExpr->iDocid;
126595127276
}while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
126596127277
}
127278
+
127279
+ /* Check if the cursor is past the end of the docid range specified
127280
+ ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
127281
+ if( rc==SQLITE_OK && (
127282
+ (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
127283
+ || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
127284
+ )){
127285
+ pCsr->isEof = 1;
127286
+ }
127287
+
126597127288
return rc;
126598127289
}
126599127290
126600127291
/*
126601127292
** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127306,20 @@
126615127306
Fts3Phrase *pPhrase = pExpr->pPhrase;
126616127307
126617127308
if( pPhrase ){
126618127309
fts3EvalInvalidatePoslist(pPhrase);
126619127310
if( pPhrase->bIncr ){
126620
- assert( pPhrase->nToken==1 );
126621
- assert( pPhrase->aToken[0].pSegcsr );
126622
- sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
127311
+ int i;
127312
+ for(i=0; i<pPhrase->nToken; i++){
127313
+ Fts3PhraseToken *pToken = &pPhrase->aToken[i];
127314
+ assert( pToken->pDeferred==0 );
127315
+ if( pToken->pSegcsr ){
127316
+ sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
127317
+ }
127318
+ }
126623127319
*pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
126624127320
}
126625
-
126626127321
pPhrase->doclist.pNextDocid = 0;
126627127322
pPhrase->doclist.iDocid = 0;
126628127323
}
126629127324
126630127325
pExpr->iDocid = 0;
@@ -126869,19 +127564,27 @@
126869127564
126870127565
iDocid = pExpr->iDocid;
126871127566
pIter = pPhrase->doclist.pList;
126872127567
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
126873127568
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
127569
+ int iMul; /* +1 if csr dir matches index dir, else -1 */
126874127570
int bOr = 0;
126875127571
u8 bEof = 0;
126876
- Fts3Expr *p;
127572
+ u8 bTreeEof = 0;
127573
+ Fts3Expr *p; /* Used to iterate from pExpr to root */
127574
+ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
126877127575
126878127576
/* Check if this phrase descends from an OR expression node. If not,
126879127577
** return NULL. Otherwise, the entry that corresponds to docid
126880
- ** pCsr->iPrevId may lie earlier in the doclist buffer. */
127578
+ ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
127579
+ ** tree that the node is part of has been marked as EOF, but the node
127580
+ ** itself is not EOF, then it may point to an earlier entry. */
127581
+ pNear = pExpr;
126881127582
for(p=pExpr->pParent; p; p=p->pParent){
126882127583
if( p->eType==FTSQUERY_OR ) bOr = 1;
127584
+ if( p->eType==FTSQUERY_NEAR ) pNear = p;
127585
+ if( p->bEof ) bTreeEof = 1;
126883127586
}
126884127587
if( bOr==0 ) return SQLITE_OK;
126885127588
126886127589
/* This is the descendent of an OR node. In this case we cannot use
126887127590
** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127599,63 @@
126896127599
}
126897127600
pIter = pPhrase->doclist.pList;
126898127601
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
126899127602
if( rc!=SQLITE_OK ) return rc;
126900127603
}
127604
+
127605
+ iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
127606
+ while( bTreeEof==1
127607
+ && pNear->bEof==0
127608
+ && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
127609
+ ){
127610
+ int rc = SQLITE_OK;
127611
+ fts3EvalNextRow(pCsr, pExpr, &rc);
127612
+ if( rc!=SQLITE_OK ) return rc;
127613
+ iDocid = pExpr->iDocid;
127614
+ pIter = pPhrase->doclist.pList;
127615
+ }
126901127616
126902
- if( pExpr->bEof ){
126903
- pIter = 0;
126904
- iDocid = 0;
126905
- }
126906127617
bEof = (pPhrase->doclist.nAll==0);
126907127618
assert( bDescDoclist==0 || bDescDoclist==1 );
126908127619
assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
126909127620
126910
- if( pCsr->bDesc==bDescDoclist ){
126911
- int dummy;
126912
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
126913
- sqlite3Fts3DoclistPrev(
126914
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126915
- &pIter, &iDocid, &dummy, &bEof
126916
- );
126917
- }
126918
- }else{
126919
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
126920
- sqlite3Fts3DoclistNext(
126921
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126922
- &pIter, &iDocid, &bEof
126923
- );
127621
+ if( bEof==0 ){
127622
+ if( pCsr->bDesc==bDescDoclist ){
127623
+ int dummy;
127624
+ if( pNear->bEof ){
127625
+ /* This expression is already at EOF. So position it to point to the
127626
+ ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
127627
+ ** iDocid is already set for this entry, so all that is required is
127628
+ ** to set pIter to point to the first byte of the last position-list
127629
+ ** in the doclist.
127630
+ **
127631
+ ** It would also be correct to set pIter and iDocid to zero. In
127632
+ ** this case, the first call to sqltie3Fts4DoclistPrev() below
127633
+ ** would also move the iterator to point to the last entry in the
127634
+ ** doclist. However, this is expensive, as to do so it has to
127635
+ ** iterate through the entire doclist from start to finish (since
127636
+ ** it does not know the docid for the last entry). */
127637
+ pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
127638
+ fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
127639
+ }
127640
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
127641
+ sqlite3Fts3DoclistPrev(
127642
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127643
+ &pIter, &iDocid, &dummy, &bEof
127644
+ );
127645
+ }
127646
+ }else{
127647
+ if( pNear->bEof ){
127648
+ pIter = 0;
127649
+ iDocid = 0;
127650
+ }
127651
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
127652
+ sqlite3Fts3DoclistNext(
127653
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127654
+ &pIter, &iDocid, &bEof
127655
+ );
127656
+ }
126924127657
}
126925127658
}
126926127659
126927127660
if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
126928127661
}
@@ -127026,10 +127759,11 @@
127026127759
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
127027127760
Fts3MultiSegReader csr; /* Must be right after "base" */
127028127761
Fts3SegFilter filter;
127029127762
char *zStop;
127030127763
int nStop; /* Byte-length of string zStop */
127764
+ int iLangid; /* Language id to query */
127031127765
int isEof; /* True if cursor is at EOF */
127032127766
sqlite3_int64 iRowid; /* Current rowid */
127033127767
127034127768
int iCol; /* Current value of 'col' column */
127035127769
int nStat; /* Size of aStat[] array */
@@ -127040,11 +127774,12 @@
127040127774
};
127041127775
127042127776
/*
127043127777
** Schema of the terms table.
127044127778
*/
127045
-#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
127779
+#define FTS3_AUX_SCHEMA \
127780
+ "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
127046127781
127047127782
/*
127048127783
** This function does all the work for both the xConnect and xCreate methods.
127049127784
** These tables have no persistent representation of their own, so xConnect
127050127785
** and xCreate are identical operations.
@@ -127087,11 +127822,11 @@
127087127822
}else{
127088127823
zFts3 = argv[3];
127089127824
}
127090127825
nFts3 = (int)strlen(zFts3);
127091127826
127092
- rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
127827
+ rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
127093127828
if( rc!=SQLITE_OK ) return rc;
127094127829
127095127830
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
127096127831
p = (Fts3auxTable *)sqlite3_malloc(nByte);
127097127832
if( !p ) return SQLITE_NOMEM;
@@ -127147,10 +127882,12 @@
127147127882
){
127148127883
int i;
127149127884
int iEq = -1;
127150127885
int iGe = -1;
127151127886
int iLe = -1;
127887
+ int iLangid = -1;
127888
+ int iNext = 1; /* Next free argvIndex value */
127152127889
127153127890
UNUSED_PARAMETER(pVTab);
127154127891
127155127892
/* This vtab delivers always results in "ORDER BY term ASC" order. */
127156127893
if( pInfo->nOrderBy==1
@@ -127158,40 +127895,52 @@
127158127895
&& pInfo->aOrderBy[0].desc==0
127159127896
){
127160127897
pInfo->orderByConsumed = 1;
127161127898
}
127162127899
127163
- /* Search for equality and range constraints on the "term" column. */
127900
+ /* Search for equality and range constraints on the "term" column.
127901
+ ** And equality constraints on the hidden "languageid" column. */
127164127902
for(i=0; i<pInfo->nConstraint; i++){
127165
- if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
127903
+ if( pInfo->aConstraint[i].usable ){
127166127904
int op = pInfo->aConstraint[i].op;
127167
- if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
127168
- if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
127169
- if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
127170
- if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
127171
- if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
127905
+ int iCol = pInfo->aConstraint[i].iColumn;
127906
+
127907
+ if( iCol==0 ){
127908
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
127909
+ if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
127910
+ if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
127911
+ if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
127912
+ if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
127913
+ }
127914
+ if( iCol==4 ){
127915
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
127916
+ }
127172127917
}
127173127918
}
127174127919
127175127920
if( iEq>=0 ){
127176127921
pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
127177
- pInfo->aConstraintUsage[iEq].argvIndex = 1;
127922
+ pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
127178127923
pInfo->estimatedCost = 5;
127179127924
}else{
127180127925
pInfo->idxNum = 0;
127181127926
pInfo->estimatedCost = 20000;
127182127927
if( iGe>=0 ){
127183127928
pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
127184
- pInfo->aConstraintUsage[iGe].argvIndex = 1;
127929
+ pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
127185127930
pInfo->estimatedCost /= 2;
127186127931
}
127187127932
if( iLe>=0 ){
127188127933
pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
127189
- pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
127934
+ pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
127190127935
pInfo->estimatedCost /= 2;
127191127936
}
127192127937
}
127938
+ if( iLangid>=0 ){
127939
+ pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
127940
+ pInfo->estimatedCost--;
127941
+ }
127193127942
127194127943
return SQLITE_OK;
127195127944
}
127196127945
127197127946
/*
@@ -127347,21 +128096,42 @@
127347128096
sqlite3_value **apVal /* Arguments for the indexing scheme */
127348128097
){
127349128098
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
127350128099
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
127351128100
int rc;
127352
- int isScan;
128101
+ int isScan = 0;
128102
+ int iLangVal = 0; /* Language id to query */
128103
+
128104
+ int iEq = -1; /* Index of term=? value in apVal */
128105
+ int iGe = -1; /* Index of term>=? value in apVal */
128106
+ int iLe = -1; /* Index of term<=? value in apVal */
128107
+ int iLangid = -1; /* Index of languageid=? value in apVal */
128108
+ int iNext = 0;
127353128109
127354128110
UNUSED_PARAMETER(nVal);
127355128111
UNUSED_PARAMETER(idxStr);
127356128112
127357128113
assert( idxStr==0 );
127358128114
assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
127359128115
|| idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
127360128116
|| idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
127361128117
);
127362
- isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
128118
+
128119
+ if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
128120
+ iEq = iNext++;
128121
+ }else{
128122
+ isScan = 1;
128123
+ if( idxNum & FTS4AUX_GE_CONSTRAINT ){
128124
+ iGe = iNext++;
128125
+ }
128126
+ if( idxNum & FTS4AUX_LE_CONSTRAINT ){
128127
+ iLe = iNext++;
128128
+ }
128129
+ }
128130
+ if( iNext<nVal ){
128131
+ iLangid = iNext++;
128132
+ }
127363128133
127364128134
/* In case this cursor is being reused, close and zero it. */
127365128135
testcase(pCsr->filter.zTerm);
127366128136
sqlite3Fts3SegReaderFinish(&pCsr->csr);
127367128137
sqlite3_free((void *)pCsr->filter.zTerm);
@@ -127369,26 +128139,39 @@
127369128139
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
127370128140
127371128141
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
127372128142
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
127373128143
127374
- if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
128144
+ if( iEq>=0 || iGe>=0 ){
127375128145
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
128146
+ assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
127376128147
if( zStr ){
127377128148
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
127378128149
pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
127379128150
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
127380128151
}
127381128152
}
127382
- if( idxNum&FTS4AUX_LE_CONSTRAINT ){
127383
- int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
127384
- pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
127385
- pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
128153
+
128154
+ if( iLe>=0 ){
128155
+ pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
128156
+ pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
127386128157
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
127387128158
}
128159
+
128160
+ if( iLangid>=0 ){
128161
+ iLangVal = sqlite3_value_int(apVal[iLangid]);
127388128162
127389
- rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
128163
+ /* If the user specified a negative value for the languageid, use zero
128164
+ ** instead. This works, as the "languageid=?" constraint will also
128165
+ ** be tested by the VDBE layer. The test will always be false (since
128166
+ ** this module will not return a row with a negative languageid), and
128167
+ ** so the overall query will return zero rows. */
128168
+ if( iLangVal<0 ) iLangVal = 0;
128169
+ }
128170
+ pCsr->iLangid = iLangVal;
128171
+
128172
+ rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
127390128173
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
127391128174
);
127392128175
if( rc==SQLITE_OK ){
127393128176
rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
127394128177
}
@@ -127408,28 +128191,41 @@
127408128191
/*
127409128192
** xColumn - Return a column value.
127410128193
*/
127411128194
static int fts3auxColumnMethod(
127412128195
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
127413
- sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
128196
+ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
127414128197
int iCol /* Index of column to read value from */
127415128198
){
127416128199
Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
127417128200
127418128201
assert( p->isEof==0 );
127419
- if( iCol==0 ){ /* Column "term" */
127420
- sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
127421
- }else if( iCol==1 ){ /* Column "col" */
127422
- if( p->iCol ){
127423
- sqlite3_result_int(pContext, p->iCol-1);
127424
- }else{
127425
- sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
127426
- }
127427
- }else if( iCol==2 ){ /* Column "documents" */
127428
- sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
127429
- }else{ /* Column "occurrences" */
127430
- sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
128202
+ switch( iCol ){
128203
+ case 0: /* term */
128204
+ sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
128205
+ break;
128206
+
128207
+ case 1: /* col */
128208
+ if( p->iCol ){
128209
+ sqlite3_result_int(pCtx, p->iCol-1);
128210
+ }else{
128211
+ sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
128212
+ }
128213
+ break;
128214
+
128215
+ case 2: /* documents */
128216
+ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
128217
+ break;
128218
+
128219
+ case 3: /* occurrences */
128220
+ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
128221
+ break;
128222
+
128223
+ default: /* languageid */
128224
+ assert( iCol==4 );
128225
+ sqlite3_result_int(pCtx, p->iLangid);
128226
+ break;
127431128227
}
127432128228
127433128229
return SQLITE_OK;
127434128230
}
127435128231
@@ -135756,11 +136552,11 @@
135756136552
assert( p->bFts4==0 );
135757136553
sqlite3Fts3CreateStatTable(&rc, p);
135758136554
if( rc ) return rc;
135759136555
}
135760136556
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
135761
- if( rc ) return rc;;
136557
+ if( rc ) return rc;
135762136558
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
135763136559
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
135764136560
sqlite3_step(pStmt);
135765136561
rc = sqlite3_reset(pStmt);
135766136562
return rc;
@@ -136025,10 +136821,13 @@
136025136821
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136026136822
p->nNodeSize = atoi(&zVal[9]);
136027136823
rc = SQLITE_OK;
136028136824
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136029136825
p->nMaxPendingData = atoi(&zVal[11]);
136826
+ rc = SQLITE_OK;
136827
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
136828
+ p->bNoIncrDoclist = atoi(&zVal[21]);
136030136829
rc = SQLITE_OK;
136031136830
#endif
136032136831
}else{
136033136832
rc = SQLITE_ERROR;
136034136833
}
136035136834
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -23,531 +23,10 @@
23 # define SQLITE_PRIVATE static
24 #endif
25 #ifndef SQLITE_API
26 # define SQLITE_API
27 #endif
28 /************** Begin file sqliteInt.h ***************************************/
29 /*
30 ** 2001 September 15
31 **
32 ** The author disclaims copyright to this source code. In place of
33 ** a legal notice, here is a blessing:
34 **
35 ** May you do good and not evil.
36 ** May you find forgiveness for yourself and forgive others.
37 ** May you share freely, never taking more than you give.
38 **
39 *************************************************************************
40 ** Internal interface definitions for SQLite.
41 **
42 */
43 #ifndef _SQLITEINT_H_
44 #define _SQLITEINT_H_
45
46 /*
47 ** These #defines should enable >2GB file support on POSIX if the
48 ** underlying operating system supports it. If the OS lacks
49 ** large file support, or if the OS is windows, these should be no-ops.
50 **
51 ** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
52 ** system #includes. Hence, this block of code must be the very first
53 ** code in all source files.
54 **
55 ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
56 ** on the compiler command line. This is necessary if you are compiling
57 ** on a recent machine (ex: Red Hat 7.2) but you want your code to work
58 ** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
59 ** without this option, LFS is enable. But LFS does not exist in the kernel
60 ** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
61 ** portability you should omit LFS.
62 **
63 ** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
64 */
65 #ifndef SQLITE_DISABLE_LFS
66 # define _LARGE_FILE 1
67 # ifndef _FILE_OFFSET_BITS
68 # define _FILE_OFFSET_BITS 64
69 # endif
70 # define _LARGEFILE_SOURCE 1
71 #endif
72
73 /*
74 ** Include the configuration header output by 'configure' if we're using the
75 ** autoconf-based build
76 */
77 #ifdef _HAVE_SQLITE_CONFIG_H
78 #include "config.h"
79 #endif
80
81 /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
82 /************** Begin file sqliteLimit.h *************************************/
83 /*
84 ** 2007 May 7
85 **
86 ** The author disclaims copyright to this source code. In place of
87 ** a legal notice, here is a blessing:
88 **
89 ** May you do good and not evil.
90 ** May you find forgiveness for yourself and forgive others.
91 ** May you share freely, never taking more than you give.
92 **
93 *************************************************************************
94 **
95 ** This file defines various limits of what SQLite can process.
96 */
97
98 /*
99 ** The maximum length of a TEXT or BLOB in bytes. This also
100 ** limits the size of a row in a table or index.
101 **
102 ** The hard limit is the ability of a 32-bit signed integer
103 ** to count the size: 2^31-1 or 2147483647.
104 */
105 #ifndef SQLITE_MAX_LENGTH
106 # define SQLITE_MAX_LENGTH 1000000000
107 #endif
108
109 /*
110 ** This is the maximum number of
111 **
112 ** * Columns in a table
113 ** * Columns in an index
114 ** * Columns in a view
115 ** * Terms in the SET clause of an UPDATE statement
116 ** * Terms in the result set of a SELECT statement
117 ** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
118 ** * Terms in the VALUES clause of an INSERT statement
119 **
120 ** The hard upper limit here is 32676. Most database people will
121 ** tell you that in a well-normalized database, you usually should
122 ** not have more than a dozen or so columns in any table. And if
123 ** that is the case, there is no point in having more than a few
124 ** dozen values in any of the other situations described above.
125 */
126 #ifndef SQLITE_MAX_COLUMN
127 # define SQLITE_MAX_COLUMN 2000
128 #endif
129
130 /*
131 ** The maximum length of a single SQL statement in bytes.
132 **
133 ** It used to be the case that setting this value to zero would
134 ** turn the limit off. That is no longer true. It is not possible
135 ** to turn this limit off.
136 */
137 #ifndef SQLITE_MAX_SQL_LENGTH
138 # define SQLITE_MAX_SQL_LENGTH 1000000000
139 #endif
140
141 /*
142 ** The maximum depth of an expression tree. This is limited to
143 ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
144 ** want to place more severe limits on the complexity of an
145 ** expression.
146 **
147 ** A value of 0 used to mean that the limit was not enforced.
148 ** But that is no longer true. The limit is now strictly enforced
149 ** at all times.
150 */
151 #ifndef SQLITE_MAX_EXPR_DEPTH
152 # define SQLITE_MAX_EXPR_DEPTH 1000
153 #endif
154
155 /*
156 ** The maximum number of terms in a compound SELECT statement.
157 ** The code generator for compound SELECT statements does one
158 ** level of recursion for each term. A stack overflow can result
159 ** if the number of terms is too large. In practice, most SQL
160 ** never has more than 3 or 4 terms. Use a value of 0 to disable
161 ** any limit on the number of terms in a compount SELECT.
162 */
163 #ifndef SQLITE_MAX_COMPOUND_SELECT
164 # define SQLITE_MAX_COMPOUND_SELECT 500
165 #endif
166
167 /*
168 ** The maximum number of opcodes in a VDBE program.
169 ** Not currently enforced.
170 */
171 #ifndef SQLITE_MAX_VDBE_OP
172 # define SQLITE_MAX_VDBE_OP 25000
173 #endif
174
175 /*
176 ** The maximum number of arguments to an SQL function.
177 */
178 #ifndef SQLITE_MAX_FUNCTION_ARG
179 # define SQLITE_MAX_FUNCTION_ARG 127
180 #endif
181
182 /*
183 ** The maximum number of in-memory pages to use for the main database
184 ** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
185 */
186 #ifndef SQLITE_DEFAULT_CACHE_SIZE
187 # define SQLITE_DEFAULT_CACHE_SIZE 2000
188 #endif
189 #ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
190 # define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
191 #endif
192
193 /*
194 ** The default number of frames to accumulate in the log file before
195 ** checkpointing the database in WAL mode.
196 */
197 #ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
198 # define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
199 #endif
200
201 /*
202 ** The maximum number of attached databases. This must be between 0
203 ** and 62. The upper bound on 62 is because a 64-bit integer bitmap
204 ** is used internally to track attached databases.
205 */
206 #ifndef SQLITE_MAX_ATTACHED
207 # define SQLITE_MAX_ATTACHED 10
208 #endif
209
210
211 /*
212 ** The maximum value of a ?nnn wildcard that the parser will accept.
213 */
214 #ifndef SQLITE_MAX_VARIABLE_NUMBER
215 # define SQLITE_MAX_VARIABLE_NUMBER 999
216 #endif
217
218 /* Maximum page size. The upper bound on this value is 65536. This a limit
219 ** imposed by the use of 16-bit offsets within each page.
220 **
221 ** Earlier versions of SQLite allowed the user to change this value at
222 ** compile time. This is no longer permitted, on the grounds that it creates
223 ** a library that is technically incompatible with an SQLite library
224 ** compiled with a different limit. If a process operating on a database
225 ** with a page-size of 65536 bytes crashes, then an instance of SQLite
226 ** compiled with the default page-size limit will not be able to rollback
227 ** the aborted transaction. This could lead to database corruption.
228 */
229 #ifdef SQLITE_MAX_PAGE_SIZE
230 # undef SQLITE_MAX_PAGE_SIZE
231 #endif
232 #define SQLITE_MAX_PAGE_SIZE 65536
233
234
235 /*
236 ** The default size of a database page.
237 */
238 #ifndef SQLITE_DEFAULT_PAGE_SIZE
239 # define SQLITE_DEFAULT_PAGE_SIZE 1024
240 #endif
241 #if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
242 # undef SQLITE_DEFAULT_PAGE_SIZE
243 # define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
244 #endif
245
246 /*
247 ** Ordinarily, if no value is explicitly provided, SQLite creates databases
248 ** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
249 ** device characteristics (sector-size and atomic write() support),
250 ** SQLite may choose a larger value. This constant is the maximum value
251 ** SQLite will choose on its own.
252 */
253 #ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
254 # define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
255 #endif
256 #if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
257 # undef SQLITE_MAX_DEFAULT_PAGE_SIZE
258 # define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
259 #endif
260
261
262 /*
263 ** Maximum number of pages in one database file.
264 **
265 ** This is really just the default value for the max_page_count pragma.
266 ** This value can be lowered (or raised) at run-time using that the
267 ** max_page_count macro.
268 */
269 #ifndef SQLITE_MAX_PAGE_COUNT
270 # define SQLITE_MAX_PAGE_COUNT 1073741823
271 #endif
272
273 /*
274 ** Maximum length (in bytes) of the pattern in a LIKE or GLOB
275 ** operator.
276 */
277 #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
278 # define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
279 #endif
280
281 /*
282 ** Maximum depth of recursion for triggers.
283 **
284 ** A value of 1 means that a trigger program will not be able to itself
285 ** fire any triggers. A value of 0 means that no trigger programs at all
286 ** may be executed.
287 */
288 #ifndef SQLITE_MAX_TRIGGER_DEPTH
289 # define SQLITE_MAX_TRIGGER_DEPTH 1000
290 #endif
291
292 /************** End of sqliteLimit.h *****************************************/
293 /************** Continuing where we left off in sqliteInt.h ******************/
294
295 /* Disable nuisance warnings on Borland compilers */
296 #if defined(__BORLANDC__)
297 #pragma warn -rch /* unreachable code */
298 #pragma warn -ccc /* Condition is always true or false */
299 #pragma warn -aus /* Assigned value is never used */
300 #pragma warn -csu /* Comparing signed and unsigned */
301 #pragma warn -spa /* Suspicious pointer arithmetic */
302 #endif
303
304 /* Needed for various definitions... */
305 #ifndef _GNU_SOURCE
306 # define _GNU_SOURCE
307 #endif
308
309 #if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
310 # define _BSD_SOURCE
311 #endif
312
313 /*
314 ** Include standard header files as necessary
315 */
316 #ifdef HAVE_STDINT_H
317 #include <stdint.h>
318 #endif
319 #ifdef HAVE_INTTYPES_H
320 #include <inttypes.h>
321 #endif
322
323 /*
324 ** The following macros are used to cast pointers to integers and
325 ** integers to pointers. The way you do this varies from one compiler
326 ** to the next, so we have developed the following set of #if statements
327 ** to generate appropriate macros for a wide range of compilers.
328 **
329 ** The correct "ANSI" way to do this is to use the intptr_t type.
330 ** Unfortunately, that typedef is not available on all compilers, or
331 ** if it is available, it requires an #include of specific headers
332 ** that vary from one machine to the next.
333 **
334 ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
335 ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
336 ** So we have to define the macros in different ways depending on the
337 ** compiler.
338 */
339 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
340 # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
341 # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
342 #elif !defined(__GNUC__) /* Works for compilers other than LLVM */
343 # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
344 # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
345 #elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
346 # define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
347 # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
348 #else /* Generates a warning - but it always works */
349 # define SQLITE_INT_TO_PTR(X) ((void*)(X))
350 # define SQLITE_PTR_TO_INT(X) ((int)(X))
351 #endif
352
353 /*
354 ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
355 ** 0 means mutexes are permanently disable and the library is never
356 ** threadsafe. 1 means the library is serialized which is the highest
357 ** level of threadsafety. 2 means the library is multithreaded - multiple
358 ** threads can use SQLite as long as no two threads try to use the same
359 ** database connection at the same time.
360 **
361 ** Older versions of SQLite used an optional THREADSAFE macro.
362 ** We support that for legacy.
363 */
364 #if !defined(SQLITE_THREADSAFE)
365 # if defined(THREADSAFE)
366 # define SQLITE_THREADSAFE THREADSAFE
367 # else
368 # define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
369 # endif
370 #endif
371
372 /*
373 ** Powersafe overwrite is on by default. But can be turned off using
374 ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
375 */
376 #ifndef SQLITE_POWERSAFE_OVERWRITE
377 # define SQLITE_POWERSAFE_OVERWRITE 1
378 #endif
379
380 /*
381 ** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
382 ** It determines whether or not the features related to
383 ** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
384 ** be overridden at runtime using the sqlite3_config() API.
385 */
386 #if !defined(SQLITE_DEFAULT_MEMSTATUS)
387 # define SQLITE_DEFAULT_MEMSTATUS 1
388 #endif
389
390 /*
391 ** Exactly one of the following macros must be defined in order to
392 ** specify which memory allocation subsystem to use.
393 **
394 ** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
395 ** SQLITE_WIN32_MALLOC // Use Win32 native heap API
396 ** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
397 ** SQLITE_MEMDEBUG // Debugging version of system malloc()
398 **
399 ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
400 ** assert() macro is enabled, each call into the Win32 native heap subsystem
401 ** will cause HeapValidate to be called. If heap validation should fail, an
402 ** assertion will be triggered.
403 **
404 ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
405 ** the default.
406 */
407 #if defined(SQLITE_SYSTEM_MALLOC) \
408 + defined(SQLITE_WIN32_MALLOC) \
409 + defined(SQLITE_ZERO_MALLOC) \
410 + defined(SQLITE_MEMDEBUG)>1
411 # error "Two or more of the following compile-time configuration options\
412 are defined but at most one is allowed:\
413 SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
414 SQLITE_ZERO_MALLOC"
415 #endif
416 #if defined(SQLITE_SYSTEM_MALLOC) \
417 + defined(SQLITE_WIN32_MALLOC) \
418 + defined(SQLITE_ZERO_MALLOC) \
419 + defined(SQLITE_MEMDEBUG)==0
420 # define SQLITE_SYSTEM_MALLOC 1
421 #endif
422
423 /*
424 ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
425 ** sizes of memory allocations below this value where possible.
426 */
427 #if !defined(SQLITE_MALLOC_SOFT_LIMIT)
428 # define SQLITE_MALLOC_SOFT_LIMIT 1024
429 #endif
430
431 /*
432 ** We need to define _XOPEN_SOURCE as follows in order to enable
433 ** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
434 ** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
435 ** it.
436 */
437 #if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
438 # define _XOPEN_SOURCE 600
439 #endif
440
441 /*
442 ** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
443 ** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
444 ** make it true by defining or undefining NDEBUG.
445 **
446 ** Setting NDEBUG makes the code smaller and faster by disabling the
447 ** assert() statements in the code. So we want the default action
448 ** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
449 ** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
450 ** feature.
451 */
452 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
453 # define NDEBUG 1
454 #endif
455 #if defined(NDEBUG) && defined(SQLITE_DEBUG)
456 # undef NDEBUG
457 #endif
458
459 /*
460 ** The testcase() macro is used to aid in coverage testing. When
461 ** doing coverage testing, the condition inside the argument to
462 ** testcase() must be evaluated both true and false in order to
463 ** get full branch coverage. The testcase() macro is inserted
464 ** to help ensure adequate test coverage in places where simple
465 ** condition/decision coverage is inadequate. For example, testcase()
466 ** can be used to make sure boundary values are tested. For
467 ** bitmask tests, testcase() can be used to make sure each bit
468 ** is significant and used at least once. On switch statements
469 ** where multiple cases go to the same block of code, testcase()
470 ** can insure that all cases are evaluated.
471 **
472 */
473 #ifdef SQLITE_COVERAGE_TEST
474 SQLITE_PRIVATE void sqlite3Coverage(int);
475 # define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
476 #else
477 # define testcase(X)
478 #endif
479
480 /*
481 ** The TESTONLY macro is used to enclose variable declarations or
482 ** other bits of code that are needed to support the arguments
483 ** within testcase() and assert() macros.
484 */
485 #if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
486 # define TESTONLY(X) X
487 #else
488 # define TESTONLY(X)
489 #endif
490
491 /*
492 ** Sometimes we need a small amount of code such as a variable initialization
493 ** to setup for a later assert() statement. We do not want this code to
494 ** appear when assert() is disabled. The following macro is therefore
495 ** used to contain that setup code. The "VVA" acronym stands for
496 ** "Verification, Validation, and Accreditation". In other words, the
497 ** code within VVA_ONLY() will only run during verification processes.
498 */
499 #ifndef NDEBUG
500 # define VVA_ONLY(X) X
501 #else
502 # define VVA_ONLY(X)
503 #endif
504
505 /*
506 ** The ALWAYS and NEVER macros surround boolean expressions which
507 ** are intended to always be true or false, respectively. Such
508 ** expressions could be omitted from the code completely. But they
509 ** are included in a few cases in order to enhance the resilience
510 ** of SQLite to unexpected behavior - to make the code "self-healing"
511 ** or "ductile" rather than being "brittle" and crashing at the first
512 ** hint of unplanned behavior.
513 **
514 ** In other words, ALWAYS and NEVER are added for defensive code.
515 **
516 ** When doing coverage testing ALWAYS and NEVER are hard-coded to
517 ** be true and false so that the unreachable code they specify will
518 ** not be counted as untested code.
519 */
520 #if defined(SQLITE_COVERAGE_TEST)
521 # define ALWAYS(X) (1)
522 # define NEVER(X) (0)
523 #elif !defined(NDEBUG)
524 # define ALWAYS(X) ((X)?1:(assert(0),0))
525 # define NEVER(X) ((X)?(assert(0),1):0)
526 #else
527 # define ALWAYS(X) (X)
528 # define NEVER(X) (X)
529 #endif
530
531 /*
532 ** Return true (non-zero) if the input is a integer that is too large
533 ** to fit in 32-bits. This macro is used inside of various testcase()
534 ** macros to verify that we have tested SQLite for large-file support.
535 */
536 #define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
537
538 /*
539 ** The macro unlikely() is a hint that surrounds a boolean
540 ** expression that is usually false. Macro likely() surrounds
541 ** a boolean expression that is usually true. These hints could,
542 ** in theory, be used by the compiler to generate better code, but
543 ** currently they are just comments for human readers.
544 */
545 #define likely(X) (X)
546 #define unlikely(X) (X)
547
548 /************** Include sqlite3.h in the middle of sqliteInt.h ***************/
549 /************** Begin file sqlite3.h *****************************************/
550 /*
551 ** 2001 September 15
552 **
553 ** The author disclaims copyright to this source code. In place of
@@ -656,11 +135,11 @@
656 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
657 ** [sqlite_version()] and [sqlite_source_id()].
658 */
659 #define SQLITE_VERSION "3.8.1"
660 #define SQLITE_VERSION_NUMBER 3008001
661 #define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
662
663 /*
664 ** CAPI3REF: Run-Time Library Version Numbers
665 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
666 **
@@ -2164,31 +1643,31 @@
2164 ** supplied by the application must not invoke any SQLite interface.
2165 ** In a multi-threaded application, the application-defined logger
2166 ** function must be threadsafe. </dd>
2167 **
2168 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
2169 ** <dd> This option takes a single argument of type int. If non-zero, then
2170 ** URI handling is globally enabled. If the parameter is zero, then URI handling
2171 ** is globally disabled. If URI handling is globally enabled, all filenames
2172 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
2173 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
2174 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
2175 ** connection is opened. If it is globally disabled, filenames are
2176 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
2177 ** database connection is opened. By default, URI handling is globally
2178 ** disabled. The default value may be changed by compiling with the
2179 ** [SQLITE_USE_URI] symbol defined.
2180 **
2181 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
2182 ** <dd> This option takes a single integer argument which is interpreted as
2183 ** a boolean in order to enable or disable the use of covering indices for
2184 ** full table scans in the query optimizer. The default setting is determined
2185 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
2186 ** if that compile-time option is omitted.
2187 ** The ability to disable the use of covering indices for full table scans
2188 ** is because some incorrectly coded legacy applications might malfunction
2189 ** malfunction when the optimization is enabled. Providing the ability to
2190 ** disable the optimization allows the older, buggy application code to work
2191 ** without change even with newer versions of SQLite.
2192 **
2193 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
2194 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -2213,20 +1692,20 @@
2213 ** configuration option can be seen in the "test_sqllog.c" source file in
2214 ** the canonical SQLite source tree.</dd>
2215 **
2216 ** [[SQLITE_CONFIG_MMAP_SIZE]]
2217 ** <dt>SQLITE_CONFIG_MMAP_SIZE
2218 ** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
2219 ** that are the default mmap size limit (the default setting for
2220 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
2221 ** The default setting can be overridden by each database connection using
2222 ** either the [PRAGMA mmap_size] command, or by using the
2223 ** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
2224 ** cannot be changed at run-time. Nor may the maximum allowed mmap size
2225 ** exceed the compile-time maximum mmap size set by the
2226 ** [SQLITE_MAX_MMAP_SIZE] compile-time option.
2227 ** If either argument to this option is negative, then that argument is
2228 ** changed to its compile-time default.
2229 ** </dl>
2230 */
2231 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
2232 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
@@ -7846,11 +7325,530 @@
7846
7847 #endif /* ifndef _SQLITE3RTREE_H_ */
7848
7849
7850 /************** End of sqlite3.h *********************************************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7851 /************** Continuing where we left off in sqliteInt.h ******************/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7852 /************** Include hash.h in the middle of sqliteInt.h ******************/
7853 /************** Begin file hash.h ********************************************/
7854 /*
7855 ** 2001 September 22
7856 **
@@ -8272,10 +8270,35 @@
8272 typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
8273 #else
8274 typedef u32 tRowcnt; /* 32-bit is the default */
8275 #endif
8276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8277 /*
8278 ** Macros to determine whether the machine is big or little endian,
8279 ** evaluated at runtime.
8280 */
8281 #ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10442,12 @@
10419 char *zDflt; /* Original text of the default value */
10420 char *zType; /* Data type for this column */
10421 char *zColl; /* Collating sequence. If NULL, use the default */
10422 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
10423 char affinity; /* One of the SQLITE_AFF_... values */
10424 u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
 
10425 };
10426
10427 /* Allowed values for Column.colFlags:
10428 */
10429 #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10607,11 @@
10583 tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
10584 int tnum; /* Root BTree node for this table (see note above) */
10585 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10586 i16 nCol; /* Number of columns in this table */
10587 u16 nRef; /* Number of pointers to this Table */
 
10588 u8 tabFlags; /* Mask of TF_* values */
10589 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10590 #ifndef SQLITE_OMIT_ALTERTABLE
10591 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10592 #endif
@@ -10694,11 +10719,11 @@
10694 #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
10695 #define OE_SetNull 7 /* Set the foreign key value to NULL */
10696 #define OE_SetDflt 8 /* Set the foreign key value to its default */
10697 #define OE_Cascade 9 /* Cascade the changes */
10698
10699 #define OE_Default 99 /* Do whatever the default action is */
10700
10701
10702 /*
10703 ** An instance of the following structure is passed as the first
10704 ** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10806,11 @@
10781 Schema *pSchema; /* Schema containing this index */
10782 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10783 char **azColl; /* Array of collation sequence names for index */
10784 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
10785 int tnum; /* DB Page containing root of this index */
 
10786 u16 nColumn; /* Number of columns in table used by this index */
10787 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10788 unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10789 unsigned bUnordered:1; /* Use this index for == or IN queries only */
10790 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11662,11 @@
11636 */
11637 typedef struct DbFixer DbFixer;
11638 struct DbFixer {
11639 Parse *pParse; /* The parsing context. Error messages written here */
11640 Schema *pSchema; /* Fix items to this schema */
 
11641 const char *zDb; /* Make sure all objects are contained in this database */
11642 const char *zType; /* Type of the container - used for error messages */
11643 const Token *pName; /* Name of the container - used for error messages */
11644 };
11645
@@ -12174,11 +12201,11 @@
12174 # define sqlite3AuthContextPush(a,b,c)
12175 # define sqlite3AuthContextPop(a) ((void)(a))
12176 #endif
12177 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
12178 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12179 SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12180 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
12181 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
12182 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
12183 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
12184 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12213,16 @@
12186 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
12187 SQLITE_PRIVATE int sqlite3Atoi(const char*);
12188 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
12189 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
12190 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
 
 
 
 
 
 
12191
12192 /*
12193 ** Routines to read and write variable-length integers. These used to
12194 ** be defined locally, but now we use the varint routines in the util.c
12195 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12335,11 @@
12302 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12303 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12304 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
12305 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
12306 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12307 SQLITE_PRIVATE char sqlite3AffinityType(const char*);
12308 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
12309 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
12310 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
12311 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
12312 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -12435,14 +12468,14 @@
12435 SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
12436 SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
12437 SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
12438 #else
12439 #define sqlite3FkActions(a,b,c,d,e,f)
12440 #define sqlite3FkCheck(a,b,c,d)
12441 #define sqlite3FkDropTable(a,b,c)
12442 #define sqlite3FkOldmask(a,b) 0
12443 #define sqlite3FkRequired(a,b,c,d,e,f) 0
12444 #endif
12445 #ifndef SQLITE_OMIT_FOREIGN_KEY
12446 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
12447 SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
12448 #else
@@ -14397,10 +14430,14 @@
14397 ** is available. This routine returns 0 on success and
14398 ** non-zero on any kind of error.
14399 **
14400 ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
14401 ** routine will always fail.
 
 
 
 
14402 */
14403 static int osLocaltime(time_t *t, struct tm *pTm){
14404 int rc;
14405 #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
14406 && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
@@ -14453,10 +14490,15 @@
14453 memset(&sLocal, 0, sizeof(sLocal));
14454
14455 x = *p;
14456 computeYMD_HMS(&x);
14457 if( x.Y<1971 || x.Y>=2038 ){
 
 
 
 
 
14458 x.Y = 2000;
14459 x.M = 1;
14460 x.D = 1;
14461 x.h = 0;
14462 x.m = 0;
@@ -22387,10 +22429,87 @@
22387 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
22388 if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
22389 }
22390 }
22391 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22392
22393 /************** End of util.c ************************************************/
22394 /************** Begin file hash.c ********************************************/
22395 /*
22396 ** 2001 September 22
@@ -31382,11 +31501,11 @@
31382 #endif
31383
31384 #define osGetVersionExA ((BOOL(WINAPI*)( \
31385 LPOSVERSIONINFOA))aSyscall[34].pCurrent)
31386
31387 #if defined(SQLITE_WIN32_HAS_WIDE)
31388 { "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
31389 #else
31390 { "GetVersionExW", (SYSCALL)0, 0 },
31391 #endif
31392
@@ -32896,12 +33015,11 @@
32896 #endif
32897 assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
32898 OSTRACE(("CLOSE file=%p\n", pFile->h));
32899
32900 #if SQLITE_MAX_MMAP_SIZE>0
32901 rc = winUnmapfile(pFile);
32902 if( rc!=SQLITE_OK ) return rc;
32903 #endif
32904
32905 do{
32906 rc = osCloseHandle(pFile->h);
32907 /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -33703,11 +33821,11 @@
33703 }
33704 *(i64*)pArg = pFile->mmapSizeMax;
33705 if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
33706 pFile->mmapSizeMax = newLimit;
33707 if( pFile->mmapSize>0 ){
33708 (void)winUnmapfile(pFile);
33709 rc = winMapfile(pFile, -1);
33710 }
33711 }
33712 OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
33713 return rc;
@@ -33920,11 +34038,11 @@
33920 osGetCurrentProcessId(), deleteFlag));
33921 pp = &winShmNodeList;
33922 while( (p = *pp)!=0 ){
33923 if( p->nRef==0 ){
33924 int i;
33925 if( p->mutex ) sqlite3_mutex_free(p->mutex);
33926 for(i=0; i<p->nRegion; i++){
33927 BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
33928 OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
33929 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
33930 UNUSED_VARIABLE_VALUE(bRc);
@@ -34773,10 +34891,11 @@
34773 ** API prior to using it.
34774 */
34775 if( winIsDriveLetterAndColon(zDir) ){
34776 zConverted = winConvertFromUtf8Filename(zDir);
34777 if( !zConverted ){
 
34778 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34779 return SQLITE_IOERR_NOMEM;
34780 }
34781 if( winIsDir(zConverted) ){
34782 sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir);
@@ -34785,17 +34904,19 @@
34785 }
34786 sqlite3_free(zConverted);
34787 }else{
34788 zConverted = sqlite3MallocZero( nBuf+1 );
34789 if( !zConverted ){
 
34790 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34791 return SQLITE_IOERR_NOMEM;
34792 }
34793 if( cygwin_conv_path(
34794 osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
34795 zConverted, nBuf+1)<0 ){
34796 sqlite3_free(zConverted);
 
34797 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
34798 return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
34799 "winGetTempname1", zDir);
34800 }
34801 if( winIsDir(zConverted) ){
@@ -34805,10 +34926,11 @@
34805 */
34806 if( osIsNT() ){
34807 char *zUtf8 = winUnicodeToUtf8(zConverted);
34808 if( !zUtf8 ){
34809 sqlite3_free(zConverted);
 
34810 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34811 return SQLITE_IOERR_NOMEM;
34812 }
34813 sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8);
34814 sqlite3_free(zUtf8);
@@ -34820,11 +34942,10 @@
34820 break;
34821 }
34822 }
34823 sqlite3_free(zConverted);
34824 }
34825 break;
34826 }
34827 }
34828 #elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
34829 else if( osIsNT() ){
34830 char *zMulti;
@@ -35190,13 +35311,13 @@
35190 pFile->zDeleteOnClose = zConverted;
35191 }else
35192 #endif
35193 {
35194 sqlite3_free(zConverted);
35195 sqlite3_free(zTmpname);
35196 }
35197
 
35198 pFile->pMethod = &winIoMethod;
35199 pFile->pVfs = pVfs;
35200 pFile->h = h;
35201 if( isReadonly ){
35202 pFile->ctrlFlags |= WINFILE_RDONLY;
@@ -48986,17 +49107,17 @@
48986 ** page contain a special header (the "file header") that describes the file.
48987 ** The format of the file header is as follows:
48988 **
48989 ** OFFSET SIZE DESCRIPTION
48990 ** 0 16 Header string: "SQLite format 3\000"
48991 ** 16 2 Page size in bytes.
48992 ** 18 1 File format write version
48993 ** 19 1 File format read version
48994 ** 20 1 Bytes of unused space at the end of each page
48995 ** 21 1 Max embedded payload fraction
48996 ** 22 1 Min embedded payload fraction
48997 ** 23 1 Min leaf payload fraction
48998 ** 24 4 File change counter
48999 ** 28 4 Reserved for future use
49000 ** 32 4 First freelist page
49001 ** 36 4 Number of freelist pages in the file
49002 ** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49127,14 @@
49006 ** 48 4 Size of page cache
49007 ** 52 4 Largest root-page (auto/incr_vacuum)
49008 ** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
49009 ** 60 4 User version
49010 ** 64 4 Incremental vacuum mode
49011 ** 68 4 unused
49012 ** 72 4 unused
49013 ** 76 4 unused
 
49014 **
49015 ** All of the integer values are big-endian (most significant byte first).
49016 **
49017 ** The file change counter is incremented when the database is changed
49018 ** This counter allows other processes to know when the file has changed
@@ -51922,10 +52044,22 @@
51922 ** MX_CELL_SIZE(pBt) bytes.
51923 */
51924 static void allocateTempSpace(BtShared *pBt){
51925 if( !pBt->pTmpSpace ){
51926 pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
 
 
 
 
 
 
 
 
 
 
 
 
51927 }
51928 }
51929
51930 /*
51931 ** Free the pBt->pTmpSpace allocation
@@ -52378,11 +52512,10 @@
52378 pBt->max1bytePayload = (u8)pBt->maxLocal;
52379 }
52380 assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
52381 pBt->pPage1 = pPage1;
52382 pBt->nPage = nPage;
52383 assert( pPage1->leaf==0 || pPage1->leaf==1 );
52384 return SQLITE_OK;
52385
52386 page1_init_failed:
52387 releasePage(pPage1);
52388 pBt->pPage1 = 0;
@@ -52538,11 +52671,11 @@
52538 ** is requested, this is a no-op.
52539 */
52540 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
52541 goto trans_begun;
52542 }
52543 assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
52544
52545 /* Write transactions are not possible on a read-only database */
52546 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
52547 rc = SQLITE_READONLY;
52548 goto trans_begun;
@@ -60189,11 +60322,13 @@
60189 }
60190
60191 pRec->nField = p->iVal+1;
60192 return &pRec->aMem[p->iVal];
60193 }
60194 #endif
 
 
60195 return sqlite3ValueNew(db);
60196 }
60197
60198 /*
60199 ** Extract a value from the supplied expression in the manner described
@@ -60203,11 +60338,11 @@
60203 ** If pCtx is NULL and an error occurs after the sqlite3_value object
60204 ** has been allocated, it is freed before returning. Or, if pCtx is not
60205 ** NULL, it is assumed that the caller will free any allocated object
60206 ** in all cases.
60207 */
60208 int valueFromExpr(
60209 sqlite3 *db, /* The database connection */
60210 Expr *pExpr, /* The expression to evaluate */
60211 u8 enc, /* Encoding to use */
60212 u8 affinity, /* Affinity to use */
60213 sqlite3_value **ppVal, /* Write the new value here */
@@ -60360,10 +60495,11 @@
60360 int nVal; /* Bytes of space required for argv[0] */
60361 int nRet;
60362 sqlite3 *db;
60363 u8 *aRet;
60364
 
60365 iSerial = sqlite3VdbeSerialType(argv[0], file_format);
60366 nSerial = sqlite3VarintLen(iSerial);
60367 nVal = sqlite3VdbeSerialTypeLen(iSerial);
60368 db = sqlite3_context_db_handle(context);
60369
@@ -62977,10 +63113,11 @@
62977 }
62978 fclose(out);
62979 }
62980 }
62981 #endif
 
62982 p->magic = VDBE_MAGIC_INIT;
62983 return p->rc & db->errMask;
62984 }
62985
62986 /*
@@ -75299,10 +75436,14 @@
75299 sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
75300 "constant between 0.0 and 1.0");
75301 pNC->nErr++;
75302 }
75303 }else{
 
 
 
 
75304 pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
75305 }
75306 }
75307 }
75308 #ifndef SQLITE_OMIT_AUTHORIZATION
@@ -76082,11 +76223,11 @@
76082 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
76083 }
76084 #ifndef SQLITE_OMIT_CAST
76085 if( op==TK_CAST ){
76086 assert( !ExprHasProperty(pExpr, EP_IntValue) );
76087 return sqlite3AffinityType(pExpr->u.zToken);
76088 }
76089 #endif
76090 if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
76091 && pExpr->pTab!=0
76092 ){
@@ -78502,11 +78643,11 @@
78502 case TK_CAST: {
78503 /* Expressions of the form: CAST(pLeft AS token) */
78504 int aff, to_op;
78505 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
78506 assert( !ExprHasProperty(pExpr, EP_IntValue) );
78507 aff = sqlite3AffinityType(pExpr->u.zToken);
78508 to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
78509 assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
78510 assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
78511 assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
78512 assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79310,11 @@
79169 }
79170 #ifndef SQLITE_OMIT_CAST
79171 case TK_CAST: {
79172 /* Expressions of the form: CAST(pLeft AS token) */
79173 const char *zAff = "unk";
79174 switch( sqlite3AffinityType(pExpr->u.zToken) ){
79175 case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
79176 case SQLITE_AFF_NONE: zAff = "NONE"; break;
79177 case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
79178 case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
79179 case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81173,11 +81314,11 @@
81173 ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
81174 ** created and used by SQLite versions 3.7.9 and later and with
81175 ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
81176 ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
81177 ** version of sqlite_stat3 and is only available when compiled with
81178 ** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is
81179 ** not possible to enable both STAT3 and STAT4 at the same time. If they
81180 ** are both enabled, then STAT4 takes precedence.
81181 **
81182 ** For most applications, sqlite_stat1 provides all the statisics required
81183 ** for the query planner to make good choices.
@@ -81249,16 +81390,16 @@
81249 **
81250 ** The sqlite_stat4 table contains multiple entries for each index.
81251 ** The idx column names the index and the tbl column is the table of the
81252 ** index. If the idx and tbl columns are the same, then the sample is
81253 ** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
81254 ** binary encoding of a key from the index, with the trailing rowid
81255 ** omitted. The nEq column is a list of integers. The first integer
81256 ** is the approximate number of entries in the index whose left-most
81257 ** column exactly matches the left-most column of the sample. The second
81258 ** integer in nEq is the approximate number of entries in the index where
81259 ** the first two columns match the first two columns of the sample.
81260 ** And so forth. nLt is another list of integers that show the approximate
81261 ** number of entries that are strictly less than the sample. The first
81262 ** integer in nLt contains the number of entries in the index where the
81263 ** left-most column is less than the left-most column of the sample.
81264 ** The K-th integer in the nLt entry is the number of index entries
@@ -81585,11 +81726,11 @@
81585 }
81586
81587 /*
81588 ** Copy the contents of object (*pFrom) into (*pTo).
81589 */
81590 void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
81591 pTo->iRowid = pFrom->iRowid;
81592 pTo->isPSample = pFrom->isPSample;
81593 pTo->iCol = pFrom->iCol;
81594 pTo->iHash = pFrom->iHash;
81595 memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
@@ -81730,10 +81871,15 @@
81730 ){
81731 sampleInsert(p, &p->current, 0);
81732 }
81733 }
81734 #endif
 
 
 
 
 
81735 }
81736
81737 /*
81738 ** Implementation of the stat_push SQL function: stat_push(P,R,C)
81739 ** Arguments:
@@ -81755,10 +81901,12 @@
81755
81756 /* The three function arguments */
81757 Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
81758 int iChng = sqlite3_value_int(argv[1]);
81759
 
 
81760 assert( p->nCol>1 ); /* Includes rowid field */
81761 assert( iChng<p->nCol );
81762
81763 if( p->nRow==0 ){
81764 /* This is the first call to this function. Do initialization. */
@@ -81884,16 +82032,16 @@
81884 if( zRet==0 ){
81885 sqlite3_result_error_nomem(context);
81886 return;
81887 }
81888
81889 sqlite3_snprintf(24, zRet, "%lld", p->nRow);
81890 z = zRet + sqlite3Strlen30(zRet);
81891 for(i=0; i<(p->nCol-1); i++){
81892 i64 nDistinct = p->current.anDLt[i] + 1;
81893 i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
81894 sqlite3_snprintf(24, z, " %lld", iVal);
81895 z += sqlite3Strlen30(z);
81896 assert( p->current.anEq[i] );
81897 }
81898 assert( z[0]=='\0' && z>zRet );
81899
@@ -81930,20 +82078,23 @@
81930 sqlite3_result_error_nomem(context);
81931 }else{
81932 int i;
81933 char *z = zRet;
81934 for(i=0; i<p->nCol; i++){
81935 sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
81936 z += sqlite3Strlen30(z);
81937 }
81938 assert( z[0]=='\0' && z>zRet );
81939 z[-1] = '\0';
81940 sqlite3_result_text(context, zRet, -1, sqlite3_free);
81941 }
81942 }
81943 }
81944 #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
 
 
 
81945 }
81946 static const FuncDef statGetFuncdef = {
81947 1+IsStat34, /* nArg */
81948 SQLITE_UTF8, /* funcFlags */
81949 0, /* pUserData */
@@ -81958,12 +82109,14 @@
81958
81959 static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
81960 assert( regOut!=regStat4 && regOut!=regStat4+1 );
81961 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
81962 sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
81963 #else
81964 assert( iParam==STAT_GET_STAT1 );
 
 
81965 #endif
81966 sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
81967 sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
81968 sqlite3VdbeChangeP5(v, 1 + IsStat34);
81969 }
@@ -82391,22 +82544,20 @@
82391 ** The first argument points to a nul-terminated string containing a
82392 ** list of space separated integers. Read the first nOut of these into
82393 ** the array aOut[].
82394 */
82395 static void decodeIntArray(
82396 char *zIntArray,
82397 int nOut,
82398 tRowcnt *aOut,
82399 int *pbUnordered
82400 ){
82401 char *z = zIntArray;
82402 int c;
82403 int i;
82404 tRowcnt v;
82405
82406 assert( pbUnordered==0 || *pbUnordered==0 );
82407
82408 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
82409 if( z==0 ) z = "";
82410 #else
82411 if( NEVER(z==0) ) z = "";
82412 #endif
@@ -82417,12 +82568,23 @@
82417 z++;
82418 }
82419 aOut[i] = v;
82420 if( *z==' ' ) z++;
82421 }
82422 if( pbUnordered && strcmp(z, "unordered")==0 ){
82423 *pbUnordered = 1;
 
 
 
 
 
 
 
 
 
 
 
82424 }
82425 }
82426
82427 /*
82428 ** This callback is invoked once for each index when reading the
@@ -82457,16 +82619,17 @@
82457 pIndex = 0;
82458 }
82459 z = argv[2];
82460
82461 if( pIndex ){
82462 int bUnordered = 0;
82463 decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
82464 if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
82465 pIndex->bUnordered = bUnordered;
82466 }else{
82467 decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
 
 
 
82468 }
82469
82470 return 0;
82471 }
82472
@@ -83185,32 +83348,28 @@
83185 #endif /* SQLITE_OMIT_ATTACH */
83186
83187 /*
83188 ** Initialize a DbFixer structure. This routine must be called prior
83189 ** to passing the structure to one of the sqliteFixAAAA() routines below.
83190 **
83191 ** The return value indicates whether or not fixation is required. TRUE
83192 ** means we do need to fix the database references, FALSE means we do not.
83193 */
83194 SQLITE_PRIVATE int sqlite3FixInit(
83195 DbFixer *pFix, /* The fixer to be initialized */
83196 Parse *pParse, /* Error messages will be written here */
83197 int iDb, /* This is the database that must be used */
83198 const char *zType, /* "view", "trigger", or "index" */
83199 const Token *pName /* Name of the view, trigger, or index */
83200 ){
83201 sqlite3 *db;
83202
83203 if( NEVER(iDb<0) || iDb==1 ) return 0;
83204 db = pParse->db;
83205 assert( db->nDb>iDb );
83206 pFix->pParse = pParse;
83207 pFix->zDb = db->aDb[iDb].zName;
83208 pFix->pSchema = db->aDb[iDb].pSchema;
83209 pFix->zType = zType;
83210 pFix->pName = pName;
83211 return 1;
83212 }
83213
83214 /*
83215 ** The following set of routines walk through the parse tree and assign
83216 ** a specific database to all table references where the database name
@@ -83234,19 +83393,21 @@
83234 struct SrcList_item *pItem;
83235
83236 if( NEVER(pList==0) ) return 0;
83237 zDb = pFix->zDb;
83238 for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83239 if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83240 sqlite3ErrorMsg(pFix->pParse,
83241 "%s %T cannot reference objects in database %s",
83242 pFix->zType, pFix->pName, pItem->zDatabase);
83243 return 1;
83244 }
83245 sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83246 pItem->zDatabase = 0;
83247 pItem->pSchema = pFix->pSchema;
 
 
83248 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
83249 if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
83250 if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
83251 #endif
83252 }
@@ -83264,13 +83425,25 @@
83264 if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
83265 return 1;
83266 }
83267 if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
83268 return 1;
 
 
 
83269 }
83270 if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
83271 return 1;
 
 
 
 
 
 
 
 
 
83272 }
83273 pSelect = pSelect->pPrior;
83274 }
83275 return 0;
83276 }
@@ -83277,10 +83450,18 @@
83277 SQLITE_PRIVATE int sqlite3FixExpr(
83278 DbFixer *pFix, /* Context of the fixation */
83279 Expr *pExpr /* The expression to be fixed to one database */
83280 ){
83281 while( pExpr ){
 
 
 
 
 
 
 
 
83282 if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
83283 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
83284 if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
83285 }else{
83286 if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84641,11 @@
84460 }
84461 pTable->zName = zName;
84462 pTable->iPKey = -1;
84463 pTable->pSchema = db->aDb[iDb].pSchema;
84464 pTable->nRef = 1;
84465 pTable->nRowEst = 1000000;
84466 assert( pParse->pNewTable==0 );
84467 pParse->pNewTable = pTable;
84468
84469 /* If this is the magic sqlite_sequence table used by autoincrement,
84470 ** then record a pointer to this table in the main database structure
@@ -84607,10 +84788,11 @@
84607 /* If there is no type specified, columns have the default affinity
84608 ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
84609 ** be called next to set pCol->affinity correctly.
84610 */
84611 pCol->affinity = SQLITE_AFF_NONE;
 
84612 p->nCol++;
84613 }
84614
84615 /*
84616 ** This routine is called by the parser while in the middle of
@@ -84648,26 +84830,30 @@
84648 ** 'DOUB' | SQLITE_AFF_REAL
84649 **
84650 ** If none of the substrings in the above table are found,
84651 ** SQLITE_AFF_NUMERIC is returned.
84652 */
84653 SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
84654 u32 h = 0;
84655 char aff = SQLITE_AFF_NUMERIC;
 
84656
84657 if( zIn ) while( zIn[0] ){
 
84658 h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
84659 zIn++;
84660 if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84661 aff = SQLITE_AFF_TEXT;
 
84662 }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
84663 aff = SQLITE_AFF_TEXT;
84664 }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
84665 aff = SQLITE_AFF_TEXT;
84666 }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
84667 && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
84668 aff = SQLITE_AFF_NONE;
 
84669 #ifndef SQLITE_OMIT_FLOATING_POINT
84670 }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
84671 && aff==SQLITE_AFF_NUMERIC ){
84672 aff = SQLITE_AFF_REAL;
84673 }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84867,32 @@
84681 aff = SQLITE_AFF_INTEGER;
84682 break;
84683 }
84684 }
84685
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84686 return aff;
84687 }
84688
84689 /*
84690 ** This routine is called by the parser while in the middle of
@@ -84702,11 +84910,11 @@
84702 p = pParse->pNewTable;
84703 if( p==0 || NEVER(p->nCol<1) ) return;
84704 pCol = &p->aCol[p->nCol-1];
84705 assert( pCol->zType==0 );
84706 pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84707 pCol->affinity = sqlite3AffinityType(pCol->zType);
84708 }
84709
84710 /*
84711 ** The expression is the default value for the most recently added column
84712 ** of the table currently under construction.
@@ -85050,18 +85258,46 @@
85050 testcase( pCol->affinity==SQLITE_AFF_REAL );
85051
85052 zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
85053 len = sqlite3Strlen30(zType);
85054 assert( pCol->affinity==SQLITE_AFF_NONE
85055 || pCol->affinity==sqlite3AffinityType(zType) );
85056 memcpy(&zStmt[k], zType, len);
85057 k += len;
85058 assert( k<=n );
85059 }
85060 sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
85061 return zStmt;
85062 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85063
85064 /*
85065 ** This routine is called to report the final ")" that terminates
85066 ** a CREATE TABLE statement.
85067 **
@@ -85085,13 +85321,14 @@
85085 Parse *pParse, /* Parse context */
85086 Token *pCons, /* The ',' token after the last column defn. */
85087 Token *pEnd, /* The final ')' token in the CREATE TABLE */
85088 Select *pSelect /* Select from a "CREATE ... AS SELECT" */
85089 ){
85090 Table *p;
85091 sqlite3 *db = pParse->db;
85092 int iDb;
 
85093
85094 if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
85095 return;
85096 }
85097 p = pParse->pNewTable;
@@ -85106,10 +85343,16 @@
85106 */
85107 if( p->pCheck ){
85108 sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
85109 }
85110 #endif /* !defined(SQLITE_OMIT_CHECK) */
 
 
 
 
 
 
85111
85112 /* If the db->init.busy is 1 it means we are reading the SQL off the
85113 ** "sqlite_master" or "sqlite_temp_master" table on the disk.
85114 ** So do not write to the disk again. Extract the root page number
85115 ** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85546,12 @@
85303 sqlite3SelectDelete(db, pSelect);
85304 return;
85305 }
85306 sqlite3TwoPartName(pParse, pName1, pName2, &pName);
85307 iDb = sqlite3SchemaToIndex(db, p->pSchema);
85308 if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
85309 && sqlite3FixSelect(&sFix, pSelect)
85310 ){
85311 sqlite3SelectDelete(db, pSelect);
85312 return;
85313 }
85314
85315 /* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86308,14 @@
86066 sqlite3 *db = pParse->db;
86067 Db *pDb; /* The specific table containing the indexed database */
86068 int iDb; /* Index of the database that is being written */
86069 Token *pName = 0; /* Unqualified name of the index to create */
86070 struct ExprList_item *pListItem; /* For looping over pList */
86071 int nCol;
86072 int nExtra = 0;
86073 char *zExtra;
 
86074
86075 assert( pParse->nErr==0 ); /* Never called with prior errors */
86076 if( db->mallocFailed || IN_DECLARE_VTAB ){
86077 goto exit_create_index;
86078 }
@@ -86105,13 +86348,12 @@
86105 iDb = 1;
86106 }
86107 }
86108 #endif
86109
86110 if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
86111 sqlite3FixSrcList(&sFix, pTblName)
86112 ){
86113 /* Because the parser constructs pTblName from a single identifier,
86114 ** sqlite3FixSrcList can never fail. */
86115 assert(0);
86116 }
86117 pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86538,10 @@
86296 ** same column more than once cannot be an error because that would
86297 ** break backwards compatibility - it needs to be a warning.
86298 */
86299 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
86300 const char *zColName = pListItem->zName;
86301 Column *pTabCol;
86302 int requestedSortOrder;
86303 char *zColl; /* Collation sequence name */
86304
86305 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
86306 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86574,11 @@
86333 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
86334 pIndex->aSortOrder[i] = (u8)requestedSortOrder;
86335 if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
86336 }
86337 sqlite3DefaultRowEst(pIndex);
 
86338
86339 if( pTab==pParse->pNewTable ){
86340 /* This routine has been called to create an automatic index as a
86341 ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
86342 ** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88480,11 @@
88238 ** API function sqlite3_count_changes) to be set incorrectly. */
88239 if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
88240 && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
88241 ){
88242 assert( !isView );
 
88243 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
88244 pTab->zName, P4_STATIC);
88245 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
88246 assert( pIdx->pSchema==pTab->pSchema );
88247 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -90943,11 +91186,11 @@
90943 ** generating any VDBE code. If one can be found, then jump over
90944 ** the entire DELETE if there are no outstanding deferred constraints
90945 ** when this statement is run. */
90946 FKey *p;
90947 for(p=pTab->pFKey; p; p=p->pNextFrom){
90948 if( p->isDeferred ) break;
90949 }
90950 if( !p ) return;
90951 iSkip = sqlite3VdbeMakeLabel(v);
90952 sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
90953 }
@@ -90957,15 +91200,22 @@
90957 pParse->disableTriggers = 0;
90958
90959 /* If the DELETE has generated immediate foreign key constraint
90960 ** violations, halt the VDBE and return an error at this point, before
90961 ** any modifications to the schema are made. This is because statement
90962 ** transactions are not able to rollback schema changes. */
90963 sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
90964 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
90965 OE_Abort, "foreign key constraint failed", P4_STATIC
90966 );
 
 
 
 
 
 
 
90967
90968 if( iSkip ){
90969 sqlite3VdbeResolveLabel(v, iSkip);
90970 }
90971 }
@@ -93487,10 +93737,11 @@
93487 (char*)pKey, P4_KEYINFO_HANDOFF);
93488 VdbeComment((v, "%s", pSrcIdx->zName));
93489 pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
93490 sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
93491 (char*)pKey, P4_KEYINFO_HANDOFF);
 
93492 VdbeComment((v, "%s", pDestIdx->zName));
93493 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
93494 sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
93495 sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
93496 sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94962,193 +95213,382 @@
94962 #define PragTyp_MMAP_SIZE 23
94963 #define PragTyp_PAGE_SIZE 24
94964 #define PragTyp_SECURE_DELETE 25
94965 #define PragTyp_SHRINK_MEMORY 26
94966 #define PragTyp_SOFT_HEAP_LIMIT 27
94967 #define PragTyp_SYNCHRONOUS 28
94968 #define PragTyp_TABLE_INFO 29
94969 #define PragTyp_TEMP_STORE 30
94970 #define PragTyp_TEMP_STORE_DIRECTORY 31
94971 #define PragTyp_WAL_AUTOCHECKPOINT 32
94972 #define PragTyp_WAL_CHECKPOINT 33
94973 #define PragTyp_ACTIVATE_EXTENSIONS 34
94974 #define PragTyp_HEXKEY 35
94975 #define PragTyp_KEY 36
94976 #define PragTyp_REKEY 37
94977 #define PragTyp_LOCK_STATUS 38
94978 #define PragTyp_PARSER_TRACE 39
 
 
94979 static const struct sPragmaNames {
94980 const char *const zName; /* Name of pragma */
94981 u8 ePragTyp; /* PragTyp_XXX value */
 
94982 u32 iArg; /* Extra argument */
94983 } aPragmaNames[] = {
94984 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
94985 { "activate_extensions", PragTyp_ACTIVATE_EXTENSIONS, 0 },
 
 
 
94986 #endif
94987 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
94988 { "application_id", PragTyp_HEADER_VALUE, 0 },
 
 
 
94989 #endif
94990 #if !defined(SQLITE_OMIT_AUTOVACUUM)
94991 { "auto_vacuum", PragTyp_AUTO_VACUUM, 0 },
 
 
 
94992 #endif
94993 #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
94994 { "automatic_index", PragTyp_FLAG,
94995 SQLITE_AutoIndex },
 
 
94996 #endif
94997 { "busy_timeout", PragTyp_BUSY_TIMEOUT, 0 },
 
 
 
94998 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
94999 { "cache_size", PragTyp_CACHE_SIZE, 0 },
 
 
 
95000 #endif
95001 { "cache_spill", PragTyp_FLAG,
95002 SQLITE_CacheSpill },
95003 { "case_sensitive_like", PragTyp_CASE_SENSITIVE_LIKE, 0 },
95004 { "checkpoint_fullfsync", PragTyp_FLAG,
95005 SQLITE_CkptFullFSync },
 
 
 
 
 
 
 
95006 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95007 { "collation_list", PragTyp_COLLATION_LIST, 0 },
 
 
 
95008 #endif
95009 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95010 { "compile_options", PragTyp_COMPILE_OPTIONS, 0 },
 
 
 
95011 #endif
95012 { "count_changes", PragTyp_FLAG,
95013 SQLITE_CountRows },
 
 
95014 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95015 { "data_store_directory", PragTyp_DATA_STORE_DIRECTORY, 0 },
 
 
 
95016 #endif
95017 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95018 { "database_list", PragTyp_DATABASE_LIST, 0 },
 
 
 
95019 #endif
95020 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95021 { "default_cache_size", PragTyp_DEFAULT_CACHE_SIZE, 0 },
 
 
 
95022 #endif
95023 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95024 { "defer_foreign_keys", PragTyp_FLAG,
95025 SQLITE_DeferFKs },
 
 
95026 #endif
95027 { "empty_result_callbacks", PragTyp_FLAG,
95028 SQLITE_NullCallback },
 
 
95029 #if !defined(SQLITE_OMIT_UTF16)
95030 { "encoding", PragTyp_ENCODING, 0 },
 
 
 
95031 #endif
95032 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95033 { "foreign_key_check", PragTyp_FOREIGN_KEY_CHECK, 0 },
 
 
 
95034 #endif
95035 #if !defined(SQLITE_OMIT_FOREIGN_KEY)
95036 { "foreign_key_list", PragTyp_FOREIGN_KEY_LIST, 0 },
 
 
 
95037 #endif
95038 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95039 { "foreign_keys", PragTyp_FLAG,
95040 SQLITE_ForeignKeys },
 
 
95041 #endif
95042 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95043 { "freelist_count", PragTyp_HEADER_VALUE, 0 },
 
 
 
95044 #endif
95045 { "full_column_names", PragTyp_FLAG,
95046 SQLITE_FullColNames },
95047 { "fullfsync", PragTyp_FLAG,
95048 SQLITE_FullFSync },
 
 
 
 
95049 #if defined(SQLITE_HAS_CODEC)
95050 { "hexkey", PragTyp_HEXKEY, 0 },
 
 
 
 
 
 
 
95051 #endif
95052 #if !defined(SQLITE_OMIT_CHECK)
95053 { "ignore_check_constraints", PragTyp_FLAG,
95054 SQLITE_IgnoreChecks },
 
 
95055 #endif
95056 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95057 { "incremental_vacuum", PragTyp_INCREMENTAL_VACUUM, 0 },
 
 
 
95058 #endif
95059 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95060 { "index_info", PragTyp_INDEX_INFO, 0 },
95061 { "index_list", PragTyp_INDEX_LIST, 0 },
 
 
 
 
 
 
95062 #endif
95063 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95064 { "integrity_check", PragTyp_INTEGRITY_CHECK, 0 },
 
 
 
95065 #endif
95066 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95067 { "journal_mode", PragTyp_JOURNAL_MODE, 0 },
95068 { "journal_size_limit", PragTyp_JOURNAL_SIZE_LIMIT, 0 },
 
 
 
 
 
 
95069 #endif
95070 #if defined(SQLITE_HAS_CODEC)
95071 { "key", PragTyp_KEY, 0 },
 
 
 
95072 #endif
95073 { "legacy_file_format", PragTyp_FLAG,
95074 SQLITE_LegacyFileFmt },
 
 
95075 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95076 { "lock_proxy_file", PragTyp_LOCK_PROXY_FILE, 0 },
 
 
 
95077 #endif
95078 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95079 { "lock_status", PragTyp_LOCK_STATUS, 0 },
95080 #endif
95081 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95082 { "locking_mode", PragTyp_LOCKING_MODE, 0 },
95083 { "max_page_count", PragTyp_PAGE_COUNT, 0 },
95084 { "mmap_size", PragTyp_MMAP_SIZE, 0 },
95085 { "page_count", PragTyp_PAGE_COUNT, 0 },
95086 { "page_size", PragTyp_PAGE_SIZE, 0 },
95087 #endif
95088 #if defined(SQLITE_DEBUG)
95089 { "parser_trace", PragTyp_PARSER_TRACE, 0 },
95090 #endif
95091 { "query_only", PragTyp_FLAG,
95092 SQLITE_QueryOnly },
95093 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95094 { "quick_check", PragTyp_INTEGRITY_CHECK, 0 },
95095 #endif
95096 { "read_uncommitted", PragTyp_FLAG,
95097 SQLITE_ReadUncommitted },
95098 { "recursive_triggers", PragTyp_FLAG,
95099 SQLITE_RecTriggers },
95100 #if defined(SQLITE_HAS_CODEC)
95101 { "rekey", PragTyp_REKEY, 0 },
95102 #endif
95103 { "reverse_unordered_selects", PragTyp_FLAG,
95104 SQLITE_ReverseOrder },
95105 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95106 { "schema_version", PragTyp_HEADER_VALUE, 0 },
95107 #endif
95108 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95109 { "secure_delete", PragTyp_SECURE_DELETE, 0 },
95110 #endif
95111 { "short_column_names", PragTyp_FLAG,
95112 SQLITE_ShortColNames },
95113 { "shrink_memory", PragTyp_SHRINK_MEMORY, 0 },
95114 { "soft_heap_limit", PragTyp_SOFT_HEAP_LIMIT, 0 },
95115 #if defined(SQLITE_DEBUG)
95116 { "sql_trace", PragTyp_FLAG,
95117 SQLITE_SqlTrace },
95118 #endif
95119 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95120 { "synchronous", PragTyp_SYNCHRONOUS, 0 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95121 #endif
95122 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95123 { "table_info", PragTyp_TABLE_INFO, 0 },
 
 
 
95124 #endif
95125 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95126 { "temp_store", PragTyp_TEMP_STORE, 0 },
95127 { "temp_store_directory", PragTyp_TEMP_STORE_DIRECTORY, 0 },
 
 
 
 
 
 
95128 #endif
95129 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95130 { "user_version", PragTyp_HEADER_VALUE, 0 },
 
 
 
95131 #endif
95132 #if defined(SQLITE_DEBUG)
95133 { "vdbe_addoptrace", PragTyp_FLAG,
95134 SQLITE_VdbeAddopTrace },
95135 { "vdbe_debug", PragTyp_FLAG,
95136 SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95137 { "vdbe_listing", PragTyp_FLAG,
95138 SQLITE_VdbeListing },
95139 { "vdbe_trace", PragTyp_FLAG,
95140 SQLITE_VdbeTrace },
 
 
 
 
 
 
 
 
95141 #endif
95142 #if !defined(SQLITE_OMIT_WAL)
95143 { "wal_autocheckpoint", PragTyp_WAL_AUTOCHECKPOINT, 0 },
95144 { "wal_checkpoint", PragTyp_WAL_CHECKPOINT, 0 },
 
 
 
 
 
 
95145 #endif
95146 { "writable_schema", PragTyp_FLAG,
95147 SQLITE_WriteSchema|SQLITE_RecoveryMode },
 
 
95148 };
95149 /* Number of pragmas: 55 on by default, 66 total. */
95150 /* End of the automatically generated pragma table.
95151 ***************************************************************************/
95152
95153 /*
95154 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95916,15 @@
95476 }else{
95477 lwr = mid + 1;
95478 }
95479 }
95480 if( lwr>upr ) goto pragma_out;
 
 
 
 
 
95481
95482 /* Jump to the appropriate pragma handler */
95483 switch( aPragmaNames[mid].ePragTyp ){
95484
95485 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95955,10 @@
95510 { OP_Integer, 0, 1, 0}, /* 6 */
95511 { OP_Noop, 0, 0, 0},
95512 { OP_ResultRow, 1, 1, 0},
95513 };
95514 int addr;
95515 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95516 sqlite3VdbeUsesBtree(v, iDb);
95517 if( !zRight ){
95518 sqlite3VdbeSetNumCols(v, 1);
95519 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
95520 pParse->nMem += 2;
@@ -95606,11 +96050,10 @@
95606 **
95607 ** Return the number of pages in the specified database.
95608 */
95609 case PragTyp_PAGE_COUNT: {
95610 int iReg;
95611 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95612 sqlite3CodeVerifySchema(pParse, iDb);
95613 iReg = ++pParse->nMem;
95614 if( sqlite3Tolower(zLeft[0])=='p' ){
95615 sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
95616 }else{
@@ -95679,18 +96122,10 @@
95679 */
95680 case PragTyp_JOURNAL_MODE: {
95681 int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
95682 int ii; /* Loop counter */
95683
95684 /* Force the schema to be loaded on all databases. This causes all
95685 ** database files to be opened and the journal_modes set. This is
95686 ** necessary because subsequent processing must know if the databases
95687 ** are in WAL mode. */
95688 if( sqlite3ReadSchema(pParse) ){
95689 goto pragma_out;
95690 }
95691
95692 sqlite3VdbeSetNumCols(v, 1);
95693 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
95694
95695 if( zRight==0 ){
95696 /* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96187,44 @@
95752 */
95753 #ifndef SQLITE_OMIT_AUTOVACUUM
95754 case PragTyp_AUTO_VACUUM: {
95755 Btree *pBt = pDb->pBt;
95756 assert( pBt!=0 );
95757 if( sqlite3ReadSchema(pParse) ){
95758 goto pragma_out;
95759 }
95760 if( !zRight ){
95761 int auto_vacuum;
95762 if( ALWAYS(pBt) ){
95763 auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
95764 }else{
95765 auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
95766 }
95767 returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
95768 }else{
95769 int eAuto = getAutoVacuum(zRight);
95770 assert( eAuto>=0 && eAuto<=2 );
95771 db->nextAutovac = (u8)eAuto;
95772 if( ALWAYS(eAuto>=0) ){
95773 /* Call SetAutoVacuum() to set initialize the internal auto and
95774 ** incr-vacuum flags. This is required in case this connection
95775 ** creates the database file. It is important that it is created
95776 ** as an auto-vacuum capable db.
95777 */
95778 rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
95779 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
95780 /* When setting the auto_vacuum mode to either "full" or
95781 ** "incremental", write the value of meta[6] in the database
95782 ** file. Before writing to meta[6], check that meta[3] indicates
95783 ** that this really is an auto-vacuum capable database.
95784 */
95785 static const VdbeOpList setMeta6[] = {
95786 { OP_Transaction, 0, 1, 0}, /* 0 */
95787 { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
95788 { OP_If, 1, 0, 0}, /* 2 */
95789 { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
95790 { OP_Integer, 0, 1, 0}, /* 4 */
95791 { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
95792 };
95793 int iAddr;
95794 iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
95795 sqlite3VdbeChangeP1(v, iAddr, iDb);
95796 sqlite3VdbeChangeP1(v, iAddr+1, iDb);
95797 sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
95798 sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
95799 sqlite3VdbeChangeP1(v, iAddr+5, iDb);
95800 sqlite3VdbeUsesBtree(v, iDb);
95801 }
95802 }
95803 }
95804 break;
95805 }
95806 #endif
@@ -95811,13 +96235,10 @@
95811 ** Do N steps of incremental vacuuming on a database.
95812 */
95813 #ifndef SQLITE_OMIT_AUTOVACUUM
95814 case PragTyp_INCREMENTAL_VACUUM: {
95815 int iLimit, addr;
95816 if( sqlite3ReadSchema(pParse) ){
95817 goto pragma_out;
95818 }
95819 if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
95820 iLimit = 0x7fffffff;
95821 }
95822 sqlite3BeginWriteOperation(pParse, 0, iDb);
95823 sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96262,10 @@
95841 ** number of pages in the cache. If N is negative, then the
95842 ** number of pages is adjusted so that the cache uses -N kibibytes
95843 ** of memory.
95844 */
95845 case PragTyp_CACHE_SIZE: {
95846 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95847 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
95848 if( !zRight ){
95849 returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
95850 }else{
95851 int size = sqlite3Atoi(zRight);
@@ -96062,11 +96482,10 @@
96062 ** the local value does not make changes to the disk file and the
96063 ** default value will be restored the next time the database is
96064 ** opened.
96065 */
96066 case PragTyp_SYNCHRONOUS: {
96067 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96068 if( !zRight ){
96069 returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
96070 }else{
96071 if( !db->autoCommit ){
96072 sqlite3ErrorMsg(pParse,
@@ -96124,11 +96543,10 @@
96124 ** notnull: True if 'NOT NULL' is part of column declaration
96125 ** dflt_value: The default value for the column, if any.
96126 */
96127 case PragTyp_TABLE_INFO: if( zRight ){
96128 Table *pTab;
96129 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96130 pTab = sqlite3FindTable(db, zRight, zDb);
96131 if( pTab ){
96132 int i, k;
96133 int nHidden = 0;
96134 Column *pCol;
@@ -96170,15 +96588,44 @@
96170 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
96171 }
96172 }
96173 }
96174 break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96175
96176 case PragTyp_INDEX_INFO: if( zRight ){
96177 Index *pIdx;
96178 Table *pTab;
96179 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96180 pIdx = sqlite3FindIndex(db, zRight, zDb);
96181 if( pIdx ){
96182 int i;
96183 pTab = pIdx->pTable;
96184 sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96647,32 @@
96200 break;
96201
96202 case PragTyp_INDEX_LIST: if( zRight ){
96203 Index *pIdx;
96204 Table *pTab;
96205 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96206 pTab = sqlite3FindTable(db, zRight, zDb);
96207 if( pTab ){
96208 v = sqlite3GetVdbe(pParse);
96209 pIdx = pTab->pIndex;
96210 if( pIdx ){
96211 int i = 0;
96212 sqlite3VdbeSetNumCols(v, 3);
96213 pParse->nMem = 3;
96214 sqlite3CodeVerifySchema(pParse, iDb);
96215 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96216 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96217 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96218 while(pIdx){
96219 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96220 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96221 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96222 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
96223 ++i;
96224 pIdx = pIdx->pNext;
96225 }
96226 }
96227 }
96228 }
96229 break;
96230
96231 case PragTyp_DATABASE_LIST: {
96232 int i;
96233 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96234 sqlite3VdbeSetNumCols(v, 3);
96235 pParse->nMem = 3;
96236 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96237 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96238 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96707,10 @@
96267
96268 #ifndef SQLITE_OMIT_FOREIGN_KEY
96269 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
96270 FKey *pFK;
96271 Table *pTab;
96272 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96273 pTab = sqlite3FindTable(db, zRight, zDb);
96274 if( pTab ){
96275 v = sqlite3GetVdbe(pParse);
96276 pFK = pTab->pFKey;
96277 if( pFK ){
@@ -96329,11 +96768,10 @@
96329 int regRow; /* Registers to hold a row from pTab */
96330 int addrTop; /* Top of a loop checking foreign keys */
96331 int addrOk; /* Jump here if the key is OK */
96332 int *aiCols; /* child to parent column mapping */
96333
96334 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96335 regResult = pParse->nMem+1;
96336 pParse->nMem += 4;
96337 regKey = ++pParse->nMem;
96338 regRow = ++pParse->nMem;
96339 v = sqlite3GetVdbe(pParse);
@@ -96357,12 +96795,12 @@
96357 if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
96358 sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
96359 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
96360 P4_TRANSIENT);
96361 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96362 pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
96363 if( pParent==0 ) break;
96364 pIdx = 0;
96365 sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
96366 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
96367 if( x==0 ){
96368 if( pIdx==0 ){
@@ -96375,22 +96813,24 @@
96375 }else{
96376 k = 0;
96377 break;
96378 }
96379 }
 
96380 if( pFK ) break;
96381 if( pParse->nTab<i ) pParse->nTab = i;
96382 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
96383 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96384 pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
96385 assert( pParent!=0 );
96386 pIdx = 0;
96387 aiCols = 0;
96388 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
96389 assert( x==0 );
 
 
96390 addrOk = sqlite3VdbeMakeLabel(v);
96391 if( pIdx==0 ){
96392 int iKey = pFK->aCol[0].iFrom;
96393 assert( iKey>=0 && iKey<pTab->nCol );
96394 if( iKey!=pTab->iPKey ){
96395 sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
96396 sqlite3ColumnDefault(v, pTab, iKey, regRow);
@@ -96404,17 +96844,19 @@
96404 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
96405 sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
96406 }else{
96407 for(j=0; j<pFK->nCol; j++){
96408 sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
96409 aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
96410 sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
96411 }
96412 sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
96413 sqlite3VdbeChangeP4(v, -1,
96414 sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
96415 sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
 
 
96416 }
96417 sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
96418 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
96419 pFK->zTo, P4_TRANSIENT);
96420 sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
@@ -96490,11 +96932,10 @@
96490 assert( iDb>=0 );
96491 assert( iDb==0 || pId2->z );
96492 if( pId2->z==0 ) iDb = -1;
96493
96494 /* Initialize the VDBE program */
96495 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96496 pParse->nMem = 6;
96497 sqlite3VdbeSetNumCols(v, 1);
96498 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
96499
96500 /* Set the maximum error count */
@@ -96814,11 +97255,10 @@
96814 eMode = SQLITE_CHECKPOINT_FULL;
96815 }else if( sqlite3StrICmp(zRight, "restart")==0 ){
96816 eMode = SQLITE_CHECKPOINT_RESTART;
96817 }
96818 }
96819 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
96820 sqlite3VdbeSetNumCols(v, 3);
96821 pParse->nMem = 3;
96822 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
96823 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
96824 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97374,16 @@
96934 if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
96935 break;
96936 }
96937 case PragTyp_HEXKEY: {
96938 if( zRight ){
96939 int i, h1, h2;
 
96940 char zKey[40];
96941 for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
96942 h1 += 9*(1&(h1>>6));
96943 h2 += 9*(1&(h2>>6));
96944 zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
96945 }
96946 if( (zLeft[3] & 0xf)==0xb ){
96947 sqlite3_key_v2(db, zDb, zKey, i/2);
96948 }else{
96949 sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99353,13 @@
98913 }
98914
98915 /*
98916 ** Return a pointer to a string containing the 'declaration type' of the
98917 ** expression pExpr. The string may be treated as static by the caller.
 
 
 
98918 **
98919 ** The declaration type is the exact datatype definition extracted from the
98920 ** original CREATE TABLE statement if the expression is a column. The
98921 ** declaration type for a ROWID field is INTEGER. Exactly when an expression
98922 ** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99370,40 @@
98927 ** SELECT (SELECT col FROM tbl;
98928 ** SELECT (SELECT col FROM tbl);
98929 ** SELECT abc FROM (SELECT col AS abc FROM tbl);
98930 **
98931 ** The declaration type for any expression other than a column is NULL.
 
 
 
98932 */
98933 static const char *columnType(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98934 NameContext *pNC,
98935 Expr *pExpr,
98936 const char **pzOriginDb,
98937 const char **pzOriginTab,
98938 const char **pzOriginCol
98939 ){
 
98940 char const *zType = 0;
98941 char const *zOriginDb = 0;
98942 char const *zOriginTab = 0;
98943 char const *zOriginCol = 0;
98944 int j;
 
 
98945 if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
98946
98947 switch( pExpr->op ){
98948 case TK_AGG_COLUMN:
98949 case TK_COLUMN: {
98950 /* The expression is a column. Locate the table the column is being
98951 ** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99460,39 @@
99002 NameContext sNC;
99003 Expr *p = pS->pEList->a[iCol].pExpr;
99004 sNC.pSrcList = pS->pSrc;
99005 sNC.pNext = pNC;
99006 sNC.pParse = pNC->pParse;
99007 zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99008 }
99009 }else if( ALWAYS(pTab->pSchema) ){
99010 /* A real table */
99011 assert( !pS );
99012 if( iCol<0 ) iCol = pTab->iPKey;
99013 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
 
99014 if( iCol<0 ){
99015 zType = "INTEGER";
99016 zOriginCol = "rowid";
99017 }else{
99018 zType = pTab->aCol[iCol].zType;
99019 zOriginCol = pTab->aCol[iCol].zName;
 
99020 }
99021 zOriginTab = pTab->zName;
99022 if( pNC->pParse ){
99023 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99024 zOriginDb = pNC->pParse->db->aDb[iDb].zName;
99025 }
 
 
 
 
 
 
 
 
99026 }
99027 break;
99028 }
99029 #ifndef SQLITE_OMIT_SUBQUERY
99030 case TK_SELECT: {
@@ -99037,22 +99505,25 @@
99037 Expr *p = pS->pEList->a[0].pExpr;
99038 assert( ExprHasProperty(pExpr, EP_xIsSelect) );
99039 sNC.pSrcList = pS->pSrc;
99040 sNC.pNext = pNC;
99041 sNC.pParse = pNC->pParse;
99042 zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
99043 break;
99044 }
99045 #endif
99046 }
99047
99048 if( pzOriginDb ){
99049 assert( pzOriginTab && pzOriginCol );
99050 *pzOriginDb = zOriginDb;
99051 *pzOriginTab = zOriginTab;
99052 *pzOriginCol = zOriginCol;
 
99053 }
 
 
99054 return zType;
99055 }
99056
99057 /*
99058 ** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99545,25 @@
99074 const char *zType;
99075 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99076 const char *zOrigDb = 0;
99077 const char *zOrigTab = 0;
99078 const char *zOrigCol = 0;
99079 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
99080
99081 /* The vdbe must make its own copy of the column-type and other
99082 ** column specific strings, in case the schema is reset before this
99083 ** virtual machine is deleted.
99084 */
99085 sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
99086 sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
99087 sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
99088 #else
99089 zType = columnType(&sNC, p, 0, 0, 0);
99090 #endif
99091 sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
99092 }
99093 #endif /* SQLITE_OMIT_DECLTYPE */
99094 }
99095
99096 /*
99097 ** Generate code that will tell the VDBE the names of columns
99098 ** in the result set. This information is used to provide the
@@ -99277,39 +99748,41 @@
99277 ** This routine requires that all identifiers in the SELECT
99278 ** statement be resolved.
99279 */
99280 static void selectAddColumnTypeAndCollation(
99281 Parse *pParse, /* Parsing contexts */
99282 int nCol, /* Number of columns */
99283 Column *aCol, /* List of columns */
99284 Select *pSelect /* SELECT used to determine types and collations */
99285 ){
99286 sqlite3 *db = pParse->db;
99287 NameContext sNC;
99288 Column *pCol;
99289 CollSeq *pColl;
99290 int i;
99291 Expr *p;
99292 struct ExprList_item *a;
 
99293
99294 assert( pSelect!=0 );
99295 assert( (pSelect->selFlags & SF_Resolved)!=0 );
99296 assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
99297 if( db->mallocFailed ) return;
99298 memset(&sNC, 0, sizeof(sNC));
99299 sNC.pSrcList = pSelect->pSrc;
99300 a = pSelect->pEList->a;
99301 for(i=0, pCol=aCol; i<nCol; i++, pCol++){
99302 p = a[i].pExpr;
99303 pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
 
99304 pCol->affinity = sqlite3ExprAffinity(p);
99305 if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
99306 pColl = sqlite3ExprCollSeq(pParse, p);
99307 if( pColl ){
99308 pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
99309 }
99310 }
 
99311 }
99312
99313 /*
99314 ** Given a SELECT statement, generate a Table structure that describes
99315 ** the result set of that SELECT.
@@ -99333,13 +99806,13 @@
99333 /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
99334 ** is disabled */
99335 assert( db->lookaside.bEnabled==0 );
99336 pTab->nRef = 1;
99337 pTab->zName = 0;
99338 pTab->nRowEst = 1000000;
99339 selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99340 selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
99341 pTab->iPKey = -1;
99342 if( db->mallocFailed ){
99343 sqlite3DeleteTable(db, pTab);
99344 return 0;
99345 }
@@ -101247,15 +101720,15 @@
101247 assert( pFrom->pTab==0 );
101248 sqlite3WalkSelect(pWalker, pSel);
101249 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101250 if( pTab==0 ) return WRC_Abort;
101251 pTab->nRef = 1;
101252 pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
101253 while( pSel->pPrior ){ pSel = pSel->pPrior; }
101254 selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101255 pTab->iPKey = -1;
101256 pTab->nRowEst = 1000000;
101257 pTab->tabFlags |= TF_Ephemeral;
101258 #endif
101259 }else{
101260 /* An ordinary table or view name in the FROM clause */
101261 assert( pFrom->pTab==0 );
@@ -101535,11 +102008,11 @@
101535 if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
101536 /* A sub-query in the FROM clause of a SELECT */
101537 Select *pSel = pFrom->pSelect;
101538 assert( pSel );
101539 while( pSel->pPrior ) pSel = pSel->pPrior;
101540 selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
101541 }
101542 }
101543 }
101544 return WRC_Continue;
101545 }
@@ -102450,29 +102923,29 @@
102450 int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102451
102452 sqlite3CodeVerifySchema(pParse, iDb);
102453 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102454
102455 /* Search for the index that has the least amount of columns. If
102456 ** there is such an index, and it has less columns than the table
102457 ** does, then we can assume that it consumes less space on disk and
102458 ** will therefore be cheaper to scan to determine the query result.
102459 ** In this case set iRoot to the root page number of the index b-tree
102460 ** and pKeyInfo to the KeyInfo structure required to navigate the
102461 ** index.
102462 **
102463 ** (2011-04-15) Do not do a full scan of an unordered index.
 
 
102464 **
102465 ** In practice the KeyInfo structure will not be used. It is only
102466 ** passed to keep OP_OpenRead happy.
102467 */
102468 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102469 if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
 
 
 
 
102470 pBest = pIdx;
102471 }
102472 }
102473 if( pBest && pBest->nColumn<pTab->nCol ){
102474 iRoot = pBest->tnum;
102475 pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102476 }
102477
102478 /* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103519,12 @@
103046 }
103047
103048 /* Ensure the table name matches database name and that the table exists */
103049 if( db->mallocFailed ) goto trigger_cleanup;
103050 assert( pTableName->nSrc==1 );
103051 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
103052 sqlite3FixSrcList(&sFix, pTableName) ){
103053 goto trigger_cleanup;
103054 }
103055 pTab = sqlite3SrcListLookup(pParse, pTableName);
103056 if( !pTab ){
103057 /* The table does not exist. */
@@ -103189,12 +103662,14 @@
103189 pStepList->pTrig = pTrig;
103190 pStepList = pStepList->pNext;
103191 }
103192 nameToken.z = pTrig->zName;
103193 nameToken.n = sqlite3Strlen30(nameToken.z);
103194 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
103195 && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
 
 
103196 goto triggerfinish_cleanup;
103197 }
103198
103199 /* if we are not initializing,
103200 ** build the sqlite_master entry
@@ -104781,18 +105256,38 @@
104781
104782 return vacuumFinalize(db, pStmt, pzErrMsg);
104783 }
104784
104785 /*
104786 ** The non-standard VACUUM command is used to clean up the database,
104787 ** collapse free space, etc. It is modelled after the VACUUM command
104788 ** in PostgreSQL.
104789 **
104790 ** In version 1.0.x of SQLite, the VACUUM command would call
104791 ** gdbm_reorganize() on all the database tables. But beginning
104792 ** with 2.0.0, SQLite no longer uses GDBM so this command has
104793 ** become a no-op.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104794 */
104795 SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
104796 Vdbe *v = sqlite3GetVdbe(pParse);
104797 if( v ){
104798 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106701,10 @@
106206 typedef struct WhereLoopBuilder WhereLoopBuilder;
106207 typedef struct WhereScan WhereScan;
106208 typedef struct WhereOrCost WhereOrCost;
106209 typedef struct WhereOrSet WhereOrSet;
106210
106211 /*
106212 ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
106213 ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
106214 ** (Virtual tables can return a larger cost, but let's assume they do not.)
106215 ** So all costs can be stored in a 16-bit integer without risk
106216 ** of overflow.
106217 **
106218 ** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
106219 ** Instead, a close estimate is used. Any value of X=1 is stored as 0.
106220 ** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
106221 ** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
106222 **
106223 ** The tool/wherecosttest.c source file implements a command-line program
106224 ** that will convert WhereCosts to integers, convert integers to WhereCosts
106225 ** and do addition and multiplication on WhereCost values. The wherecosttest
106226 ** command-line program is a useful utility to have around when working with
106227 ** this module.
106228 */
106229 typedef short int WhereCost;
106230
106231 /*
106232 ** This object contains information needed to implement a single nested
106233 ** loop in WHERE clause.
106234 **
106235 ** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106765,13 @@
106290 #ifdef SQLITE_DEBUG
106291 char cId; /* Symbolic ID of this loop for debugging use */
106292 #endif
106293 u8 iTab; /* Position in FROM clause of table for this loop */
106294 u8 iSortIdx; /* Sorting index number. 0==None */
106295 WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
106296 WhereCost rRun; /* Cost of running each loop */
106297 WhereCost nOut; /* Estimated number of output rows */
106298 union {
106299 struct { /* Information for internal btree tables */
106300 int nEq; /* Number of equality constraints */
106301 Index *pIndex; /* Index used, or NULL */
106302 } btree;
@@ -106322,12 +106797,12 @@
106322 ** subquery on one operand of an OR operator in the WHERE clause.
106323 ** See WhereOrSet for additional information
106324 */
106325 struct WhereOrCost {
106326 Bitmask prereq; /* Prerequisites */
106327 WhereCost rRun; /* Cost of running this subquery */
106328 WhereCost nOut; /* Number of outputs for this subquery */
106329 };
106330
106331 /* The WhereOrSet object holds a set of possible WhereOrCosts that
106332 ** correspond to the subquery(s) of OR-clause processing. Only the
106333 ** best N_OR_COST elements are retained.
@@ -106361,12 +106836,12 @@
106361 ** at the end is the choosen query plan.
106362 */
106363 struct WherePath {
106364 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106365 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106366 WhereCost nRow; /* Estimated number of rows generated by this path */
106367 WhereCost rCost; /* Total cost of this path */
106368 u8 isOrdered; /* True if this path satisfies ORDER BY */
106369 u8 isOrderedValid; /* True if the isOrdered field is valid */
106370 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106371 };
106372
@@ -106428,11 +106903,11 @@
106428 union {
106429 int leftColumn; /* Column number of X in "X <op> <expr>" */
106430 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106431 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106432 } u;
106433 WhereCost truthProb; /* Probability of truth for this expression */
106434 u16 eOperator; /* A WO_xx value describing <op> */
106435 u8 wtFlags; /* TERM_xxx bit flags. See below */
106436 u8 nChild; /* Number of children that must disable us */
106437 WhereClause *pWC; /* The clause this term is part of */
106438 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +107051,11 @@
106576 SrcList *pTabList; /* List of tables in the join */
106577 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
106578 ExprList *pResultSet; /* Result set. DISTINCT operates on these */
106579 WhereLoop *pLoops; /* List of all WhereLoop objects */
106580 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
106581 WhereCost nRowOut; /* Estimated number of output rows */
106582 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
106583 u8 bOBSat; /* ORDER BY satisfied by indices */
106584 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
106585 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
106586 u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107111,15 @@
106636 #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
106637 #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
106638 #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
106639 #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
106640
106641
106642 /* Convert a WhereCost value (10 times log2(X)) into its integer value X.
106643 ** A rough approximation is used. The value returned is not exact.
106644 */
106645 static u64 whereCostToInt(WhereCost x){
106646 u64 n;
106647 if( x<10 ) return 1;
106648 n = x%10;
106649 x /= 10;
106650 if( n>=5 ) n -= 2;
106651 else if( n>=1 ) n -= 1;
106652 if( x>=3 ) return (n+8)<<(x-3);
106653 return (n+8)>>(3-x);
106654 }
106655
106656 /*
106657 ** Return the estimated number of output rows from a WHERE clause
106658 */
106659 SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
106660 return whereCostToInt(pWInfo->nRowOut);
106661 }
106662
106663 /*
106664 ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
106665 ** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107177,12 @@
106717 ** so that pSet keeps the N_OR_COST best entries seen so far.
106718 */
106719 static int whereOrInsert(
106720 WhereOrSet *pSet, /* The WhereOrSet to be updated */
106721 Bitmask prereq, /* Prerequisites of the new entry */
106722 WhereCost rRun, /* Run-cost of the new entry */
106723 WhereCost nOut /* Number of outputs for the new entry */
106724 ){
106725 u16 i;
106726 WhereOrCost *p;
106727 for(i=pSet->n, p=pSet->a; i>0; i--, p++){
106728 if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107263,10 @@
106803 if( pWC->a!=pWC->aStatic ){
106804 sqlite3DbFree(db, pWC->a);
106805 }
106806 }
106807
106808 /* Forward declaration */
106809 static WhereCost whereCost(tRowcnt x);
106810
106811 /*
106812 ** Add a single new WhereTerm entry to the WhereClause object pWC.
106813 ** The new WhereTerm object is constructed from Expr p and with wtFlags.
106814 ** The index in pWC->a[] of the new WhereTerm is returned on success.
106815 ** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107305,11 @@
106848 }
106849 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
106850 }
106851 pTerm = &pWC->a[idx = pWC->nTerm++];
106852 if( p && ExprHasProperty(p, EP_Unlikely) ){
106853 pTerm->truthProb = whereCost(p->iTable) - 99;
106854 }else{
106855 pTerm->truthProb = -1;
106856 }
106857 pTerm->pExpr = sqlite3ExprSkipCollate(p);
106858 pTerm->wtFlags = wtFlags;
@@ -108112,79 +108569,16 @@
108112 }
108113
108114 return 0;
108115 }
108116
108117 /*
108118 ** Find (an approximate) sum of two WhereCosts. This computation is
108119 ** not a simple "+" operator because WhereCost is stored as a logarithmic
108120 ** value.
108121 **
108122 */
108123 static WhereCost whereCostAdd(WhereCost a, WhereCost b){
108124 static const unsigned char x[] = {
108125 10, 10, /* 0,1 */
108126 9, 9, /* 2,3 */
108127 8, 8, /* 4,5 */
108128 7, 7, 7, /* 6,7,8 */
108129 6, 6, 6, /* 9,10,11 */
108130 5, 5, 5, /* 12-14 */
108131 4, 4, 4, 4, /* 15-18 */
108132 3, 3, 3, 3, 3, 3, /* 19-24 */
108133 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
108134 };
108135 if( a>=b ){
108136 if( a>b+49 ) return a;
108137 if( a>b+31 ) return a+1;
108138 return a+x[a-b];
108139 }else{
108140 if( b>a+49 ) return b;
108141 if( b>a+31 ) return b+1;
108142 return b+x[b-a];
108143 }
108144 }
108145
108146 /*
108147 ** Convert an integer into a WhereCost. In other words, compute a
108148 ** good approximatation for 10*log2(x).
108149 */
108150 static WhereCost whereCost(tRowcnt x){
108151 static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
108152 WhereCost y = 40;
108153 if( x<8 ){
108154 if( x<2 ) return 0;
108155 while( x<8 ){ y -= 10; x <<= 1; }
108156 }else{
108157 while( x>255 ){ y += 40; x >>= 4; }
108158 while( x>15 ){ y += 10; x >>= 1; }
108159 }
108160 return a[x&7] + y - 10;
108161 }
108162
108163 #ifndef SQLITE_OMIT_VIRTUALTABLE
108164 /*
108165 ** Convert a double (as received from xBestIndex of a virtual table)
108166 ** into a WhereCost. In other words, compute an approximation for
108167 ** 10*log2(x).
108168 */
108169 static WhereCost whereCostFromDouble(double x){
108170 u64 a;
108171 WhereCost e;
108172 assert( sizeof(x)==8 && sizeof(a)==8 );
108173 if( x<=1 ) return 0;
108174 if( x<=2000000000 ) return whereCost((tRowcnt)x);
108175 memcpy(&a, &x, 8);
108176 e = (a>>52) - 1022;
108177 return e*10;
108178 }
108179 #endif /* SQLITE_OMIT_VIRTUALTABLE */
108180
108181 /*
108182 ** Estimate the logarithm of the input value to base 2.
108183 */
108184 static WhereCost estLog(WhereCost N){
108185 WhereCost x = whereCost(N);
108186 return x>33 ? x - 33 : 0;
108187 }
108188
108189 /*
108190 ** Two routines for printing the content of an sqlite3_index_info
@@ -108596,10 +108990,13 @@
108596 int iMin = 0; /* Smallest sample not yet tested */
108597 int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
108598 int iTest; /* Next sample to test */
108599 int res; /* Result of comparison operation */
108600
 
 
 
108601 assert( pRec!=0 || pParse->db->mallocFailed );
108602 if( pRec==0 ) return;
108603 iCol = pRec->nField - 1;
108604 assert( pIdx->nSample>0 );
108605 assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
@@ -108693,11 +109090,11 @@
108693 **
108694 ** ... FROM t1 WHERE a > ? AND a < ? ...
108695 **
108696 ** then nEq is set to 0.
108697 **
108698 ** When this function is called, *pnOut is set to the whereCost() of the
108699 ** number of rows that the index scan is expected to visit without
108700 ** considering the range constraints. If nEq is 0, this is the number of
108701 ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
108702 ** to account for the range contraints pLower and pUpper.
108703 **
@@ -108709,19 +109106,19 @@
108709 static int whereRangeScanEst(
108710 Parse *pParse, /* Parsing & code generating context */
108711 WhereLoopBuilder *pBuilder,
108712 WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
108713 WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
108714 WhereCost *pnOut /* IN/OUT: Number of rows visited */
108715 ){
108716 int rc = SQLITE_OK;
108717 int nOut = (int)*pnOut;
108718 WhereCost nNew;
108719
108720 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108721 Index *p = pBuilder->pNew->u.btree.pIndex;
108722 int nEq = pBuilder->pNew->u.btree.nEq;
108723
108724 if( p->nSample>0
108725 && nEq==pBuilder->nRecValid
108726 && nEq<p->nSampleCol
108727 && OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109195,18 @@
108798 }
108799
108800 pBuilder->pRec = pRec;
108801 if( rc==SQLITE_OK ){
108802 if( iUpper>iLower ){
108803 nNew = whereCost(iUpper - iLower);
108804 }else{
108805 nNew = 10; assert( 10==whereCost(2) );
108806 }
108807 if( nNew<nOut ){
108808 nOut = nNew;
108809 }
108810 *pnOut = (WhereCost)nOut;
108811 WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
108812 (u32)iLower, (u32)iUpper, nOut));
108813 return SQLITE_OK;
108814 }
108815 }
@@ -108820,20 +109217,20 @@
108820 assert( pLower || pUpper );
108821 /* TUNING: Each inequality constraint reduces the search space 4-fold.
108822 ** A BETWEEN operator, therefore, reduces the search space 16-fold */
108823 nNew = nOut;
108824 if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
108825 nNew -= 20; assert( 20==whereCost(4) );
108826 nOut--;
108827 }
108828 if( pUpper ){
108829 nNew -= 20; assert( 20==whereCost(4) );
108830 nOut--;
108831 }
108832 if( nNew<10 ) nNew = 10;
108833 if( nNew<nOut ) nOut = nNew;
108834 *pnOut = (WhereCost)nOut;
108835 return rc;
108836 }
108837
108838 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
108839 /*
@@ -110441,11 +110838,11 @@
110441 **
110442 ** In the current implementation, the first extra WHERE clause term reduces
110443 ** the number of output rows by a factor of 10 and each additional term
110444 ** reduces the number of output rows by sqrt(2).
110445 */
110446 static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){
110447 WhereTerm *pTerm, *pX;
110448 Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
110449 int i, j;
110450
110451 if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
@@ -110473,11 +110870,11 @@
110473 */
110474 static int whereLoopAddBtreeIndex(
110475 WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110476 struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110477 Index *pProbe, /* An index on pSrc */
110478 WhereCost nInMul /* log(Number of iterations due to IN) */
110479 ){
110480 WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110481 Parse *pParse = pWInfo->pParse; /* Parsing context */
110482 sqlite3 *db = pParse->db; /* Database connection malloc context */
110483 WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110883,15 @@
110486 WhereScan scan; /* Iterator for WHERE terms */
110487 Bitmask saved_prereq; /* Original value of pNew->prereq */
110488 u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110489 int saved_nEq; /* Original value of pNew->u.btree.nEq */
110490 u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110491 WhereCost saved_nOut; /* Original value of pNew->nOut */
110492 int iCol; /* Index of the column in the table */
110493 int rc = SQLITE_OK; /* Return code */
110494 WhereCost nRowEst; /* Estimated index selectivity */
110495 WhereCost rLogSize; /* Logarithm of table size */
110496 WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110497
110498 pNew = pBuilder->pNew;
110499 if( db->mallocFailed ) return SQLITE_NOMEM;
110500
@@ -110510,11 +110907,11 @@
110510 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110511
110512 assert( pNew->u.btree.nEq<=pProbe->nColumn );
110513 if( pNew->u.btree.nEq < pProbe->nColumn ){
110514 iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110515 nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110516 if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110517 }else{
110518 iCol = -1;
110519 nRowEst = 0;
110520 }
@@ -110524,11 +110921,11 @@
110524 saved_nLTerm = pNew->nLTerm;
110525 saved_wsFlags = pNew->wsFlags;
110526 saved_prereq = pNew->prereq;
110527 saved_nOut = pNew->nOut;
110528 pNew->rSetup = 0;
110529 rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
110530 for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110531 int nIn = 0;
110532 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110533 int nRecValid = pBuilder->nRecValid;
110534 #endif
@@ -110551,14 +110948,14 @@
110551 if( pTerm->eOperator & WO_IN ){
110552 Expr *pExpr = pTerm->pExpr;
110553 pNew->wsFlags |= WHERE_COLUMN_IN;
110554 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110555 /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110556 nIn = 46; assert( 46==whereCost(25) );
110557 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110558 /* "x IN (value, value, ...)" */
110559 nIn = whereCost(pExpr->x.pList->nExpr);
110560 }
110561 pNew->rRun += nIn;
110562 pNew->u.btree.nEq++;
110563 pNew->nOut = nRowEst + nInMul + nIn;
110564 }else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110973,11 @@
110576 pNew->nOut = nRowEst + nInMul;
110577 }else if( pTerm->eOperator & (WO_ISNULL) ){
110578 pNew->wsFlags |= WHERE_COLUMN_NULL;
110579 pNew->u.btree.nEq++;
110580 /* TUNING: IS NULL selects 2 rows */
110581 nIn = 10; assert( 10==whereCost(2) );
110582 pNew->nOut = nRowEst + nInMul + nIn;
110583 }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110584 testcase( pTerm->eOperator & WO_GT );
110585 testcase( pTerm->eOperator & WO_GE );
110586 pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110993,11 @@
110596 pNew->aLTerm[pNew->nLTerm-2] : 0;
110597 }
110598 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110599 /* Adjust nOut and rRun for STAT3 range values */
110600 assert( pNew->nOut==saved_nOut );
110601 whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
110602 }
110603 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110604 if( nInMul==0
110605 && pProbe->nSample
110606 && pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,23 +111013,23 @@
110616 && !ExprHasProperty(pExpr, EP_xIsSelect) ){
110617 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
110618 }
110619 assert( nOut==0 || rc==SQLITE_OK );
110620 if( nOut ){
110621 nOut = whereCost(nOut);
110622 pNew->nOut = MIN(nOut, saved_nOut);
110623 }
110624 }
110625 #endif
110626 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
110627 /* Each row involves a step of the index, then a binary search of
110628 ** the main table */
110629 pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
110630 }
110631 /* Step cost for each output row */
110632 pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
110633 whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
110634 rc = whereLoopInsert(pBuilder, pNew);
110635 if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
110636 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
110637 ){
110638 whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
@@ -110727,18 +111124,20 @@
110727 struct SrcList_item *pSrc; /* The FROM clause btree term to add */
110728 WhereLoop *pNew; /* Template WhereLoop object */
110729 int rc = SQLITE_OK; /* Return code */
110730 int iSortIdx = 1; /* Index number */
110731 int b; /* A boolean value */
110732 WhereCost rSize; /* number of rows in the table */
110733 WhereCost rLogSize; /* Logarithm of the number of rows in the table */
110734 WhereClause *pWC; /* The parsed WHERE clause */
 
110735
110736 pNew = pBuilder->pNew;
110737 pWInfo = pBuilder->pWInfo;
110738 pTabList = pWInfo->pTabList;
110739 pSrc = pTabList->a + pNew->iTab;
 
110740 pWC = pBuilder->pWC;
110741 assert( !IsVirtual(pSrc->pTab) );
110742
110743 if( pSrc->pIndex ){
110744 /* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111151,22 @@
110752 memset(&sPk, 0, sizeof(Index));
110753 sPk.nColumn = 1;
110754 sPk.aiColumn = &aiColumnPk;
110755 sPk.aiRowEst = aiRowEstPk;
110756 sPk.onError = OE_Replace;
110757 sPk.pTable = pSrc->pTab;
110758 aiRowEstPk[0] = pSrc->pTab->nRowEst;
110759 aiRowEstPk[1] = 1;
110760 pFirst = pSrc->pTab->pIndex;
110761 if( pSrc->notIndexed==0 ){
110762 /* The real indices of the table are only considered if the
110763 ** NOT INDEXED qualifier is omitted from the FROM clause */
110764 sPk.pNext = pFirst;
110765 }
110766 pProbe = &sPk;
110767 }
110768 rSize = whereCost(pSrc->pTab->nRowEst);
110769 rLogSize = estLog(rSize);
110770
110771 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
110772 /* Automatic indexes */
110773 if( !pBuilder->pOrSet
@@ -110788,17 +111187,17 @@
110788 pNew->nLTerm = 1;
110789 pNew->aLTerm[0] = pTerm;
110790 /* TUNING: One-time cost for computing the automatic index is
110791 ** approximately 7*N*log2(N) where N is the number of rows in
110792 ** the table being indexed. */
110793 pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
110794 /* TUNING: Each index lookup yields 20 rows in the table. This
110795 ** is more than the usual guess of 10 rows, since we have no way
110796 ** of knowning how selective the index will ultimately be. It would
110797 ** not be unreasonable to make this value much larger. */
110798 pNew->nOut = 43; assert( 43==whereCost(20) );
110799 pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
110800 pNew->wsFlags = WHERE_AUTO_INDEX;
110801 pNew->prereq = mExtra | pTerm->prereqRight;
110802 rc = whereLoopInsert(pBuilder, pNew);
110803 }
110804 }
@@ -110828,15 +111227,13 @@
110828
110829 /* Full table scan */
110830 pNew->iSortIdx = b ? iSortIdx : 0;
110831 /* TUNING: Cost of full table scan is 3*(N + log2(N)).
110832 ** + The extra 3 factor is to encourage the use of indexed lookups
110833 ** over full scans. A smaller constant 2 is used for covering
110834 ** index scans so that a covering index scan will be favored over
110835 ** a table scan. */
110836 pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
110837 whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
110838 rc = whereLoopInsert(pBuilder, pNew);
110839 pNew->nOut = rSize;
110840 if( rc ) break;
110841 }else{
110842 Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
@@ -110844,33 +111241,32 @@
110844
110845 /* Full scan via index */
110846 if( b
110847 || ( m==0
110848 && pProbe->bUnordered==0
 
110849 && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
110850 && sqlite3GlobalConfig.bUseCis
110851 && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
110852 )
110853 ){
110854 pNew->iSortIdx = b ? iSortIdx : 0;
110855 if( m==0 ){
110856 /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
110857 ** + The extra 2 factor is to encourage the use of indexed lookups
110858 ** over index scans. A table scan uses a factor of 3 so that
110859 ** index scans are favored over table scans.
110860 ** + If this covering index might also help satisfy the ORDER BY
110861 ** clause, then the cost is fudged down slightly so that this
110862 ** index is favored above other indices that have no hope of
110863 ** helping with the ORDER BY. */
110864 pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
110865 }else{
110866 assert( b!=0 );
110867 /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
110868 ** which we will simplify to just N*log2(N) */
110869 pNew->rRun = rSize + rLogSize;
110870 }
110871 whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
110872 rc = whereLoopInsert(pBuilder, pNew);
110873 pNew->nOut = rSize;
110874 if( rc ) break;
110875 }
110876 }
@@ -111037,13 +111433,13 @@
111037 pIdxInfo->needToFreeIdxStr = 0;
111038 pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111039 pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111040 && pIdxInfo->orderByConsumed);
111041 pNew->rSetup = 0;
111042 pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
111043 /* TUNING: Every virtual table query returns 25 rows */
111044 pNew->nOut = 46; assert( 46==whereCost(25) );
111045 whereLoopInsert(pBuilder, pNew);
111046 if( pNew->u.vtab.needFree ){
111047 sqlite3_free(pNew->u.vtab.idxStr);
111048 pNew->u.vtab.needFree = 0;
111049 }
@@ -111076,10 +111472,12 @@
111076 pWC = pBuilder->pWC;
111077 if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111078 pWCEnd = pWC->a + pWC->nTerm;
111079 pNew = pBuilder->pNew;
111080 memset(&sSum, 0, sizeof(sSum));
 
 
111081
111082 for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111083 if( (pTerm->eOperator & WO_OR)!=0
111084 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111085 ){
@@ -111087,12 +111485,10 @@
111087 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111088 WhereTerm *pOrTerm;
111089 int once = 1;
111090 int i, j;
111091
111092 pItem = pWInfo->pTabList->a + pNew->iTab;
111093 iCur = pItem->iCursor;
111094 sSubBuild = *pBuilder;
111095 sSubBuild.pOrderBy = 0;
111096 sSubBuild.pOrSet = &sCur;
111097
111098 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111525,12 @@
111129 whereOrMove(&sPrev, &sSum);
111130 sSum.n = 0;
111131 for(i=0; i<sPrev.n; i++){
111132 for(j=0; j<sCur.n; j++){
111133 whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111134 whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111135 whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111136 }
111137 }
111138 }
111139 }
111140 pNew->nLTerm = 1;
@@ -111468,23 +111864,23 @@
111468 ** costs if nRowEst==0.
111469 **
111470 ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111471 ** error occurs.
111472 */
111473 static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
111474 int mxChoice; /* Maximum number of simultaneous paths tracked */
111475 int nLoop; /* Number of terms in the join */
111476 Parse *pParse; /* Parsing context */
111477 sqlite3 *db; /* The database connection */
111478 int iLoop; /* Loop counter over the terms of the join */
111479 int ii, jj; /* Loop counters */
111480 int mxI = 0; /* Index of next entry to replace */
111481 WhereCost rCost; /* Cost of a path */
111482 WhereCost nOut; /* Number of outputs */
111483 WhereCost mxCost = 0; /* Maximum cost of a set of paths */
111484 WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
111485 WhereCost rSortCost; /* Cost to do a sort */
111486 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111487 WherePath *aFrom; /* All nFrom paths at the previous level */
111488 WherePath *aTo; /* The nTo best paths at the current level */
111489 WherePath *pFrom; /* An element of aFrom[] that we are working on */
111490 WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111913,23 @@
111517 /* Seed the search with a single WherePath containing zero WhereLoops.
111518 **
111519 ** TUNING: Do not let the number of iterations go above 25. If the cost
111520 ** of computing an automatic index is not paid back within the first 25
111521 ** rows, then do not use the automatic index. */
111522 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
111523 nFrom = 1;
111524
111525 /* Precompute the cost of sorting the final result set, if the caller
111526 ** to sqlite3WhereBegin() was concerned about sorting */
111527 rSortCost = 0;
111528 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111529 aFrom[0].isOrderedValid = 1;
111530 }else{
111531 /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
111532 ** number of output rows. */
 
 
111533 rSortCost = nRowEst + estLog(nRowEst);
111534 WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111535 }
111536
111537 /* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111945,12 @@
111547 u8 isOrdered = pFrom->isOrdered;
111548 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111549 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111550 /* At this point, pWLoop is a candidate to be the next loop.
111551 ** Compute its cost */
111552 rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111553 rCost = whereCostAdd(rCost, pFrom->rCost);
111554 nOut = pFrom->nRow + pWLoop->nOut;
111555 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111556 if( !isOrderedValid ){
111557 switch( wherePathSatisfiesOrderBy(pWInfo,
111558 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111960,11 @@
111562 isOrderedValid = 1;
111563 break;
111564 case 0: /* No. pFrom+pWLoop will require a separate sort */
111565 isOrdered = 0;
111566 isOrderedValid = 1;
111567 rCost = whereCostAdd(rCost, rSortCost);
111568 break;
111569 default: /* Cannot tell yet. Try again on the next iteration */
111570 break;
111571 }
111572 }else{
@@ -111769,11 +112167,11 @@
111769 pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
111770 pLoop->aLTerm[0] = pTerm;
111771 pLoop->nLTerm = 1;
111772 pLoop->u.btree.nEq = 1;
111773 /* TUNING: Cost of a rowid lookup is 10 */
111774 pLoop->rRun = 33; /* 33==whereCost(10) */
111775 }else{
111776 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
111777 assert( pLoop->aLTermSpace==pLoop->aLTerm );
111778 assert( ArraySize(pLoop->aLTermSpace)==4 );
111779 if( pIdx->onError==OE_None
@@ -111792,16 +112190,16 @@
111792 }
111793 pLoop->nLTerm = j;
111794 pLoop->u.btree.nEq = j;
111795 pLoop->u.btree.pIndex = pIdx;
111796 /* TUNING: Cost of a unique index lookup is 15 */
111797 pLoop->rRun = 39; /* 39==whereCost(15) */
111798 break;
111799 }
111800 }
111801 if( pLoop->wsFlags ){
111802 pLoop->nOut = (WhereCost)1;
111803 pWInfo->a[0].pWLoop = pLoop;
111804 pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
111805 pWInfo->a[0].iTabCur = iCur;
111806 pWInfo->nRowOut = 1;
111807 if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112563,11 @@
112165 WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112166 pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112167
112168 /* If the caller is an UPDATE or DELETE statement that is requesting
112169 ** to use a one-pass algorithm, determine if this is appropriate.
112170 ** The one-pass algorithm only works if the WHERE clause constraints
112171 ** the statement to update a single row.
112172 */
112173 assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112174 if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112175 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121981,16 @@
121583 ** verifying the operation of the SQLite core.
121584 */
121585 int inTransaction; /* True after xBegin but before xCommit/xRollback */
121586 int mxSavepoint; /* Largest valid xSavepoint integer */
121587 #endif
 
 
 
 
 
 
121588 };
121589
121590 /*
121591 ** When the core wants to read from the virtual table, it creates a
121592 ** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +122012,12 @@
121608 int nDoclist; /* Size of buffer at aDoclist */
121609 u8 bDesc; /* True to sort in descending order */
121610 int eEvalmode; /* An FTS3_EVAL_XX constant */
121611 int nRowAvg; /* Average size of database rows, in pages */
121612 sqlite3_int64 nDoc; /* Documents in table */
121613
 
121614 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
121615 u32 *aMatchinfo; /* Information about most recent match */
121616 int nMatchinfo; /* Number of elements in aMatchinfo[] */
121617 char *zMatchinfo; /* Matchinfo specification */
121618 };
@@ -121638,10 +122043,19 @@
121638 */
121639 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
121640 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
121641 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
121642
 
 
 
 
 
 
 
 
 
121643
121644 struct Fts3Doclist {
121645 char *aAll; /* Array containing doclist (or NULL) */
121646 int nAll; /* Size of a[] in bytes */
121647 char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123472,31 @@
123058 */
123059 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123060 Fts3Table *p = (Fts3Table *)pVTab;
123061 int i; /* Iterator variable */
123062 int iCons = -1; /* Index of constraint to use */
 
123063 int iLangidCons = -1; /* Index of langid=x constraint, if present */
 
 
 
123064
123065 /* By default use a full table scan. This is an expensive option,
123066 ** so search through the constraints to see if a more efficient
123067 ** strategy is possible.
123068 */
123069 pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123070 pInfo->estimatedCost = 5000000;
123071 for(i=0; i<pInfo->nConstraint; i++){
 
123072 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123073 if( pCons->usable==0 ) continue;
 
 
123074
123075 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123076 if( iCons<0
123077 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123078 && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
123079 ){
123080 pInfo->idxNum = FTS3_DOCID_SEARCH;
123081 pInfo->estimatedCost = 1.0;
123082 iCons = i;
123083 }
123084
@@ -123103,18 +123521,42 @@
123103 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123104 && pCons->iColumn==p->nColumn + 2
123105 ){
123106 iLangidCons = i;
123107 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123108 }
123109
 
123110 if( iCons>=0 ){
123111 pInfo->aConstraintUsage[iCons].argvIndex = 1;
123112 pInfo->aConstraintUsage[iCons].omit = 1;
123113 }
123114 if( iLangidCons>=0 ){
123115 pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
 
 
 
 
 
 
 
 
 
123116 }
123117
123118 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123119 ** docid) order. Both ascending and descending are possible.
123120 */
@@ -124556,10 +124998,37 @@
124556 rc = fts3EvalNext((Fts3Cursor *)pCursor);
124557 }
124558 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
124559 return rc;
124560 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124561
124562 /*
124563 ** This is the xFilter interface for the virtual table. See
124564 ** the virtual table xFilter method documentation for additional
124565 ** information.
@@ -124582,44 +125051,62 @@
124582 int nVal, /* Number of elements in apVal */
124583 sqlite3_value **apVal /* Arguments for the indexing scheme */
124584 ){
124585 int rc;
124586 char *zSql; /* SQL statement used to access %_content */
 
124587 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
124588 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
 
 
 
 
 
 
124589
124590 UNUSED_PARAMETER(idxStr);
124591 UNUSED_PARAMETER(nVal);
124592
124593 assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
124594 assert( nVal==0 || nVal==1 || nVal==2 );
124595 assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
124596 assert( p->pSegments==0 );
 
 
 
 
 
 
 
 
124597
124598 /* In case the cursor has been used before, clear it now. */
124599 sqlite3_finalize(pCsr->pStmt);
124600 sqlite3_free(pCsr->aDoclist);
124601 sqlite3Fts3ExprFree(pCsr->pExpr);
124602 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
124603
 
 
 
 
124604 if( idxStr ){
124605 pCsr->bDesc = (idxStr[0]=='D');
124606 }else{
124607 pCsr->bDesc = p->bDescIdx;
124608 }
124609 pCsr->eSearch = (i16)idxNum;
124610
124611 if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
124612 int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
124613 const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
124614
124615 if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
124616 return SQLITE_NOMEM;
124617 }
124618
124619 pCsr->iLangid = 0;
124620 if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
124621
124622 assert( p->base.zErrMsg==0 );
124623 rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
124624 p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
124625 &p->base.zErrMsg
@@ -124638,11 +125125,11 @@
124638 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
124639 ** statement loops through all rows of the %_content table. For a
124640 ** full-text query or docid lookup, the statement retrieves a single
124641 ** row by docid.
124642 */
124643 if( idxNum==FTS3_FULLSCAN_SEARCH ){
124644 zSql = sqlite3_mprintf(
124645 "SELECT %s ORDER BY rowid %s",
124646 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
124647 );
124648 if( zSql ){
@@ -124649,14 +125136,14 @@
124649 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
124650 sqlite3_free(zSql);
124651 }else{
124652 rc = SQLITE_NOMEM;
124653 }
124654 }else if( idxNum==FTS3_DOCID_SEARCH ){
124655 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
124656 if( rc==SQLITE_OK ){
124657 rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
124658 }
124659 }
124660 if( rc!=SQLITE_OK ) return rc;
124661
124662 return fts3NextMethod(pCursor);
@@ -125543,10 +126030,16 @@
125543 }
125544
125545 return SQLITE_OK;
125546 }
125547
 
 
 
 
 
 
125548 /*
125549 ** This function is called for each Fts3Phrase in a full-text query
125550 ** expression to initialize the mechanism for returning rows. Once this
125551 ** function has been called successfully on an Fts3Phrase, it may be
125552 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +126049,47 @@
125556 ** memory within this call.
125557 **
125558 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
125559 */
125560 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
125561 int rc; /* Error code */
125562 Fts3PhraseToken *pFirst = &p->aToken[0];
125563 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125564
125565 if( pCsr->bDesc==pTab->bDescIdx
125566 && bOptOk==1
125567 && p->nToken==1
125568 && pFirst->pSegcsr
125569 && pFirst->pSegcsr->bLookup
125570 && pFirst->bFirst==0
125571 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125572 /* Use the incremental approach. */
125573 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
125574 rc = sqlite3Fts3MsrIncrStart(
125575 pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
 
 
 
 
 
125576 p->bIncr = 1;
125577
125578 }else{
125579 /* Load the full doclist for the phrase into memory. */
125580 rc = fts3EvalPhraseLoad(pCsr, p);
125581 p->bIncr = 0;
125582 }
@@ -125680,10 +126193,220 @@
125680 }
125681 }
125682
125683 *ppIter = p;
125684 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125685
125686 /*
125687 ** Attempt to move the phrase iterator to point to the next matching docid.
125688 ** If an error occurs, return an SQLite error code. Otherwise, return
125689 ** SQLITE_OK.
@@ -125700,59 +126423,18 @@
125700 int rc = SQLITE_OK;
125701 Fts3Doclist *pDL = &p->doclist;
125702 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
125703
125704 if( p->bIncr ){
125705 assert( p->nToken==1 );
125706 assert( pDL->pNextDocid==0 );
125707 rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
125708 &pDL->iDocid, &pDL->pList, &pDL->nList
125709 );
125710 if( rc==SQLITE_OK && !pDL->pList ){
125711 *pbEof = 1;
125712 }
125713 }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
125714 sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
125715 &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
125716 );
125717 pDL->pList = pDL->pNextDocid;
125718 }else{
125719 char *pIter; /* Used to iterate through aAll */
125720 char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
125721 if( pDL->pNextDocid ){
125722 pIter = pDL->pNextDocid;
125723 }else{
125724 pIter = pDL->aAll;
125725 }
125726
125727 if( pIter>=pEnd ){
125728 /* We have already reached the end of this doclist. EOF. */
125729 *pbEof = 1;
125730 }else{
125731 sqlite3_int64 iDelta;
125732 pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
125733 if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
125734 pDL->iDocid += iDelta;
125735 }else{
125736 pDL->iDocid -= iDelta;
125737 }
125738 pDL->pList = pIter;
125739 fts3PoslistCopy(0, &pIter);
125740 pDL->nList = (int)(pIter - pDL->pList);
125741
125742 /* pIter now points just past the 0x00 that terminates the position-
125743 ** list for document pDL->iDocid. However, if this position-list was
125744 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
125745 ** point to the start of the next docid value. The following line deals
125746 ** with this case by advancing pIter past the zero-padding added by
125747 ** fts3EvalNearTrim(). */
125748 while( pIter<pEnd && *pIter==0 ) pIter++;
125749
125750 pDL->pNextDocid = pIter;
125751 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
125752 *pbEof = 0;
125753 }
125754 }
125755
125756 return rc;
125757 }
125758
@@ -125773,11 +126455,10 @@
125773 ** code before returning.
125774 */
125775 static void fts3EvalStartReaders(
125776 Fts3Cursor *pCsr, /* FTS Cursor handle */
125777 Fts3Expr *pExpr, /* Expression to initialize phrases in */
125778 int bOptOk, /* True to enable incremental loading */
125779 int *pRc /* IN/OUT: Error code */
125780 ){
125781 if( pExpr && SQLITE_OK==*pRc ){
125782 if( pExpr->eType==FTSQUERY_PHRASE ){
125783 int i;
@@ -125784,14 +126465,14 @@
125784 int nToken = pExpr->pPhrase->nToken;
125785 for(i=0; i<nToken; i++){
125786 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
125787 }
125788 pExpr->bDeferred = (i==nToken);
125789 *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
125790 }else{
125791 fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
125792 fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
125793 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
125794 }
125795 }
125796 }
125797
@@ -126029,11 +126710,11 @@
126029 /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126030 ** for-loop. Except, limit the value to 2^24 to prevent it from
126031 ** overflowing the 32-bit integer it is stored in. */
126032 if( ii<12 ) nLoad4 = nLoad4*4;
126033
126034 if( ii==0 || pTC->pPhrase->nToken>1 ){
126035 /* Either this is the cheapest token in the entire query, or it is
126036 ** part of a multi-token phrase. Either way, the entire doclist will
126037 ** (eventually) be loaded into memory. It may as well be now. */
126038 Fts3PhraseToken *pToken = pTC->pToken;
126039 int nList = 0;
@@ -126109,11 +126790,11 @@
126109 sqlite3_free(aTC);
126110 }
126111 }
126112 #endif
126113
126114 fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
126115 return rc;
126116 }
126117
126118 /*
126119 ** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127273,20 @@
126592 pCsr->isRequireSeek = 1;
126593 pCsr->isMatchinfoNeeded = 1;
126594 pCsr->iPrevId = pExpr->iDocid;
126595 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
126596 }
 
 
 
 
 
 
 
 
 
 
126597 return rc;
126598 }
126599
126600 /*
126601 ** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127306,20 @@
126615 Fts3Phrase *pPhrase = pExpr->pPhrase;
126616
126617 if( pPhrase ){
126618 fts3EvalInvalidatePoslist(pPhrase);
126619 if( pPhrase->bIncr ){
126620 assert( pPhrase->nToken==1 );
126621 assert( pPhrase->aToken[0].pSegcsr );
126622 sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
 
 
 
 
 
126623 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
126624 }
126625
126626 pPhrase->doclist.pNextDocid = 0;
126627 pPhrase->doclist.iDocid = 0;
126628 }
126629
126630 pExpr->iDocid = 0;
@@ -126869,19 +127564,27 @@
126869
126870 iDocid = pExpr->iDocid;
126871 pIter = pPhrase->doclist.pList;
126872 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
126873 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
 
126874 int bOr = 0;
126875 u8 bEof = 0;
126876 Fts3Expr *p;
 
 
126877
126878 /* Check if this phrase descends from an OR expression node. If not,
126879 ** return NULL. Otherwise, the entry that corresponds to docid
126880 ** pCsr->iPrevId may lie earlier in the doclist buffer. */
 
 
 
126881 for(p=pExpr->pParent; p; p=p->pParent){
126882 if( p->eType==FTSQUERY_OR ) bOr = 1;
 
 
126883 }
126884 if( bOr==0 ) return SQLITE_OK;
126885
126886 /* This is the descendent of an OR node. In this case we cannot use
126887 ** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127599,63 @@
126896 }
126897 pIter = pPhrase->doclist.pList;
126898 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
126899 if( rc!=SQLITE_OK ) return rc;
126900 }
 
 
 
 
 
 
 
 
 
 
 
 
126901
126902 if( pExpr->bEof ){
126903 pIter = 0;
126904 iDocid = 0;
126905 }
126906 bEof = (pPhrase->doclist.nAll==0);
126907 assert( bDescDoclist==0 || bDescDoclist==1 );
126908 assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
126909
126910 if( pCsr->bDesc==bDescDoclist ){
126911 int dummy;
126912 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
126913 sqlite3Fts3DoclistPrev(
126914 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126915 &pIter, &iDocid, &dummy, &bEof
126916 );
126917 }
126918 }else{
126919 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
126920 sqlite3Fts3DoclistNext(
126921 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
126922 &pIter, &iDocid, &bEof
126923 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126924 }
126925 }
126926
126927 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
126928 }
@@ -127026,10 +127759,11 @@
127026 sqlite3_vtab_cursor base; /* Base class used by SQLite core */
127027 Fts3MultiSegReader csr; /* Must be right after "base" */
127028 Fts3SegFilter filter;
127029 char *zStop;
127030 int nStop; /* Byte-length of string zStop */
 
127031 int isEof; /* True if cursor is at EOF */
127032 sqlite3_int64 iRowid; /* Current rowid */
127033
127034 int iCol; /* Current value of 'col' column */
127035 int nStat; /* Size of aStat[] array */
@@ -127040,11 +127774,12 @@
127040 };
127041
127042 /*
127043 ** Schema of the terms table.
127044 */
127045 #define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
 
127046
127047 /*
127048 ** This function does all the work for both the xConnect and xCreate methods.
127049 ** These tables have no persistent representation of their own, so xConnect
127050 ** and xCreate are identical operations.
@@ -127087,11 +127822,11 @@
127087 }else{
127088 zFts3 = argv[3];
127089 }
127090 nFts3 = (int)strlen(zFts3);
127091
127092 rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
127093 if( rc!=SQLITE_OK ) return rc;
127094
127095 nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
127096 p = (Fts3auxTable *)sqlite3_malloc(nByte);
127097 if( !p ) return SQLITE_NOMEM;
@@ -127147,10 +127882,12 @@
127147 ){
127148 int i;
127149 int iEq = -1;
127150 int iGe = -1;
127151 int iLe = -1;
 
 
127152
127153 UNUSED_PARAMETER(pVTab);
127154
127155 /* This vtab delivers always results in "ORDER BY term ASC" order. */
127156 if( pInfo->nOrderBy==1
@@ -127158,40 +127895,52 @@
127158 && pInfo->aOrderBy[0].desc==0
127159 ){
127160 pInfo->orderByConsumed = 1;
127161 }
127162
127163 /* Search for equality and range constraints on the "term" column. */
 
127164 for(i=0; i<pInfo->nConstraint; i++){
127165 if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
127166 int op = pInfo->aConstraint[i].op;
127167 if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
127168 if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
127169 if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
127170 if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
127171 if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
 
 
 
 
 
 
 
127172 }
127173 }
127174
127175 if( iEq>=0 ){
127176 pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
127177 pInfo->aConstraintUsage[iEq].argvIndex = 1;
127178 pInfo->estimatedCost = 5;
127179 }else{
127180 pInfo->idxNum = 0;
127181 pInfo->estimatedCost = 20000;
127182 if( iGe>=0 ){
127183 pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
127184 pInfo->aConstraintUsage[iGe].argvIndex = 1;
127185 pInfo->estimatedCost /= 2;
127186 }
127187 if( iLe>=0 ){
127188 pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
127189 pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
127190 pInfo->estimatedCost /= 2;
127191 }
127192 }
 
 
 
 
127193
127194 return SQLITE_OK;
127195 }
127196
127197 /*
@@ -127347,21 +128096,42 @@
127347 sqlite3_value **apVal /* Arguments for the indexing scheme */
127348 ){
127349 Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
127350 Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
127351 int rc;
127352 int isScan;
 
 
 
 
 
 
 
127353
127354 UNUSED_PARAMETER(nVal);
127355 UNUSED_PARAMETER(idxStr);
127356
127357 assert( idxStr==0 );
127358 assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
127359 || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
127360 || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
127361 );
127362 isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127363
127364 /* In case this cursor is being reused, close and zero it. */
127365 testcase(pCsr->filter.zTerm);
127366 sqlite3Fts3SegReaderFinish(&pCsr->csr);
127367 sqlite3_free((void *)pCsr->filter.zTerm);
@@ -127369,26 +128139,39 @@
127369 memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
127370
127371 pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
127372 if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
127373
127374 if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
127375 const unsigned char *zStr = sqlite3_value_text(apVal[0]);
 
127376 if( zStr ){
127377 pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
127378 pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
127379 if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
127380 }
127381 }
127382 if( idxNum&FTS4AUX_LE_CONSTRAINT ){
127383 int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
127384 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
127385 pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
127386 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
127387 }
 
 
 
127388
127389 rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
 
 
 
 
 
 
 
 
 
127390 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
127391 );
127392 if( rc==SQLITE_OK ){
127393 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
127394 }
@@ -127408,28 +128191,41 @@
127408 /*
127409 ** xColumn - Return a column value.
127410 */
127411 static int fts3auxColumnMethod(
127412 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
127413 sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
127414 int iCol /* Index of column to read value from */
127415 ){
127416 Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
127417
127418 assert( p->isEof==0 );
127419 if( iCol==0 ){ /* Column "term" */
127420 sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
127421 }else if( iCol==1 ){ /* Column "col" */
127422 if( p->iCol ){
127423 sqlite3_result_int(pContext, p->iCol-1);
127424 }else{
127425 sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
127426 }
127427 }else if( iCol==2 ){ /* Column "documents" */
127428 sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
127429 }else{ /* Column "occurrences" */
127430 sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
 
 
 
 
 
 
 
 
 
 
 
 
 
127431 }
127432
127433 return SQLITE_OK;
127434 }
127435
@@ -135756,11 +136552,11 @@
135756 assert( p->bFts4==0 );
135757 sqlite3Fts3CreateStatTable(&rc, p);
135758 if( rc ) return rc;
135759 }
135760 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
135761 if( rc ) return rc;;
135762 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
135763 sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
135764 sqlite3_step(pStmt);
135765 rc = sqlite3_reset(pStmt);
135766 return rc;
@@ -136025,10 +136821,13 @@
136025 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136026 p->nNodeSize = atoi(&zVal[9]);
136027 rc = SQLITE_OK;
136028 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136029 p->nMaxPendingData = atoi(&zVal[11]);
 
 
 
136030 rc = SQLITE_OK;
136031 #endif
136032 }else{
136033 rc = SQLITE_ERROR;
136034 }
136035
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -23,531 +23,10 @@
23 # define SQLITE_PRIVATE static
24 #endif
25 #ifndef SQLITE_API
26 # define SQLITE_API
27 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28 /************** Begin file sqlite3.h *****************************************/
29 /*
30 ** 2001 September 15
31 **
32 ** The author disclaims copyright to this source code. In place of
@@ -656,11 +135,11 @@
135 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
136 ** [sqlite_version()] and [sqlite_source_id()].
137 */
138 #define SQLITE_VERSION "3.8.1"
139 #define SQLITE_VERSION_NUMBER 3008001
140 #define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a"
141
142 /*
143 ** CAPI3REF: Run-Time Library Version Numbers
144 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
145 **
@@ -2164,31 +1643,31 @@
1643 ** supplied by the application must not invoke any SQLite interface.
1644 ** In a multi-threaded application, the application-defined logger
1645 ** function must be threadsafe. </dd>
1646 **
1647 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1648 ** <dd>^(This option takes a single argument of type int. If non-zero, then
1649 ** URI handling is globally enabled. If the parameter is zero, then URI handling
1650 ** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
1651 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1652 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1653 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1654 ** connection is opened. ^If it is globally disabled, filenames are
1655 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1656 ** database connection is opened. ^(By default, URI handling is globally
1657 ** disabled. The default value may be changed by compiling with the
1658 ** [SQLITE_USE_URI] symbol defined.)^
1659 **
1660 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1661 ** <dd>^This option takes a single integer argument which is interpreted as
1662 ** a boolean in order to enable or disable the use of covering indices for
1663 ** full table scans in the query optimizer. ^The default setting is determined
1664 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
1665 ** if that compile-time option is omitted.
1666 ** The ability to disable the use of covering indices for full table scans
1667 ** is because some incorrectly coded legacy applications might malfunction
1668 ** when the optimization is enabled. Providing the ability to
1669 ** disable the optimization allows the older, buggy application code to work
1670 ** without change even with newer versions of SQLite.
1671 **
1672 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
1673 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -2213,20 +1692,20 @@
1692 ** configuration option can be seen in the "test_sqllog.c" source file in
1693 ** the canonical SQLite source tree.</dd>
1694 **
1695 ** [[SQLITE_CONFIG_MMAP_SIZE]]
1696 ** <dt>SQLITE_CONFIG_MMAP_SIZE
1697 ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
1698 ** that are the default mmap size limit (the default setting for
1699 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
1700 ** ^The default setting can be overridden by each database connection using
1701 ** either the [PRAGMA mmap_size] command, or by using the
1702 ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
1703 ** cannot be changed at run-time. Nor may the maximum allowed mmap size
1704 ** exceed the compile-time maximum mmap size set by the
1705 ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
1706 ** ^If either argument to this option is negative, then that argument is
1707 ** changed to its compile-time default.
1708 ** </dl>
1709 */
1710 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1711 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
@@ -7846,11 +7325,530 @@
7325
7326 #endif /* ifndef _SQLITE3RTREE_H_ */
7327
7328
7329 /************** End of sqlite3.h *********************************************/
7330 /************** Begin file sqliteInt.h ***************************************/
7331 /*
7332 ** 2001 September 15
7333 **
7334 ** The author disclaims copyright to this source code. In place of
7335 ** a legal notice, here is a blessing:
7336 **
7337 ** May you do good and not evil.
7338 ** May you find forgiveness for yourself and forgive others.
7339 ** May you share freely, never taking more than you give.
7340 **
7341 *************************************************************************
7342 ** Internal interface definitions for SQLite.
7343 **
7344 */
7345 #ifndef _SQLITEINT_H_
7346 #define _SQLITEINT_H_
7347
7348 /*
7349 ** These #defines should enable >2GB file support on POSIX if the
7350 ** underlying operating system supports it. If the OS lacks
7351 ** large file support, or if the OS is windows, these should be no-ops.
7352 **
7353 ** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
7354 ** system #includes. Hence, this block of code must be the very first
7355 ** code in all source files.
7356 **
7357 ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
7358 ** on the compiler command line. This is necessary if you are compiling
7359 ** on a recent machine (ex: Red Hat 7.2) but you want your code to work
7360 ** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
7361 ** without this option, LFS is enable. But LFS does not exist in the kernel
7362 ** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
7363 ** portability you should omit LFS.
7364 **
7365 ** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
7366 */
7367 #ifndef SQLITE_DISABLE_LFS
7368 # define _LARGE_FILE 1
7369 # ifndef _FILE_OFFSET_BITS
7370 # define _FILE_OFFSET_BITS 64
7371 # endif
7372 # define _LARGEFILE_SOURCE 1
7373 #endif
7374
7375 /*
7376 ** Include the configuration header output by 'configure' if we're using the
7377 ** autoconf-based build
7378 */
7379 #ifdef _HAVE_SQLITE_CONFIG_H
7380 #include "config.h"
7381 #endif
7382
7383 /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
7384 /************** Begin file sqliteLimit.h *************************************/
7385 /*
7386 ** 2007 May 7
7387 **
7388 ** The author disclaims copyright to this source code. In place of
7389 ** a legal notice, here is a blessing:
7390 **
7391 ** May you do good and not evil.
7392 ** May you find forgiveness for yourself and forgive others.
7393 ** May you share freely, never taking more than you give.
7394 **
7395 *************************************************************************
7396 **
7397 ** This file defines various limits of what SQLite can process.
7398 */
7399
7400 /*
7401 ** The maximum length of a TEXT or BLOB in bytes. This also
7402 ** limits the size of a row in a table or index.
7403 **
7404 ** The hard limit is the ability of a 32-bit signed integer
7405 ** to count the size: 2^31-1 or 2147483647.
7406 */
7407 #ifndef SQLITE_MAX_LENGTH
7408 # define SQLITE_MAX_LENGTH 1000000000
7409 #endif
7410
7411 /*
7412 ** This is the maximum number of
7413 **
7414 ** * Columns in a table
7415 ** * Columns in an index
7416 ** * Columns in a view
7417 ** * Terms in the SET clause of an UPDATE statement
7418 ** * Terms in the result set of a SELECT statement
7419 ** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
7420 ** * Terms in the VALUES clause of an INSERT statement
7421 **
7422 ** The hard upper limit here is 32676. Most database people will
7423 ** tell you that in a well-normalized database, you usually should
7424 ** not have more than a dozen or so columns in any table. And if
7425 ** that is the case, there is no point in having more than a few
7426 ** dozen values in any of the other situations described above.
7427 */
7428 #ifndef SQLITE_MAX_COLUMN
7429 # define SQLITE_MAX_COLUMN 2000
7430 #endif
7431
7432 /*
7433 ** The maximum length of a single SQL statement in bytes.
7434 **
7435 ** It used to be the case that setting this value to zero would
7436 ** turn the limit off. That is no longer true. It is not possible
7437 ** to turn this limit off.
7438 */
7439 #ifndef SQLITE_MAX_SQL_LENGTH
7440 # define SQLITE_MAX_SQL_LENGTH 1000000000
7441 #endif
7442
7443 /*
7444 ** The maximum depth of an expression tree. This is limited to
7445 ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
7446 ** want to place more severe limits on the complexity of an
7447 ** expression.
7448 **
7449 ** A value of 0 used to mean that the limit was not enforced.
7450 ** But that is no longer true. The limit is now strictly enforced
7451 ** at all times.
7452 */
7453 #ifndef SQLITE_MAX_EXPR_DEPTH
7454 # define SQLITE_MAX_EXPR_DEPTH 1000
7455 #endif
7456
7457 /*
7458 ** The maximum number of terms in a compound SELECT statement.
7459 ** The code generator for compound SELECT statements does one
7460 ** level of recursion for each term. A stack overflow can result
7461 ** if the number of terms is too large. In practice, most SQL
7462 ** never has more than 3 or 4 terms. Use a value of 0 to disable
7463 ** any limit on the number of terms in a compount SELECT.
7464 */
7465 #ifndef SQLITE_MAX_COMPOUND_SELECT
7466 # define SQLITE_MAX_COMPOUND_SELECT 500
7467 #endif
7468
7469 /*
7470 ** The maximum number of opcodes in a VDBE program.
7471 ** Not currently enforced.
7472 */
7473 #ifndef SQLITE_MAX_VDBE_OP
7474 # define SQLITE_MAX_VDBE_OP 25000
7475 #endif
7476
7477 /*
7478 ** The maximum number of arguments to an SQL function.
7479 */
7480 #ifndef SQLITE_MAX_FUNCTION_ARG
7481 # define SQLITE_MAX_FUNCTION_ARG 127
7482 #endif
7483
7484 /*
7485 ** The maximum number of in-memory pages to use for the main database
7486 ** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
7487 */
7488 #ifndef SQLITE_DEFAULT_CACHE_SIZE
7489 # define SQLITE_DEFAULT_CACHE_SIZE 2000
7490 #endif
7491 #ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
7492 # define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
7493 #endif
7494
7495 /*
7496 ** The default number of frames to accumulate in the log file before
7497 ** checkpointing the database in WAL mode.
7498 */
7499 #ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
7500 # define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
7501 #endif
7502
7503 /*
7504 ** The maximum number of attached databases. This must be between 0
7505 ** and 62. The upper bound on 62 is because a 64-bit integer bitmap
7506 ** is used internally to track attached databases.
7507 */
7508 #ifndef SQLITE_MAX_ATTACHED
7509 # define SQLITE_MAX_ATTACHED 10
7510 #endif
7511
7512
7513 /*
7514 ** The maximum value of a ?nnn wildcard that the parser will accept.
7515 */
7516 #ifndef SQLITE_MAX_VARIABLE_NUMBER
7517 # define SQLITE_MAX_VARIABLE_NUMBER 999
7518 #endif
7519
7520 /* Maximum page size. The upper bound on this value is 65536. This a limit
7521 ** imposed by the use of 16-bit offsets within each page.
7522 **
7523 ** Earlier versions of SQLite allowed the user to change this value at
7524 ** compile time. This is no longer permitted, on the grounds that it creates
7525 ** a library that is technically incompatible with an SQLite library
7526 ** compiled with a different limit. If a process operating on a database
7527 ** with a page-size of 65536 bytes crashes, then an instance of SQLite
7528 ** compiled with the default page-size limit will not be able to rollback
7529 ** the aborted transaction. This could lead to database corruption.
7530 */
7531 #ifdef SQLITE_MAX_PAGE_SIZE
7532 # undef SQLITE_MAX_PAGE_SIZE
7533 #endif
7534 #define SQLITE_MAX_PAGE_SIZE 65536
7535
7536
7537 /*
7538 ** The default size of a database page.
7539 */
7540 #ifndef SQLITE_DEFAULT_PAGE_SIZE
7541 # define SQLITE_DEFAULT_PAGE_SIZE 1024
7542 #endif
7543 #if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
7544 # undef SQLITE_DEFAULT_PAGE_SIZE
7545 # define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
7546 #endif
7547
7548 /*
7549 ** Ordinarily, if no value is explicitly provided, SQLite creates databases
7550 ** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
7551 ** device characteristics (sector-size and atomic write() support),
7552 ** SQLite may choose a larger value. This constant is the maximum value
7553 ** SQLite will choose on its own.
7554 */
7555 #ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
7556 # define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
7557 #endif
7558 #if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
7559 # undef SQLITE_MAX_DEFAULT_PAGE_SIZE
7560 # define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
7561 #endif
7562
7563
7564 /*
7565 ** Maximum number of pages in one database file.
7566 **
7567 ** This is really just the default value for the max_page_count pragma.
7568 ** This value can be lowered (or raised) at run-time using that the
7569 ** max_page_count macro.
7570 */
7571 #ifndef SQLITE_MAX_PAGE_COUNT
7572 # define SQLITE_MAX_PAGE_COUNT 1073741823
7573 #endif
7574
7575 /*
7576 ** Maximum length (in bytes) of the pattern in a LIKE or GLOB
7577 ** operator.
7578 */
7579 #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
7580 # define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
7581 #endif
7582
7583 /*
7584 ** Maximum depth of recursion for triggers.
7585 **
7586 ** A value of 1 means that a trigger program will not be able to itself
7587 ** fire any triggers. A value of 0 means that no trigger programs at all
7588 ** may be executed.
7589 */
7590 #ifndef SQLITE_MAX_TRIGGER_DEPTH
7591 # define SQLITE_MAX_TRIGGER_DEPTH 1000
7592 #endif
7593
7594 /************** End of sqliteLimit.h *****************************************/
7595 /************** Continuing where we left off in sqliteInt.h ******************/
7596
7597 /* Disable nuisance warnings on Borland compilers */
7598 #if defined(__BORLANDC__)
7599 #pragma warn -rch /* unreachable code */
7600 #pragma warn -ccc /* Condition is always true or false */
7601 #pragma warn -aus /* Assigned value is never used */
7602 #pragma warn -csu /* Comparing signed and unsigned */
7603 #pragma warn -spa /* Suspicious pointer arithmetic */
7604 #endif
7605
7606 /* Needed for various definitions... */
7607 #ifndef _GNU_SOURCE
7608 # define _GNU_SOURCE
7609 #endif
7610
7611 #if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
7612 # define _BSD_SOURCE
7613 #endif
7614
7615 /*
7616 ** Include standard header files as necessary
7617 */
7618 #ifdef HAVE_STDINT_H
7619 #include <stdint.h>
7620 #endif
7621 #ifdef HAVE_INTTYPES_H
7622 #include <inttypes.h>
7623 #endif
7624
7625 /*
7626 ** The following macros are used to cast pointers to integers and
7627 ** integers to pointers. The way you do this varies from one compiler
7628 ** to the next, so we have developed the following set of #if statements
7629 ** to generate appropriate macros for a wide range of compilers.
7630 **
7631 ** The correct "ANSI" way to do this is to use the intptr_t type.
7632 ** Unfortunately, that typedef is not available on all compilers, or
7633 ** if it is available, it requires an #include of specific headers
7634 ** that vary from one machine to the next.
7635 **
7636 ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
7637 ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
7638 ** So we have to define the macros in different ways depending on the
7639 ** compiler.
7640 */
7641 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
7642 # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
7643 # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
7644 #elif !defined(__GNUC__) /* Works for compilers other than LLVM */
7645 # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
7646 # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
7647 #elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
7648 # define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
7649 # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
7650 #else /* Generates a warning - but it always works */
7651 # define SQLITE_INT_TO_PTR(X) ((void*)(X))
7652 # define SQLITE_PTR_TO_INT(X) ((int)(X))
7653 #endif
7654
7655 /*
7656 ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
7657 ** 0 means mutexes are permanently disable and the library is never
7658 ** threadsafe. 1 means the library is serialized which is the highest
7659 ** level of threadsafety. 2 means the library is multithreaded - multiple
7660 ** threads can use SQLite as long as no two threads try to use the same
7661 ** database connection at the same time.
7662 **
7663 ** Older versions of SQLite used an optional THREADSAFE macro.
7664 ** We support that for legacy.
7665 */
7666 #if !defined(SQLITE_THREADSAFE)
7667 # if defined(THREADSAFE)
7668 # define SQLITE_THREADSAFE THREADSAFE
7669 # else
7670 # define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
7671 # endif
7672 #endif
7673
7674 /*
7675 ** Powersafe overwrite is on by default. But can be turned off using
7676 ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
7677 */
7678 #ifndef SQLITE_POWERSAFE_OVERWRITE
7679 # define SQLITE_POWERSAFE_OVERWRITE 1
7680 #endif
7681
7682 /*
7683 ** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
7684 ** It determines whether or not the features related to
7685 ** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
7686 ** be overridden at runtime using the sqlite3_config() API.
7687 */
7688 #if !defined(SQLITE_DEFAULT_MEMSTATUS)
7689 # define SQLITE_DEFAULT_MEMSTATUS 1
7690 #endif
7691
7692 /*
7693 ** Exactly one of the following macros must be defined in order to
7694 ** specify which memory allocation subsystem to use.
7695 **
7696 ** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
7697 ** SQLITE_WIN32_MALLOC // Use Win32 native heap API
7698 ** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
7699 ** SQLITE_MEMDEBUG // Debugging version of system malloc()
7700 **
7701 ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
7702 ** assert() macro is enabled, each call into the Win32 native heap subsystem
7703 ** will cause HeapValidate to be called. If heap validation should fail, an
7704 ** assertion will be triggered.
7705 **
7706 ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
7707 ** the default.
7708 */
7709 #if defined(SQLITE_SYSTEM_MALLOC) \
7710 + defined(SQLITE_WIN32_MALLOC) \
7711 + defined(SQLITE_ZERO_MALLOC) \
7712 + defined(SQLITE_MEMDEBUG)>1
7713 # error "Two or more of the following compile-time configuration options\
7714 are defined but at most one is allowed:\
7715 SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
7716 SQLITE_ZERO_MALLOC"
7717 #endif
7718 #if defined(SQLITE_SYSTEM_MALLOC) \
7719 + defined(SQLITE_WIN32_MALLOC) \
7720 + defined(SQLITE_ZERO_MALLOC) \
7721 + defined(SQLITE_MEMDEBUG)==0
7722 # define SQLITE_SYSTEM_MALLOC 1
7723 #endif
7724
7725 /*
7726 ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
7727 ** sizes of memory allocations below this value where possible.
7728 */
7729 #if !defined(SQLITE_MALLOC_SOFT_LIMIT)
7730 # define SQLITE_MALLOC_SOFT_LIMIT 1024
7731 #endif
7732
7733 /*
7734 ** We need to define _XOPEN_SOURCE as follows in order to enable
7735 ** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
7736 ** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
7737 ** it.
7738 */
7739 #if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
7740 # define _XOPEN_SOURCE 600
7741 #endif
7742
7743 /*
7744 ** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
7745 ** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
7746 ** make it true by defining or undefining NDEBUG.
7747 **
7748 ** Setting NDEBUG makes the code smaller and faster by disabling the
7749 ** assert() statements in the code. So we want the default action
7750 ** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
7751 ** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
7752 ** feature.
7753 */
7754 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
7755 # define NDEBUG 1
7756 #endif
7757 #if defined(NDEBUG) && defined(SQLITE_DEBUG)
7758 # undef NDEBUG
7759 #endif
7760
7761 /*
7762 ** The testcase() macro is used to aid in coverage testing. When
7763 ** doing coverage testing, the condition inside the argument to
7764 ** testcase() must be evaluated both true and false in order to
7765 ** get full branch coverage. The testcase() macro is inserted
7766 ** to help ensure adequate test coverage in places where simple
7767 ** condition/decision coverage is inadequate. For example, testcase()
7768 ** can be used to make sure boundary values are tested. For
7769 ** bitmask tests, testcase() can be used to make sure each bit
7770 ** is significant and used at least once. On switch statements
7771 ** where multiple cases go to the same block of code, testcase()
7772 ** can insure that all cases are evaluated.
7773 **
7774 */
7775 #ifdef SQLITE_COVERAGE_TEST
7776 SQLITE_PRIVATE void sqlite3Coverage(int);
7777 # define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
7778 #else
7779 # define testcase(X)
7780 #endif
7781
7782 /*
7783 ** The TESTONLY macro is used to enclose variable declarations or
7784 ** other bits of code that are needed to support the arguments
7785 ** within testcase() and assert() macros.
7786 */
7787 #if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
7788 # define TESTONLY(X) X
7789 #else
7790 # define TESTONLY(X)
7791 #endif
7792
7793 /*
7794 ** Sometimes we need a small amount of code such as a variable initialization
7795 ** to setup for a later assert() statement. We do not want this code to
7796 ** appear when assert() is disabled. The following macro is therefore
7797 ** used to contain that setup code. The "VVA" acronym stands for
7798 ** "Verification, Validation, and Accreditation". In other words, the
7799 ** code within VVA_ONLY() will only run during verification processes.
7800 */
7801 #ifndef NDEBUG
7802 # define VVA_ONLY(X) X
7803 #else
7804 # define VVA_ONLY(X)
7805 #endif
7806
7807 /*
7808 ** The ALWAYS and NEVER macros surround boolean expressions which
7809 ** are intended to always be true or false, respectively. Such
7810 ** expressions could be omitted from the code completely. But they
7811 ** are included in a few cases in order to enhance the resilience
7812 ** of SQLite to unexpected behavior - to make the code "self-healing"
7813 ** or "ductile" rather than being "brittle" and crashing at the first
7814 ** hint of unplanned behavior.
7815 **
7816 ** In other words, ALWAYS and NEVER are added for defensive code.
7817 **
7818 ** When doing coverage testing ALWAYS and NEVER are hard-coded to
7819 ** be true and false so that the unreachable code they specify will
7820 ** not be counted as untested code.
7821 */
7822 #if defined(SQLITE_COVERAGE_TEST)
7823 # define ALWAYS(X) (1)
7824 # define NEVER(X) (0)
7825 #elif !defined(NDEBUG)
7826 # define ALWAYS(X) ((X)?1:(assert(0),0))
7827 # define NEVER(X) ((X)?(assert(0),1):0)
7828 #else
7829 # define ALWAYS(X) (X)
7830 # define NEVER(X) (X)
7831 #endif
7832
7833 /*
7834 ** Return true (non-zero) if the input is a integer that is too large
7835 ** to fit in 32-bits. This macro is used inside of various testcase()
7836 ** macros to verify that we have tested SQLite for large-file support.
7837 */
7838 #define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
7839
7840 /*
7841 ** The macro unlikely() is a hint that surrounds a boolean
7842 ** expression that is usually false. Macro likely() surrounds
7843 ** a boolean expression that is usually true. These hints could,
7844 ** in theory, be used by the compiler to generate better code, but
7845 ** currently they are just comments for human readers.
7846 */
7847 #define likely(X) (X)
7848 #define unlikely(X) (X)
7849
7850 /************** Include hash.h in the middle of sqliteInt.h ******************/
7851 /************** Begin file hash.h ********************************************/
7852 /*
7853 ** 2001 September 22
7854 **
@@ -8272,10 +8270,35 @@
8270 typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
8271 #else
8272 typedef u32 tRowcnt; /* 32-bit is the default */
8273 #endif
8274
8275 /*
8276 ** Estimated quantities used for query planning are stored as 16-bit
8277 ** logarithms. For quantity X, the value stored is 10*log2(X). This
8278 ** gives a possible range of values of approximately 1.0e986 to 1e-986.
8279 ** But the allowed values are "grainy". Not every value is representable.
8280 ** For example, quantities 16 and 17 are both represented by a LogEst
8281 ** of 40. However, since LogEst quantatites are suppose to be estimates,
8282 ** not exact values, this imprecision is not a problem.
8283 **
8284 ** "LogEst" is short for "Logarithimic Estimate".
8285 **
8286 ** Examples:
8287 ** 1 -> 0 20 -> 43 10000 -> 132
8288 ** 2 -> 10 25 -> 46 25000 -> 146
8289 ** 3 -> 16 100 -> 66 1000000 -> 199
8290 ** 4 -> 20 1000 -> 99 1048576 -> 200
8291 ** 10 -> 33 1024 -> 100 4294967296 -> 320
8292 **
8293 ** The LogEst can be negative to indicate fractional values.
8294 ** Examples:
8295 **
8296 ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
8297 */
8298 typedef INT16_TYPE LogEst;
8299
8300 /*
8301 ** Macros to determine whether the machine is big or little endian,
8302 ** evaluated at runtime.
8303 */
8304 #ifdef SQLITE_AMALGAMATION
@@ -10419,11 +10442,12 @@
10442 char *zDflt; /* Original text of the default value */
10443 char *zType; /* Data type for this column */
10444 char *zColl; /* Collating sequence. If NULL, use the default */
10445 u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
10446 char affinity; /* One of the SQLITE_AFF_... values */
10447 u8 szEst; /* Estimated size of this column. INT==1 */
10448 u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
10449 };
10450
10451 /* Allowed values for Column.colFlags:
10452 */
10453 #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
@@ -10583,10 +10607,11 @@
10607 tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
10608 int tnum; /* Root BTree node for this table (see note above) */
10609 i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
10610 i16 nCol; /* Number of columns in this table */
10611 u16 nRef; /* Number of pointers to this Table */
10612 LogEst szTabRow; /* Estimated size of each table row in bytes */
10613 u8 tabFlags; /* Mask of TF_* values */
10614 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
10615 #ifndef SQLITE_OMIT_ALTERTABLE
10616 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
10617 #endif
@@ -10694,11 +10719,11 @@
10719 #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
10720 #define OE_SetNull 7 /* Set the foreign key value to NULL */
10721 #define OE_SetDflt 8 /* Set the foreign key value to its default */
10722 #define OE_Cascade 9 /* Cascade the changes */
10723
10724 #define OE_Default 10 /* Do whatever the default action is */
10725
10726
10727 /*
10728 ** An instance of the following structure is passed as the first
10729 ** argument to sqlite3VdbeKeyCompare and is used to control the
@@ -10781,10 +10806,11 @@
10806 Schema *pSchema; /* Schema containing this index */
10807 u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
10808 char **azColl; /* Array of collation sequence names for index */
10809 Expr *pPartIdxWhere; /* WHERE clause for partial indices */
10810 int tnum; /* DB Page containing root of this index */
10811 LogEst szIdxRow; /* Estimated average row size in bytes */
10812 u16 nColumn; /* Number of columns in table used by this index */
10813 u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
10814 unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
10815 unsigned bUnordered:1; /* Use this index for == or IN queries only */
10816 unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
@@ -11636,10 +11662,11 @@
11662 */
11663 typedef struct DbFixer DbFixer;
11664 struct DbFixer {
11665 Parse *pParse; /* The parsing context. Error messages written here */
11666 Schema *pSchema; /* Fix items to this schema */
11667 int bVarOnly; /* Check for variable references only */
11668 const char *zDb; /* Make sure all objects are contained in this database */
11669 const char *zType; /* Type of the container - used for error messages */
11670 const Token *pName; /* Name of the container - used for error messages */
11671 };
11672
@@ -12174,11 +12201,11 @@
12201 # define sqlite3AuthContextPush(a,b,c)
12202 # define sqlite3AuthContextPop(a) ((void)(a))
12203 #endif
12204 SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
12205 SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
12206 SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
12207 SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
12208 SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
12209 SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
12210 SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
12211 SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
@@ -12186,10 +12213,16 @@
12213 SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
12214 SQLITE_PRIVATE int sqlite3Atoi(const char*);
12215 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
12216 SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
12217 SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
12218 SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
12219 SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
12220 #ifndef SQLITE_OMIT_VIRTUALTABLE
12221 SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
12222 #endif
12223 SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
12224
12225 /*
12226 ** Routines to read and write variable-length integers. These used to
12227 ** be defined locally, but now we use the varint routines in the util.c
12228 ** file. Code should use the MACRO forms below, as the Varint32 versions
@@ -12302,11 +12335,11 @@
12335 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
12336 SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
12337 SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
12338 SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
12339 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
12340 SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
12341 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
12342 SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
12343 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
12344 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
12345 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -12435,14 +12468,14 @@
12468 SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
12469 SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
12470 SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
12471 #else
12472 #define sqlite3FkActions(a,b,c,d,e,f)
12473 #define sqlite3FkCheck(a,b,c,d,e,f)
12474 #define sqlite3FkDropTable(a,b,c)
12475 #define sqlite3FkOldmask(a,b) 0
12476 #define sqlite3FkRequired(a,b,c,d) 0
12477 #endif
12478 #ifndef SQLITE_OMIT_FOREIGN_KEY
12479 SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
12480 SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
12481 #else
@@ -14397,10 +14430,14 @@
14430 ** is available. This routine returns 0 on success and
14431 ** non-zero on any kind of error.
14432 **
14433 ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
14434 ** routine will always fail.
14435 **
14436 ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
14437 ** library function localtime_r() is used to assist in the calculation of
14438 ** local time.
14439 */
14440 static int osLocaltime(time_t *t, struct tm *pTm){
14441 int rc;
14442 #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
14443 && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
@@ -14453,10 +14490,15 @@
14490 memset(&sLocal, 0, sizeof(sLocal));
14491
14492 x = *p;
14493 computeYMD_HMS(&x);
14494 if( x.Y<1971 || x.Y>=2038 ){
14495 /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
14496 ** works for years between 1970 and 2037. For dates outside this range,
14497 ** SQLite attempts to map the year into an equivalent year within this
14498 ** range, do the calculation, then map the year back.
14499 */
14500 x.Y = 2000;
14501 x.M = 1;
14502 x.D = 1;
14503 x.h = 0;
14504 x.m = 0;
@@ -22387,10 +22429,87 @@
22429 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
22430 if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
22431 }
22432 }
22433 #endif
22434
22435 /*
22436 ** Find (an approximate) sum of two LogEst values. This computation is
22437 ** not a simple "+" operator because LogEst is stored as a logarithmic
22438 ** value.
22439 **
22440 */
22441 SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
22442 static const unsigned char x[] = {
22443 10, 10, /* 0,1 */
22444 9, 9, /* 2,3 */
22445 8, 8, /* 4,5 */
22446 7, 7, 7, /* 6,7,8 */
22447 6, 6, 6, /* 9,10,11 */
22448 5, 5, 5, /* 12-14 */
22449 4, 4, 4, 4, /* 15-18 */
22450 3, 3, 3, 3, 3, 3, /* 19-24 */
22451 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
22452 };
22453 if( a>=b ){
22454 if( a>b+49 ) return a;
22455 if( a>b+31 ) return a+1;
22456 return a+x[a-b];
22457 }else{
22458 if( b>a+49 ) return b;
22459 if( b>a+31 ) return b+1;
22460 return b+x[b-a];
22461 }
22462 }
22463
22464 /*
22465 ** Convert an integer into a LogEst. In other words, compute a
22466 ** good approximatation for 10*log2(x).
22467 */
22468 SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
22469 static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
22470 LogEst y = 40;
22471 if( x<8 ){
22472 if( x<2 ) return 0;
22473 while( x<8 ){ y -= 10; x <<= 1; }
22474 }else{
22475 while( x>255 ){ y += 40; x >>= 4; }
22476 while( x>15 ){ y += 10; x >>= 1; }
22477 }
22478 return a[x&7] + y - 10;
22479 }
22480
22481 #ifndef SQLITE_OMIT_VIRTUALTABLE
22482 /*
22483 ** Convert a double into a LogEst
22484 ** In other words, compute an approximation for 10*log2(x).
22485 */
22486 SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
22487 u64 a;
22488 LogEst e;
22489 assert( sizeof(x)==8 && sizeof(a)==8 );
22490 if( x<=1 ) return 0;
22491 if( x<=2000000000 ) return sqlite3LogEst((u64)x);
22492 memcpy(&a, &x, 8);
22493 e = (a>>52) - 1022;
22494 return e*10;
22495 }
22496 #endif /* SQLITE_OMIT_VIRTUALTABLE */
22497
22498 /*
22499 ** Convert a LogEst into an integer.
22500 */
22501 SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
22502 u64 n;
22503 if( x<10 ) return 1;
22504 n = x%10;
22505 x /= 10;
22506 if( n>=5 ) n -= 2;
22507 else if( n>=1 ) n -= 1;
22508 if( x>=3 ) return (n+8)<<(x-3);
22509 return (n+8)>>(3-x);
22510 }
22511
22512 /************** End of util.c ************************************************/
22513 /************** Begin file hash.c ********************************************/
22514 /*
22515 ** 2001 September 22
@@ -31382,11 +31501,11 @@
31501 #endif
31502
31503 #define osGetVersionExA ((BOOL(WINAPI*)( \
31504 LPOSVERSIONINFOA))aSyscall[34].pCurrent)
31505
31506 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
31507 { "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
31508 #else
31509 { "GetVersionExW", (SYSCALL)0, 0 },
31510 #endif
31511
@@ -32896,12 +33015,11 @@
33015 #endif
33016 assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
33017 OSTRACE(("CLOSE file=%p\n", pFile->h));
33018
33019 #if SQLITE_MAX_MMAP_SIZE>0
33020 winUnmapfile(pFile);
 
33021 #endif
33022
33023 do{
33024 rc = osCloseHandle(pFile->h);
33025 /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -33703,11 +33821,11 @@
33821 }
33822 *(i64*)pArg = pFile->mmapSizeMax;
33823 if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
33824 pFile->mmapSizeMax = newLimit;
33825 if( pFile->mmapSize>0 ){
33826 winUnmapfile(pFile);
33827 rc = winMapfile(pFile, -1);
33828 }
33829 }
33830 OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
33831 return rc;
@@ -33920,11 +34038,11 @@
34038 osGetCurrentProcessId(), deleteFlag));
34039 pp = &winShmNodeList;
34040 while( (p = *pp)!=0 ){
34041 if( p->nRef==0 ){
34042 int i;
34043 if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
34044 for(i=0; i<p->nRegion; i++){
34045 BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
34046 OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
34047 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
34048 UNUSED_VARIABLE_VALUE(bRc);
@@ -34773,10 +34891,11 @@
34891 ** API prior to using it.
34892 */
34893 if( winIsDriveLetterAndColon(zDir) ){
34894 zConverted = winConvertFromUtf8Filename(zDir);
34895 if( !zConverted ){
34896 sqlite3_free(zBuf);
34897 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34898 return SQLITE_IOERR_NOMEM;
34899 }
34900 if( winIsDir(zConverted) ){
34901 sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir);
@@ -34785,17 +34904,19 @@
34904 }
34905 sqlite3_free(zConverted);
34906 }else{
34907 zConverted = sqlite3MallocZero( nBuf+1 );
34908 if( !zConverted ){
34909 sqlite3_free(zBuf);
34910 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34911 return SQLITE_IOERR_NOMEM;
34912 }
34913 if( cygwin_conv_path(
34914 osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
34915 zConverted, nBuf+1)<0 ){
34916 sqlite3_free(zConverted);
34917 sqlite3_free(zBuf);
34918 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
34919 return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
34920 "winGetTempname1", zDir);
34921 }
34922 if( winIsDir(zConverted) ){
@@ -34805,10 +34926,11 @@
34926 */
34927 if( osIsNT() ){
34928 char *zUtf8 = winUnicodeToUtf8(zConverted);
34929 if( !zUtf8 ){
34930 sqlite3_free(zConverted);
34931 sqlite3_free(zBuf);
34932 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
34933 return SQLITE_IOERR_NOMEM;
34934 }
34935 sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8);
34936 sqlite3_free(zUtf8);
@@ -34820,11 +34942,10 @@
34942 break;
34943 }
34944 }
34945 sqlite3_free(zConverted);
34946 }
 
34947 }
34948 }
34949 #elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
34950 else if( osIsNT() ){
34951 char *zMulti;
@@ -35190,13 +35311,13 @@
35311 pFile->zDeleteOnClose = zConverted;
35312 }else
35313 #endif
35314 {
35315 sqlite3_free(zConverted);
 
35316 }
35317
35318 sqlite3_free(zTmpname);
35319 pFile->pMethod = &winIoMethod;
35320 pFile->pVfs = pVfs;
35321 pFile->h = h;
35322 if( isReadonly ){
35323 pFile->ctrlFlags |= WINFILE_RDONLY;
@@ -48986,17 +49107,17 @@
49107 ** page contain a special header (the "file header") that describes the file.
49108 ** The format of the file header is as follows:
49109 **
49110 ** OFFSET SIZE DESCRIPTION
49111 ** 0 16 Header string: "SQLite format 3\000"
49112 ** 16 2 Page size in bytes. (1 means 65536)
49113 ** 18 1 File format write version
49114 ** 19 1 File format read version
49115 ** 20 1 Bytes of unused space at the end of each page
49116 ** 21 1 Max embedded payload fraction (must be 64)
49117 ** 22 1 Min embedded payload fraction (must be 32)
49118 ** 23 1 Min leaf payload fraction (must be 32)
49119 ** 24 4 File change counter
49120 ** 28 4 Reserved for future use
49121 ** 32 4 First freelist page
49122 ** 36 4 Number of freelist pages in the file
49123 ** 40 60 15 4-byte meta values passed to higher layers
@@ -49006,13 +49127,14 @@
49127 ** 48 4 Size of page cache
49128 ** 52 4 Largest root-page (auto/incr_vacuum)
49129 ** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
49130 ** 60 4 User version
49131 ** 64 4 Incremental vacuum mode
49132 ** 68 4 Application-ID
49133 ** 72 20 unused
49134 ** 92 4 The version-valid-for number
49135 ** 96 4 SQLITE_VERSION_NUMBER
49136 **
49137 ** All of the integer values are big-endian (most significant byte first).
49138 **
49139 ** The file change counter is incremented when the database is changed
49140 ** This counter allows other processes to know when the file has changed
@@ -51922,10 +52044,22 @@
52044 ** MX_CELL_SIZE(pBt) bytes.
52045 */
52046 static void allocateTempSpace(BtShared *pBt){
52047 if( !pBt->pTmpSpace ){
52048 pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
52049
52050 /* One of the uses of pBt->pTmpSpace is to format cells before
52051 ** inserting them into a leaf page (function fillInCell()). If
52052 ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
52053 ** by the various routines that manipulate binary cells. Which
52054 ** can mean that fillInCell() only initializes the first 2 or 3
52055 ** bytes of pTmpSpace, but that the first 4 bytes are copied from
52056 ** it into a database page. This is not actually a problem, but it
52057 ** does cause a valgrind error when the 1 or 2 bytes of unitialized
52058 ** data is passed to system call write(). So to avoid this error,
52059 ** zero the first 4 bytes of temp space here. */
52060 if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4);
52061 }
52062 }
52063
52064 /*
52065 ** Free the pBt->pTmpSpace allocation
@@ -52378,11 +52512,10 @@
52512 pBt->max1bytePayload = (u8)pBt->maxLocal;
52513 }
52514 assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
52515 pBt->pPage1 = pPage1;
52516 pBt->nPage = nPage;
 
52517 return SQLITE_OK;
52518
52519 page1_init_failed:
52520 releasePage(pPage1);
52521 pBt->pPage1 = 0;
@@ -52538,11 +52671,11 @@
52671 ** is requested, this is a no-op.
52672 */
52673 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
52674 goto trans_begun;
52675 }
52676 assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
52677
52678 /* Write transactions are not possible on a read-only database */
52679 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
52680 rc = SQLITE_READONLY;
52681 goto trans_begun;
@@ -60189,11 +60322,13 @@
60322 }
60323
60324 pRec->nField = p->iVal+1;
60325 return &pRec->aMem[p->iVal];
60326 }
60327 #else
60328 UNUSED_PARAMETER(p);
60329 #endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
60330 return sqlite3ValueNew(db);
60331 }
60332
60333 /*
60334 ** Extract a value from the supplied expression in the manner described
@@ -60203,11 +60338,11 @@
60338 ** If pCtx is NULL and an error occurs after the sqlite3_value object
60339 ** has been allocated, it is freed before returning. Or, if pCtx is not
60340 ** NULL, it is assumed that the caller will free any allocated object
60341 ** in all cases.
60342 */
60343 static int valueFromExpr(
60344 sqlite3 *db, /* The database connection */
60345 Expr *pExpr, /* The expression to evaluate */
60346 u8 enc, /* Encoding to use */
60347 u8 affinity, /* Affinity to use */
60348 sqlite3_value **ppVal, /* Write the new value here */
@@ -60360,10 +60495,11 @@
60495 int nVal; /* Bytes of space required for argv[0] */
60496 int nRet;
60497 sqlite3 *db;
60498 u8 *aRet;
60499
60500 UNUSED_PARAMETER( argc );
60501 iSerial = sqlite3VdbeSerialType(argv[0], file_format);
60502 nSerial = sqlite3VarintLen(iSerial);
60503 nVal = sqlite3VdbeSerialTypeLen(iSerial);
60504 db = sqlite3_context_db_handle(context);
60505
@@ -62977,10 +63113,11 @@
63113 }
63114 fclose(out);
63115 }
63116 }
63117 #endif
63118 p->iCurrentTime = 0;
63119 p->magic = VDBE_MAGIC_INIT;
63120 return p->rc & db->errMask;
63121 }
63122
63123 /*
@@ -75299,10 +75436,14 @@
75436 sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
75437 "constant between 0.0 and 1.0");
75438 pNC->nErr++;
75439 }
75440 }else{
75441 /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
75442 ** likelihood(X, 0.0625).
75443 ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
75444 ** likelihood(X,0.0625). */
75445 pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
75446 }
75447 }
75448 }
75449 #ifndef SQLITE_OMIT_AUTHORIZATION
@@ -76082,11 +76223,11 @@
76223 return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
76224 }
76225 #ifndef SQLITE_OMIT_CAST
76226 if( op==TK_CAST ){
76227 assert( !ExprHasProperty(pExpr, EP_IntValue) );
76228 return sqlite3AffinityType(pExpr->u.zToken, 0);
76229 }
76230 #endif
76231 if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
76232 && pExpr->pTab!=0
76233 ){
@@ -78502,11 +78643,11 @@
78643 case TK_CAST: {
78644 /* Expressions of the form: CAST(pLeft AS token) */
78645 int aff, to_op;
78646 inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
78647 assert( !ExprHasProperty(pExpr, EP_IntValue) );
78648 aff = sqlite3AffinityType(pExpr->u.zToken, 0);
78649 to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
78650 assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
78651 assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
78652 assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
78653 assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
@@ -79169,11 +79310,11 @@
79310 }
79311 #ifndef SQLITE_OMIT_CAST
79312 case TK_CAST: {
79313 /* Expressions of the form: CAST(pLeft AS token) */
79314 const char *zAff = "unk";
79315 switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
79316 case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
79317 case SQLITE_AFF_NONE: zAff = "NONE"; break;
79318 case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
79319 case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
79320 case SQLITE_AFF_REAL: zAff = "REAL"; break;
@@ -81173,11 +81314,11 @@
81314 ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
81315 ** created and used by SQLite versions 3.7.9 and later and with
81316 ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
81317 ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
81318 ** version of sqlite_stat3 and is only available when compiled with
81319 ** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
81320 ** not possible to enable both STAT3 and STAT4 at the same time. If they
81321 ** are both enabled, then STAT4 takes precedence.
81322 **
81323 ** For most applications, sqlite_stat1 provides all the statisics required
81324 ** for the query planner to make good choices.
@@ -81249,16 +81390,16 @@
81390 **
81391 ** The sqlite_stat4 table contains multiple entries for each index.
81392 ** The idx column names the index and the tbl column is the table of the
81393 ** index. If the idx and tbl columns are the same, then the sample is
81394 ** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
81395 ** binary encoding of a key from the index. The nEq column is a
81396 ** list of integers. The first integer is the approximate number
81397 ** of entries in the index whose left-most column exactly matches
81398 ** the left-most column of the sample. The second integer in nEq
81399 ** is the approximate number of entries in the index where the
81400 ** first two columns match the first two columns of the sample.
81401 ** And so forth. nLt is another list of integers that show the approximate
81402 ** number of entries that are strictly less than the sample. The first
81403 ** integer in nLt contains the number of entries in the index where the
81404 ** left-most column is less than the left-most column of the sample.
81405 ** The K-th integer in the nLt entry is the number of index entries
@@ -81585,11 +81726,11 @@
81726 }
81727
81728 /*
81729 ** Copy the contents of object (*pFrom) into (*pTo).
81730 */
81731 static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
81732 pTo->iRowid = pFrom->iRowid;
81733 pTo->isPSample = pFrom->isPSample;
81734 pTo->iCol = pFrom->iCol;
81735 pTo->iHash = pFrom->iHash;
81736 memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
@@ -81730,10 +81871,15 @@
81871 ){
81872 sampleInsert(p, &p->current, 0);
81873 }
81874 }
81875 #endif
81876
81877 #ifndef SQLITE_ENABLE_STAT3_OR_STAT4
81878 UNUSED_PARAMETER( p );
81879 UNUSED_PARAMETER( iChng );
81880 #endif
81881 }
81882
81883 /*
81884 ** Implementation of the stat_push SQL function: stat_push(P,R,C)
81885 ** Arguments:
@@ -81755,10 +81901,12 @@
81901
81902 /* The three function arguments */
81903 Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
81904 int iChng = sqlite3_value_int(argv[1]);
81905
81906 UNUSED_PARAMETER( argc );
81907 UNUSED_PARAMETER( context );
81908 assert( p->nCol>1 ); /* Includes rowid field */
81909 assert( iChng<p->nCol );
81910
81911 if( p->nRow==0 ){
81912 /* This is the first call to this function. Do initialization. */
@@ -81884,16 +82032,16 @@
82032 if( zRet==0 ){
82033 sqlite3_result_error_nomem(context);
82034 return;
82035 }
82036
82037 sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
82038 z = zRet + sqlite3Strlen30(zRet);
82039 for(i=0; i<(p->nCol-1); i++){
82040 u64 nDistinct = p->current.anDLt[i] + 1;
82041 u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
82042 sqlite3_snprintf(24, z, " %llu", iVal);
82043 z += sqlite3Strlen30(z);
82044 assert( p->current.anEq[i] );
82045 }
82046 assert( z[0]=='\0' && z>zRet );
82047
@@ -81930,20 +82078,23 @@
82078 sqlite3_result_error_nomem(context);
82079 }else{
82080 int i;
82081 char *z = zRet;
82082 for(i=0; i<p->nCol; i++){
82083 sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
82084 z += sqlite3Strlen30(z);
82085 }
82086 assert( z[0]=='\0' && z>zRet );
82087 z[-1] = '\0';
82088 sqlite3_result_text(context, zRet, -1, sqlite3_free);
82089 }
82090 }
82091 }
82092 #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
82093 #ifndef SQLITE_DEBUG
82094 UNUSED_PARAMETER( argc );
82095 #endif
82096 }
82097 static const FuncDef statGetFuncdef = {
82098 1+IsStat34, /* nArg */
82099 SQLITE_UTF8, /* funcFlags */
82100 0, /* pUserData */
@@ -81958,12 +82109,14 @@
82109
82110 static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
82111 assert( regOut!=regStat4 && regOut!=regStat4+1 );
82112 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
82113 sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
82114 #elif SQLITE_DEBUG
82115 assert( iParam==STAT_GET_STAT1 );
82116 #else
82117 UNUSED_PARAMETER( iParam );
82118 #endif
82119 sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
82120 sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
82121 sqlite3VdbeChangeP5(v, 1 + IsStat34);
82122 }
@@ -82391,22 +82544,20 @@
82544 ** The first argument points to a nul-terminated string containing a
82545 ** list of space separated integers. Read the first nOut of these into
82546 ** the array aOut[].
82547 */
82548 static void decodeIntArray(
82549 char *zIntArray, /* String containing int array to decode */
82550 int nOut, /* Number of slots in aOut[] */
82551 tRowcnt *aOut, /* Store integers here */
82552 Index *pIndex /* Handle extra flags for this index, if not NULL */
82553 ){
82554 char *z = zIntArray;
82555 int c;
82556 int i;
82557 tRowcnt v;
82558
 
 
82559 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
82560 if( z==0 ) z = "";
82561 #else
82562 if( NEVER(z==0) ) z = "";
82563 #endif
@@ -82417,12 +82568,23 @@
82568 z++;
82569 }
82570 aOut[i] = v;
82571 if( *z==' ' ) z++;
82572 }
82573 #ifndef SQLITE_ENABLE_STAT3_OR_STAT4
82574 assert( pIndex!=0 );
82575 #else
82576 if( pIndex )
82577 #endif
82578 {
82579 if( strcmp(z, "unordered")==0 ){
82580 pIndex->bUnordered = 1;
82581 }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
82582 int v32 = 0;
82583 sqlite3GetInt32(z+3, &v32);
82584 pIndex->szIdxRow = sqlite3LogEst(v32);
82585 }
82586 }
82587 }
82588
82589 /*
82590 ** This callback is invoked once for each index when reading the
@@ -82457,16 +82619,17 @@
82619 pIndex = 0;
82620 }
82621 z = argv[2];
82622
82623 if( pIndex ){
82624 decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
 
82625 if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
 
82626 }else{
82627 Index fakeIdx;
82628 fakeIdx.szIdxRow = pTable->szTabRow;
82629 decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
82630 pTable->szTabRow = fakeIdx.szIdxRow;
82631 }
82632
82633 return 0;
82634 }
82635
@@ -83185,32 +83348,28 @@
83348 #endif /* SQLITE_OMIT_ATTACH */
83349
83350 /*
83351 ** Initialize a DbFixer structure. This routine must be called prior
83352 ** to passing the structure to one of the sqliteFixAAAA() routines below.
 
 
 
83353 */
83354 SQLITE_PRIVATE void sqlite3FixInit(
83355 DbFixer *pFix, /* The fixer to be initialized */
83356 Parse *pParse, /* Error messages will be written here */
83357 int iDb, /* This is the database that must be used */
83358 const char *zType, /* "view", "trigger", or "index" */
83359 const Token *pName /* Name of the view, trigger, or index */
83360 ){
83361 sqlite3 *db;
83362
 
83363 db = pParse->db;
83364 assert( db->nDb>iDb );
83365 pFix->pParse = pParse;
83366 pFix->zDb = db->aDb[iDb].zName;
83367 pFix->pSchema = db->aDb[iDb].pSchema;
83368 pFix->zType = zType;
83369 pFix->pName = pName;
83370 pFix->bVarOnly = (iDb==1);
83371 }
83372
83373 /*
83374 ** The following set of routines walk through the parse tree and assign
83375 ** a specific database to all table references where the database name
@@ -83234,19 +83393,21 @@
83393 struct SrcList_item *pItem;
83394
83395 if( NEVER(pList==0) ) return 0;
83396 zDb = pFix->zDb;
83397 for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
83398 if( pFix->bVarOnly==0 ){
83399 if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
83400 sqlite3ErrorMsg(pFix->pParse,
83401 "%s %T cannot reference objects in database %s",
83402 pFix->zType, pFix->pName, pItem->zDatabase);
83403 return 1;
83404 }
83405 sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
83406 pItem->zDatabase = 0;
83407 pItem->pSchema = pFix->pSchema;
83408 }
83409 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
83410 if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
83411 if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
83412 #endif
83413 }
@@ -83264,13 +83425,25 @@
83425 if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
83426 return 1;
83427 }
83428 if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
83429 return 1;
83430 }
83431 if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
83432 return 1;
83433 }
83434 if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
83435 return 1;
83436 }
83437 if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
83438 return 1;
83439 }
83440 if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
83441 return 1;
83442 }
83443 if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
83444 return 1;
83445 }
83446 pSelect = pSelect->pPrior;
83447 }
83448 return 0;
83449 }
@@ -83277,10 +83450,18 @@
83450 SQLITE_PRIVATE int sqlite3FixExpr(
83451 DbFixer *pFix, /* Context of the fixation */
83452 Expr *pExpr /* The expression to be fixed to one database */
83453 ){
83454 while( pExpr ){
83455 if( pExpr->op==TK_VARIABLE ){
83456 if( pFix->pParse->db->init.busy ){
83457 pExpr->op = TK_NULL;
83458 }else{
83459 sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
83460 return 1;
83461 }
83462 }
83463 if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
83464 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
83465 if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
83466 }else{
83467 if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
@@ -84460,11 +84641,11 @@
84641 }
84642 pTable->zName = zName;
84643 pTable->iPKey = -1;
84644 pTable->pSchema = db->aDb[iDb].pSchema;
84645 pTable->nRef = 1;
84646 pTable->nRowEst = 1048576;
84647 assert( pParse->pNewTable==0 );
84648 pParse->pNewTable = pTable;
84649
84650 /* If this is the magic sqlite_sequence table used by autoincrement,
84651 ** then record a pointer to this table in the main database structure
@@ -84607,10 +84788,11 @@
84788 /* If there is no type specified, columns have the default affinity
84789 ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
84790 ** be called next to set pCol->affinity correctly.
84791 */
84792 pCol->affinity = SQLITE_AFF_NONE;
84793 pCol->szEst = 1;
84794 p->nCol++;
84795 }
84796
84797 /*
84798 ** This routine is called by the parser while in the middle of
@@ -84648,26 +84830,30 @@
84830 ** 'DOUB' | SQLITE_AFF_REAL
84831 **
84832 ** If none of the substrings in the above table are found,
84833 ** SQLITE_AFF_NUMERIC is returned.
84834 */
84835 SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
84836 u32 h = 0;
84837 char aff = SQLITE_AFF_NUMERIC;
84838 const char *zChar = 0;
84839
84840 if( zIn==0 ) return aff;
84841 while( zIn[0] ){
84842 h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
84843 zIn++;
84844 if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
84845 aff = SQLITE_AFF_TEXT;
84846 zChar = zIn;
84847 }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
84848 aff = SQLITE_AFF_TEXT;
84849 }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
84850 aff = SQLITE_AFF_TEXT;
84851 }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
84852 && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
84853 aff = SQLITE_AFF_NONE;
84854 if( zIn[0]=='(' ) zChar = zIn;
84855 #ifndef SQLITE_OMIT_FLOATING_POINT
84856 }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
84857 && aff==SQLITE_AFF_NUMERIC ){
84858 aff = SQLITE_AFF_REAL;
84859 }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
@@ -84681,10 +84867,32 @@
84867 aff = SQLITE_AFF_INTEGER;
84868 break;
84869 }
84870 }
84871
84872 /* If pszEst is not NULL, store an estimate of the field size. The
84873 ** estimate is scaled so that the size of an integer is 1. */
84874 if( pszEst ){
84875 *pszEst = 1; /* default size is approx 4 bytes */
84876 if( aff<=SQLITE_AFF_NONE ){
84877 if( zChar ){
84878 while( zChar[0] ){
84879 if( sqlite3Isdigit(zChar[0]) ){
84880 int v = 0;
84881 sqlite3GetInt32(zChar, &v);
84882 v = v/4 + 1;
84883 if( v>255 ) v = 255;
84884 *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
84885 break;
84886 }
84887 zChar++;
84888 }
84889 }else{
84890 *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
84891 }
84892 }
84893 }
84894 return aff;
84895 }
84896
84897 /*
84898 ** This routine is called by the parser while in the middle of
@@ -84702,11 +84910,11 @@
84910 p = pParse->pNewTable;
84911 if( p==0 || NEVER(p->nCol<1) ) return;
84912 pCol = &p->aCol[p->nCol-1];
84913 assert( pCol->zType==0 );
84914 pCol->zType = sqlite3NameFromToken(pParse->db, pType);
84915 pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
84916 }
84917
84918 /*
84919 ** The expression is the default value for the most recently added column
84920 ** of the table currently under construction.
@@ -85050,18 +85258,46 @@
85258 testcase( pCol->affinity==SQLITE_AFF_REAL );
85259
85260 zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
85261 len = sqlite3Strlen30(zType);
85262 assert( pCol->affinity==SQLITE_AFF_NONE
85263 || pCol->affinity==sqlite3AffinityType(zType, 0) );
85264 memcpy(&zStmt[k], zType, len);
85265 k += len;
85266 assert( k<=n );
85267 }
85268 sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
85269 return zStmt;
85270 }
85271
85272 /*
85273 ** Estimate the total row width for a table.
85274 */
85275 static void estimateTableWidth(Table *pTab){
85276 unsigned wTable = 0;
85277 const Column *pTabCol;
85278 int i;
85279 for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
85280 wTable += pTabCol->szEst;
85281 }
85282 if( pTab->iPKey<0 ) wTable++;
85283 pTab->szTabRow = sqlite3LogEst(wTable*4);
85284 }
85285
85286 /*
85287 ** Estimate the average size of a row for an index.
85288 */
85289 static void estimateIndexWidth(Index *pIdx){
85290 unsigned wIndex = 1;
85291 int i;
85292 const Column *aCol = pIdx->pTable->aCol;
85293 for(i=0; i<pIdx->nColumn; i++){
85294 assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
85295 wIndex += aCol[pIdx->aiColumn[i]].szEst;
85296 }
85297 pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
85298 }
85299
85300 /*
85301 ** This routine is called to report the final ")" that terminates
85302 ** a CREATE TABLE statement.
85303 **
@@ -85085,13 +85321,14 @@
85321 Parse *pParse, /* Parse context */
85322 Token *pCons, /* The ',' token after the last column defn. */
85323 Token *pEnd, /* The final ')' token in the CREATE TABLE */
85324 Select *pSelect /* Select from a "CREATE ... AS SELECT" */
85325 ){
85326 Table *p; /* The new table */
85327 sqlite3 *db = pParse->db; /* The database connection */
85328 int iDb; /* Database in which the table lives */
85329 Index *pIdx; /* An implied index of the table */
85330
85331 if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
85332 return;
85333 }
85334 p = pParse->pNewTable;
@@ -85106,10 +85343,16 @@
85343 */
85344 if( p->pCheck ){
85345 sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
85346 }
85347 #endif /* !defined(SQLITE_OMIT_CHECK) */
85348
85349 /* Estimate the average row size for the table and for all implied indices */
85350 estimateTableWidth(p);
85351 for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
85352 estimateIndexWidth(pIdx);
85353 }
85354
85355 /* If the db->init.busy is 1 it means we are reading the SQL off the
85356 ** "sqlite_master" or "sqlite_temp_master" table on the disk.
85357 ** So do not write to the disk again. Extract the root page number
85358 ** for the table from the db->init.newTnum field. (The page number
@@ -85303,13 +85546,12 @@
85546 sqlite3SelectDelete(db, pSelect);
85547 return;
85548 }
85549 sqlite3TwoPartName(pParse, pName1, pName2, &pName);
85550 iDb = sqlite3SchemaToIndex(db, p->pSchema);
85551 sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
85552 if( sqlite3FixSelect(&sFix, pSelect) ){
 
85553 sqlite3SelectDelete(db, pSelect);
85554 return;
85555 }
85556
85557 /* Make a copy of the entire SELECT statement that defines the view.
@@ -86066,13 +86308,14 @@
86308 sqlite3 *db = pParse->db;
86309 Db *pDb; /* The specific table containing the indexed database */
86310 int iDb; /* Index of the database that is being written */
86311 Token *pName = 0; /* Unqualified name of the index to create */
86312 struct ExprList_item *pListItem; /* For looping over pList */
86313 const Column *pTabCol; /* A column in the table */
86314 int nCol; /* Number of columns */
86315 int nExtra = 0; /* Space allocated for zExtra[] */
86316 char *zExtra; /* Extra space after the Index object */
86317
86318 assert( pParse->nErr==0 ); /* Never called with prior errors */
86319 if( db->mallocFailed || IN_DECLARE_VTAB ){
86320 goto exit_create_index;
86321 }
@@ -86105,13 +86348,12 @@
86348 iDb = 1;
86349 }
86350 }
86351 #endif
86352
86353 sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
86354 if( sqlite3FixSrcList(&sFix, pTblName) ){
 
86355 /* Because the parser constructs pTblName from a single identifier,
86356 ** sqlite3FixSrcList can never fail. */
86357 assert(0);
86358 }
86359 pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
@@ -86296,11 +86538,10 @@
86538 ** same column more than once cannot be an error because that would
86539 ** break backwards compatibility - it needs to be a warning.
86540 */
86541 for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
86542 const char *zColName = pListItem->zName;
 
86543 int requestedSortOrder;
86544 char *zColl; /* Collation sequence name */
86545
86546 for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
86547 if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -86333,10 +86574,11 @@
86574 requestedSortOrder = pListItem->sortOrder & sortOrderMask;
86575 pIndex->aSortOrder[i] = (u8)requestedSortOrder;
86576 if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
86577 }
86578 sqlite3DefaultRowEst(pIndex);
86579 if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
86580
86581 if( pTab==pParse->pNewTable ){
86582 /* This routine has been called to create an automatic index as a
86583 ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
86584 ** a PRIMARY KEY or UNIQUE clause following the column definitions.
@@ -88238,10 +88480,11 @@
88480 ** API function sqlite3_count_changes) to be set incorrectly. */
88481 if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
88482 && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
88483 ){
88484 assert( !isView );
88485 sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
88486 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
88487 pTab->zName, P4_STATIC);
88488 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
88489 assert( pIdx->pSchema==pTab->pSchema );
88490 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
@@ -90943,11 +91186,11 @@
91186 ** generating any VDBE code. If one can be found, then jump over
91187 ** the entire DELETE if there are no outstanding deferred constraints
91188 ** when this statement is run. */
91189 FKey *p;
91190 for(p=pTab->pFKey; p; p=p->pNextFrom){
91191 if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
91192 }
91193 if( !p ) return;
91194 iSkip = sqlite3VdbeMakeLabel(v);
91195 sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
91196 }
@@ -90957,15 +91200,22 @@
91200 pParse->disableTriggers = 0;
91201
91202 /* If the DELETE has generated immediate foreign key constraint
91203 ** violations, halt the VDBE and return an error at this point, before
91204 ** any modifications to the schema are made. This is because statement
91205 ** transactions are not able to rollback schema changes.
91206 **
91207 ** If the SQLITE_DeferFKs flag is set, then this is not required, as
91208 ** the statement transaction will not be rolled back even if FK
91209 ** constraints are violated.
91210 */
91211 if( (db->flags & SQLITE_DeferFKs)==0 ){
91212 sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
91213 sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
91214 OE_Abort, "foreign key constraint failed", P4_STATIC
91215 );
91216 }
91217
91218 if( iSkip ){
91219 sqlite3VdbeResolveLabel(v, iSkip);
91220 }
91221 }
@@ -93487,10 +93737,11 @@
93737 (char*)pKey, P4_KEYINFO_HANDOFF);
93738 VdbeComment((v, "%s", pSrcIdx->zName));
93739 pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
93740 sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
93741 (char*)pKey, P4_KEYINFO_HANDOFF);
93742 sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
93743 VdbeComment((v, "%s", pDestIdx->zName));
93744 addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
93745 sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
93746 sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
93747 sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
@@ -94962,193 +95213,382 @@
95213 #define PragTyp_MMAP_SIZE 23
95214 #define PragTyp_PAGE_SIZE 24
95215 #define PragTyp_SECURE_DELETE 25
95216 #define PragTyp_SHRINK_MEMORY 26
95217 #define PragTyp_SOFT_HEAP_LIMIT 27
95218 #define PragTyp_STATS 28
95219 #define PragTyp_SYNCHRONOUS 29
95220 #define PragTyp_TABLE_INFO 30
95221 #define PragTyp_TEMP_STORE 31
95222 #define PragTyp_TEMP_STORE_DIRECTORY 32
95223 #define PragTyp_WAL_AUTOCHECKPOINT 33
95224 #define PragTyp_WAL_CHECKPOINT 34
95225 #define PragTyp_ACTIVATE_EXTENSIONS 35
95226 #define PragTyp_HEXKEY 36
95227 #define PragTyp_KEY 37
95228 #define PragTyp_REKEY 38
95229 #define PragTyp_LOCK_STATUS 39
95230 #define PragTyp_PARSER_TRACE 40
95231 #define PragFlag_NeedSchema 0x01
95232 static const struct sPragmaNames {
95233 const char *const zName; /* Name of pragma */
95234 u8 ePragTyp; /* PragTyp_XXX value */
95235 u8 mPragFlag; /* Zero or more PragFlag_XXX values */
95236 u32 iArg; /* Extra argument */
95237 } aPragmaNames[] = {
95238 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
95239 { /* zName: */ "activate_extensions",
95240 /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
95241 /* ePragFlag: */ 0,
95242 /* iArg: */ 0 },
95243 #endif
95244 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95245 { /* zName: */ "application_id",
95246 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95247 /* ePragFlag: */ 0,
95248 /* iArg: */ 0 },
95249 #endif
95250 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95251 { /* zName: */ "auto_vacuum",
95252 /* ePragTyp: */ PragTyp_AUTO_VACUUM,
95253 /* ePragFlag: */ PragFlag_NeedSchema,
95254 /* iArg: */ 0 },
95255 #endif
95256 #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
95257 { /* zName: */ "automatic_index",
95258 /* ePragTyp: */ PragTyp_FLAG,
95259 /* ePragFlag: */ 0,
95260 /* iArg: */ SQLITE_AutoIndex },
95261 #endif
95262 { /* zName: */ "busy_timeout",
95263 /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
95264 /* ePragFlag: */ 0,
95265 /* iArg: */ 0 },
95266 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95267 { /* zName: */ "cache_size",
95268 /* ePragTyp: */ PragTyp_CACHE_SIZE,
95269 /* ePragFlag: */ PragFlag_NeedSchema,
95270 /* iArg: */ 0 },
95271 #endif
95272 { /* zName: */ "cache_spill",
95273 /* ePragTyp: */ PragTyp_FLAG,
95274 /* ePragFlag: */ 0,
95275 /* iArg: */ SQLITE_CacheSpill },
95276 { /* zName: */ "case_sensitive_like",
95277 /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
95278 /* ePragFlag: */ 0,
95279 /* iArg: */ 0 },
95280 { /* zName: */ "checkpoint_fullfsync",
95281 /* ePragTyp: */ PragTyp_FLAG,
95282 /* ePragFlag: */ 0,
95283 /* iArg: */ SQLITE_CkptFullFSync },
95284 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95285 { /* zName: */ "collation_list",
95286 /* ePragTyp: */ PragTyp_COLLATION_LIST,
95287 /* ePragFlag: */ 0,
95288 /* iArg: */ 0 },
95289 #endif
95290 #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
95291 { /* zName: */ "compile_options",
95292 /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
95293 /* ePragFlag: */ 0,
95294 /* iArg: */ 0 },
95295 #endif
95296 { /* zName: */ "count_changes",
95297 /* ePragTyp: */ PragTyp_FLAG,
95298 /* ePragFlag: */ 0,
95299 /* iArg: */ SQLITE_CountRows },
95300 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
95301 { /* zName: */ "data_store_directory",
95302 /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
95303 /* ePragFlag: */ 0,
95304 /* iArg: */ 0 },
95305 #endif
95306 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95307 { /* zName: */ "database_list",
95308 /* ePragTyp: */ PragTyp_DATABASE_LIST,
95309 /* ePragFlag: */ PragFlag_NeedSchema,
95310 /* iArg: */ 0 },
95311 #endif
95312 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
95313 { /* zName: */ "default_cache_size",
95314 /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
95315 /* ePragFlag: */ PragFlag_NeedSchema,
95316 /* iArg: */ 0 },
95317 #endif
95318 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95319 { /* zName: */ "defer_foreign_keys",
95320 /* ePragTyp: */ PragTyp_FLAG,
95321 /* ePragFlag: */ 0,
95322 /* iArg: */ SQLITE_DeferFKs },
95323 #endif
95324 { /* zName: */ "empty_result_callbacks",
95325 /* ePragTyp: */ PragTyp_FLAG,
95326 /* ePragFlag: */ 0,
95327 /* iArg: */ SQLITE_NullCallback },
95328 #if !defined(SQLITE_OMIT_UTF16)
95329 { /* zName: */ "encoding",
95330 /* ePragTyp: */ PragTyp_ENCODING,
95331 /* ePragFlag: */ 0,
95332 /* iArg: */ 0 },
95333 #endif
95334 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95335 { /* zName: */ "foreign_key_check",
95336 /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
95337 /* ePragFlag: */ PragFlag_NeedSchema,
95338 /* iArg: */ 0 },
95339 #endif
95340 #if !defined(SQLITE_OMIT_FOREIGN_KEY)
95341 { /* zName: */ "foreign_key_list",
95342 /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
95343 /* ePragFlag: */ PragFlag_NeedSchema,
95344 /* iArg: */ 0 },
95345 #endif
95346 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
95347 { /* zName: */ "foreign_keys",
95348 /* ePragTyp: */ PragTyp_FLAG,
95349 /* ePragFlag: */ 0,
95350 /* iArg: */ SQLITE_ForeignKeys },
95351 #endif
95352 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95353 { /* zName: */ "freelist_count",
95354 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95355 /* ePragFlag: */ 0,
95356 /* iArg: */ 0 },
95357 #endif
95358 { /* zName: */ "full_column_names",
95359 /* ePragTyp: */ PragTyp_FLAG,
95360 /* ePragFlag: */ 0,
95361 /* iArg: */ SQLITE_FullColNames },
95362 { /* zName: */ "fullfsync",
95363 /* ePragTyp: */ PragTyp_FLAG,
95364 /* ePragFlag: */ 0,
95365 /* iArg: */ SQLITE_FullFSync },
95366 #if defined(SQLITE_HAS_CODEC)
95367 { /* zName: */ "hexkey",
95368 /* ePragTyp: */ PragTyp_HEXKEY,
95369 /* ePragFlag: */ 0,
95370 /* iArg: */ 0 },
95371 { /* zName: */ "hexrekey",
95372 /* ePragTyp: */ PragTyp_HEXKEY,
95373 /* ePragFlag: */ 0,
95374 /* iArg: */ 0 },
95375 #endif
95376 #if !defined(SQLITE_OMIT_CHECK)
95377 { /* zName: */ "ignore_check_constraints",
95378 /* ePragTyp: */ PragTyp_FLAG,
95379 /* ePragFlag: */ 0,
95380 /* iArg: */ SQLITE_IgnoreChecks },
95381 #endif
95382 #if !defined(SQLITE_OMIT_AUTOVACUUM)
95383 { /* zName: */ "incremental_vacuum",
95384 /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
95385 /* ePragFlag: */ PragFlag_NeedSchema,
95386 /* iArg: */ 0 },
95387 #endif
95388 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95389 { /* zName: */ "index_info",
95390 /* ePragTyp: */ PragTyp_INDEX_INFO,
95391 /* ePragFlag: */ PragFlag_NeedSchema,
95392 /* iArg: */ 0 },
95393 { /* zName: */ "index_list",
95394 /* ePragTyp: */ PragTyp_INDEX_LIST,
95395 /* ePragFlag: */ PragFlag_NeedSchema,
95396 /* iArg: */ 0 },
95397 #endif
95398 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95399 { /* zName: */ "integrity_check",
95400 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95401 /* ePragFlag: */ PragFlag_NeedSchema,
95402 /* iArg: */ 0 },
95403 #endif
95404 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95405 { /* zName: */ "journal_mode",
95406 /* ePragTyp: */ PragTyp_JOURNAL_MODE,
95407 /* ePragFlag: */ PragFlag_NeedSchema,
95408 /* iArg: */ 0 },
95409 { /* zName: */ "journal_size_limit",
95410 /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
95411 /* ePragFlag: */ 0,
95412 /* iArg: */ 0 },
95413 #endif
95414 #if defined(SQLITE_HAS_CODEC)
95415 { /* zName: */ "key",
95416 /* ePragTyp: */ PragTyp_KEY,
95417 /* ePragFlag: */ 0,
95418 /* iArg: */ 0 },
95419 #endif
95420 { /* zName: */ "legacy_file_format",
95421 /* ePragTyp: */ PragTyp_FLAG,
95422 /* ePragFlag: */ 0,
95423 /* iArg: */ SQLITE_LegacyFileFmt },
95424 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
95425 { /* zName: */ "lock_proxy_file",
95426 /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
95427 /* ePragFlag: */ 0,
95428 /* iArg: */ 0 },
95429 #endif
95430 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
95431 { /* zName: */ "lock_status",
95432 /* ePragTyp: */ PragTyp_LOCK_STATUS,
95433 /* ePragFlag: */ 0,
95434 /* iArg: */ 0 },
95435 #endif
95436 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95437 { /* zName: */ "locking_mode",
95438 /* ePragTyp: */ PragTyp_LOCKING_MODE,
95439 /* ePragFlag: */ 0,
95440 /* iArg: */ 0 },
95441 { /* zName: */ "max_page_count",
95442 /* ePragTyp: */ PragTyp_PAGE_COUNT,
95443 /* ePragFlag: */ PragFlag_NeedSchema,
95444 /* iArg: */ 0 },
95445 { /* zName: */ "mmap_size",
95446 /* ePragTyp: */ PragTyp_MMAP_SIZE,
95447 /* ePragFlag: */ 0,
95448 /* iArg: */ 0 },
95449 { /* zName: */ "page_count",
95450 /* ePragTyp: */ PragTyp_PAGE_COUNT,
95451 /* ePragFlag: */ PragFlag_NeedSchema,
95452 /* iArg: */ 0 },
95453 { /* zName: */ "page_size",
95454 /* ePragTyp: */ PragTyp_PAGE_SIZE,
95455 /* ePragFlag: */ 0,
95456 /* iArg: */ 0 },
95457 #endif
95458 #if defined(SQLITE_DEBUG)
95459 { /* zName: */ "parser_trace",
95460 /* ePragTyp: */ PragTyp_PARSER_TRACE,
95461 /* ePragFlag: */ 0,
95462 /* iArg: */ 0 },
95463 #endif
95464 { /* zName: */ "query_only",
95465 /* ePragTyp: */ PragTyp_FLAG,
95466 /* ePragFlag: */ 0,
95467 /* iArg: */ SQLITE_QueryOnly },
95468 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
95469 { /* zName: */ "quick_check",
95470 /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
95471 /* ePragFlag: */ PragFlag_NeedSchema,
95472 /* iArg: */ 0 },
95473 #endif
95474 { /* zName: */ "read_uncommitted",
95475 /* ePragTyp: */ PragTyp_FLAG,
95476 /* ePragFlag: */ 0,
95477 /* iArg: */ SQLITE_ReadUncommitted },
95478 { /* zName: */ "recursive_triggers",
95479 /* ePragTyp: */ PragTyp_FLAG,
95480 /* ePragFlag: */ 0,
95481 /* iArg: */ SQLITE_RecTriggers },
95482 #if defined(SQLITE_HAS_CODEC)
95483 { /* zName: */ "rekey",
95484 /* ePragTyp: */ PragTyp_REKEY,
95485 /* ePragFlag: */ 0,
95486 /* iArg: */ 0 },
95487 #endif
95488 { /* zName: */ "reverse_unordered_selects",
95489 /* ePragTyp: */ PragTyp_FLAG,
95490 /* ePragFlag: */ 0,
95491 /* iArg: */ SQLITE_ReverseOrder },
95492 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95493 { /* zName: */ "schema_version",
95494 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95495 /* ePragFlag: */ 0,
95496 /* iArg: */ 0 },
95497 #endif
95498 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95499 { /* zName: */ "secure_delete",
95500 /* ePragTyp: */ PragTyp_SECURE_DELETE,
95501 /* ePragFlag: */ 0,
95502 /* iArg: */ 0 },
95503 #endif
95504 { /* zName: */ "short_column_names",
95505 /* ePragTyp: */ PragTyp_FLAG,
95506 /* ePragFlag: */ 0,
95507 /* iArg: */ SQLITE_ShortColNames },
95508 { /* zName: */ "shrink_memory",
95509 /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
95510 /* ePragFlag: */ 0,
95511 /* iArg: */ 0 },
95512 { /* zName: */ "soft_heap_limit",
95513 /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
95514 /* ePragFlag: */ 0,
95515 /* iArg: */ 0 },
95516 #if defined(SQLITE_DEBUG)
95517 { /* zName: */ "sql_trace",
95518 /* ePragTyp: */ PragTyp_FLAG,
95519 /* ePragFlag: */ 0,
95520 /* iArg: */ SQLITE_SqlTrace },
95521 #endif
95522 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95523 { /* zName: */ "stats",
95524 /* ePragTyp: */ PragTyp_STATS,
95525 /* ePragFlag: */ PragFlag_NeedSchema,
95526 /* iArg: */ 0 },
95527 #endif
95528 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95529 { /* zName: */ "synchronous",
95530 /* ePragTyp: */ PragTyp_SYNCHRONOUS,
95531 /* ePragFlag: */ PragFlag_NeedSchema,
95532 /* iArg: */ 0 },
95533 #endif
95534 #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
95535 { /* zName: */ "table_info",
95536 /* ePragTyp: */ PragTyp_TABLE_INFO,
95537 /* ePragFlag: */ PragFlag_NeedSchema,
95538 /* iArg: */ 0 },
95539 #endif
95540 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
95541 { /* zName: */ "temp_store",
95542 /* ePragTyp: */ PragTyp_TEMP_STORE,
95543 /* ePragFlag: */ 0,
95544 /* iArg: */ 0 },
95545 { /* zName: */ "temp_store_directory",
95546 /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
95547 /* ePragFlag: */ 0,
95548 /* iArg: */ 0 },
95549 #endif
95550 #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
95551 { /* zName: */ "user_version",
95552 /* ePragTyp: */ PragTyp_HEADER_VALUE,
95553 /* ePragFlag: */ 0,
95554 /* iArg: */ 0 },
95555 #endif
95556 #if defined(SQLITE_DEBUG)
95557 { /* zName: */ "vdbe_addoptrace",
95558 /* ePragTyp: */ PragTyp_FLAG,
95559 /* ePragFlag: */ 0,
95560 /* iArg: */ SQLITE_VdbeAddopTrace },
95561 { /* zName: */ "vdbe_debug",
95562 /* ePragTyp: */ PragTyp_FLAG,
95563 /* ePragFlag: */ 0,
95564 /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
95565 { /* zName: */ "vdbe_listing",
95566 /* ePragTyp: */ PragTyp_FLAG,
95567 /* ePragFlag: */ 0,
95568 /* iArg: */ SQLITE_VdbeListing },
95569 { /* zName: */ "vdbe_trace",
95570 /* ePragTyp: */ PragTyp_FLAG,
95571 /* ePragFlag: */ 0,
95572 /* iArg: */ SQLITE_VdbeTrace },
95573 #endif
95574 #if !defined(SQLITE_OMIT_WAL)
95575 { /* zName: */ "wal_autocheckpoint",
95576 /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
95577 /* ePragFlag: */ 0,
95578 /* iArg: */ 0 },
95579 { /* zName: */ "wal_checkpoint",
95580 /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
95581 /* ePragFlag: */ PragFlag_NeedSchema,
95582 /* iArg: */ 0 },
95583 #endif
95584 { /* zName: */ "writable_schema",
95585 /* ePragTyp: */ PragTyp_FLAG,
95586 /* ePragFlag: */ 0,
95587 /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
95588 };
95589 /* Number of pragmas: 56 on by default, 68 total. */
95590 /* End of the automatically generated pragma table.
95591 ***************************************************************************/
95592
95593 /*
95594 ** Interpret the given string as a safety level. Return 0 for OFF,
@@ -95476,10 +95916,15 @@
95916 }else{
95917 lwr = mid + 1;
95918 }
95919 }
95920 if( lwr>upr ) goto pragma_out;
95921
95922 /* Make sure the database schema is loaded if the pragma requires that */
95923 if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
95924 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
95925 }
95926
95927 /* Jump to the appropriate pragma handler */
95928 switch( aPragmaNames[mid].ePragTyp ){
95929
95930 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -95510,11 +95955,10 @@
95955 { OP_Integer, 0, 1, 0}, /* 6 */
95956 { OP_Noop, 0, 0, 0},
95957 { OP_ResultRow, 1, 1, 0},
95958 };
95959 int addr;
 
95960 sqlite3VdbeUsesBtree(v, iDb);
95961 if( !zRight ){
95962 sqlite3VdbeSetNumCols(v, 1);
95963 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
95964 pParse->nMem += 2;
@@ -95606,11 +96050,10 @@
96050 **
96051 ** Return the number of pages in the specified database.
96052 */
96053 case PragTyp_PAGE_COUNT: {
96054 int iReg;
 
96055 sqlite3CodeVerifySchema(pParse, iDb);
96056 iReg = ++pParse->nMem;
96057 if( sqlite3Tolower(zLeft[0])=='p' ){
96058 sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
96059 }else{
@@ -95679,18 +96122,10 @@
96122 */
96123 case PragTyp_JOURNAL_MODE: {
96124 int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
96125 int ii; /* Loop counter */
96126
 
 
 
 
 
 
 
 
96127 sqlite3VdbeSetNumCols(v, 1);
96128 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
96129
96130 if( zRight==0 ){
96131 /* If there is no "=MODE" part of the pragma, do a query for the
@@ -95752,55 +96187,44 @@
96187 */
96188 #ifndef SQLITE_OMIT_AUTOVACUUM
96189 case PragTyp_AUTO_VACUUM: {
96190 Btree *pBt = pDb->pBt;
96191 assert( pBt!=0 );
 
 
 
96192 if( !zRight ){
96193 returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
 
 
 
 
 
 
96194 }else{
96195 int eAuto = getAutoVacuum(zRight);
96196 assert( eAuto>=0 && eAuto<=2 );
96197 db->nextAutovac = (u8)eAuto;
96198 /* Call SetAutoVacuum() to set initialize the internal auto and
96199 ** incr-vacuum flags. This is required in case this connection
96200 ** creates the database file. It is important that it is created
96201 ** as an auto-vacuum capable db.
96202 */
96203 rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
96204 if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
96205 /* When setting the auto_vacuum mode to either "full" or
96206 ** "incremental", write the value of meta[6] in the database
96207 ** file. Before writing to meta[6], check that meta[3] indicates
96208 ** that this really is an auto-vacuum capable database.
96209 */
96210 static const VdbeOpList setMeta6[] = {
96211 { OP_Transaction, 0, 1, 0}, /* 0 */
96212 { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
96213 { OP_If, 1, 0, 0}, /* 2 */
96214 { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
96215 { OP_Integer, 0, 1, 0}, /* 4 */
96216 { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
96217 };
96218 int iAddr;
96219 iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
96220 sqlite3VdbeChangeP1(v, iAddr, iDb);
96221 sqlite3VdbeChangeP1(v, iAddr+1, iDb);
96222 sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
96223 sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
96224 sqlite3VdbeChangeP1(v, iAddr+5, iDb);
96225 sqlite3VdbeUsesBtree(v, iDb);
 
 
96226 }
96227 }
96228 break;
96229 }
96230 #endif
@@ -95811,13 +96235,10 @@
96235 ** Do N steps of incremental vacuuming on a database.
96236 */
96237 #ifndef SQLITE_OMIT_AUTOVACUUM
96238 case PragTyp_INCREMENTAL_VACUUM: {
96239 int iLimit, addr;
 
 
 
96240 if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
96241 iLimit = 0x7fffffff;
96242 }
96243 sqlite3BeginWriteOperation(pParse, 0, iDb);
96244 sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
@@ -95841,11 +96262,10 @@
96262 ** number of pages in the cache. If N is negative, then the
96263 ** number of pages is adjusted so that the cache uses -N kibibytes
96264 ** of memory.
96265 */
96266 case PragTyp_CACHE_SIZE: {
 
96267 assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
96268 if( !zRight ){
96269 returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
96270 }else{
96271 int size = sqlite3Atoi(zRight);
@@ -96062,11 +96482,10 @@
96482 ** the local value does not make changes to the disk file and the
96483 ** default value will be restored the next time the database is
96484 ** opened.
96485 */
96486 case PragTyp_SYNCHRONOUS: {
 
96487 if( !zRight ){
96488 returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
96489 }else{
96490 if( !db->autoCommit ){
96491 sqlite3ErrorMsg(pParse,
@@ -96124,11 +96543,10 @@
96543 ** notnull: True if 'NOT NULL' is part of column declaration
96544 ** dflt_value: The default value for the column, if any.
96545 */
96546 case PragTyp_TABLE_INFO: if( zRight ){
96547 Table *pTab;
 
96548 pTab = sqlite3FindTable(db, zRight, zDb);
96549 if( pTab ){
96550 int i, k;
96551 int nHidden = 0;
96552 Column *pCol;
@@ -96170,15 +96588,44 @@
96588 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
96589 }
96590 }
96591 }
96592 break;
96593
96594 case PragTyp_STATS: {
96595 Index *pIdx;
96596 HashElem *i;
96597 v = sqlite3GetVdbe(pParse);
96598 sqlite3VdbeSetNumCols(v, 4);
96599 pParse->nMem = 4;
96600 sqlite3CodeVerifySchema(pParse, iDb);
96601 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
96602 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC);
96603 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC);
96604 sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC);
96605 for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
96606 Table *pTab = sqliteHashData(i);
96607 sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0);
96608 sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
96609 sqlite3VdbeAddOp2(v, OP_Integer,
96610 (int)sqlite3LogEstToInt(pTab->szTabRow), 3);
96611 sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4);
96612 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96613 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
96614 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96615 sqlite3VdbeAddOp2(v, OP_Integer,
96616 (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
96617 sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
96618 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
96619 }
96620 }
96621 }
96622 break;
96623
96624 case PragTyp_INDEX_INFO: if( zRight ){
96625 Index *pIdx;
96626 Table *pTab;
 
96627 pIdx = sqlite3FindIndex(db, zRight, zDb);
96628 if( pIdx ){
96629 int i;
96630 pTab = pIdx->pTable;
96631 sqlite3VdbeSetNumCols(v, 3);
@@ -96200,39 +96647,32 @@
96647 break;
96648
96649 case PragTyp_INDEX_LIST: if( zRight ){
96650 Index *pIdx;
96651 Table *pTab;
96652 int i;
96653 pTab = sqlite3FindTable(db, zRight, zDb);
96654 if( pTab ){
96655 v = sqlite3GetVdbe(pParse);
96656 sqlite3VdbeSetNumCols(v, 3);
96657 pParse->nMem = 3;
96658 sqlite3CodeVerifySchema(pParse, iDb);
96659 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96660 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96661 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
96662 for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
96663 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
96664 sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
96665 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
96666 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
 
 
 
 
 
 
96667 }
96668 }
96669 }
96670 break;
96671
96672 case PragTyp_DATABASE_LIST: {
96673 int i;
 
96674 sqlite3VdbeSetNumCols(v, 3);
96675 pParse->nMem = 3;
96676 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
96677 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
96678 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
@@ -96267,11 +96707,10 @@
96707
96708 #ifndef SQLITE_OMIT_FOREIGN_KEY
96709 case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
96710 FKey *pFK;
96711 Table *pTab;
 
96712 pTab = sqlite3FindTable(db, zRight, zDb);
96713 if( pTab ){
96714 v = sqlite3GetVdbe(pParse);
96715 pFK = pTab->pFKey;
96716 if( pFK ){
@@ -96329,11 +96768,10 @@
96768 int regRow; /* Registers to hold a row from pTab */
96769 int addrTop; /* Top of a loop checking foreign keys */
96770 int addrOk; /* Jump here if the key is OK */
96771 int *aiCols; /* child to parent column mapping */
96772
 
96773 regResult = pParse->nMem+1;
96774 pParse->nMem += 4;
96775 regKey = ++pParse->nMem;
96776 regRow = ++pParse->nMem;
96777 v = sqlite3GetVdbe(pParse);
@@ -96357,12 +96795,12 @@
96795 if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
96796 sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
96797 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
96798 P4_TRANSIENT);
96799 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96800 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
96801 if( pParent==0 ) continue;
96802 pIdx = 0;
96803 sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
96804 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
96805 if( x==0 ){
96806 if( pIdx==0 ){
@@ -96375,22 +96813,24 @@
96813 }else{
96814 k = 0;
96815 break;
96816 }
96817 }
96818 assert( pParse->nErr>0 || pFK==0 );
96819 if( pFK ) break;
96820 if( pParse->nTab<i ) pParse->nTab = i;
96821 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
96822 for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
96823 pParent = sqlite3FindTable(db, pFK->zTo, zDb);
 
96824 pIdx = 0;
96825 aiCols = 0;
96826 if( pParent ){
96827 x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
96828 assert( x==0 );
96829 }
96830 addrOk = sqlite3VdbeMakeLabel(v);
96831 if( pParent && pIdx==0 ){
96832 int iKey = pFK->aCol[0].iFrom;
96833 assert( iKey>=0 && iKey<pTab->nCol );
96834 if( iKey!=pTab->iPKey ){
96835 sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
96836 sqlite3ColumnDefault(v, pTab, iKey, regRow);
@@ -96404,17 +96844,19 @@
96844 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
96845 sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
96846 }else{
96847 for(j=0; j<pFK->nCol; j++){
96848 sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
96849 aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
96850 sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
96851 }
96852 if( pParent ){
96853 sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
96854 sqlite3VdbeChangeP4(v, -1,
96855 sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
96856 sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
96857 }
96858 }
96859 sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
96860 sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
96861 pFK->zTo, P4_TRANSIENT);
96862 sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
@@ -96490,11 +96932,10 @@
96932 assert( iDb>=0 );
96933 assert( iDb==0 || pId2->z );
96934 if( pId2->z==0 ) iDb = -1;
96935
96936 /* Initialize the VDBE program */
 
96937 pParse->nMem = 6;
96938 sqlite3VdbeSetNumCols(v, 1);
96939 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
96940
96941 /* Set the maximum error count */
@@ -96814,11 +97255,10 @@
97255 eMode = SQLITE_CHECKPOINT_FULL;
97256 }else if( sqlite3StrICmp(zRight, "restart")==0 ){
97257 eMode = SQLITE_CHECKPOINT_RESTART;
97258 }
97259 }
 
97260 sqlite3VdbeSetNumCols(v, 3);
97261 pParse->nMem = 3;
97262 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
97263 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
97264 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
@@ -96934,16 +97374,16 @@
97374 if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
97375 break;
97376 }
97377 case PragTyp_HEXKEY: {
97378 if( zRight ){
97379 u8 iByte;
97380 int i;
97381 char zKey[40];
97382 for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
97383 iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
97384 if( (i&1)!=0 ) zKey[i/2] = iByte;
 
97385 }
97386 if( (zLeft[3] & 0xf)==0xb ){
97387 sqlite3_key_v2(db, zDb, zKey, i/2);
97388 }else{
97389 sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -98913,10 +99353,13 @@
99353 }
99354
99355 /*
99356 ** Return a pointer to a string containing the 'declaration type' of the
99357 ** expression pExpr. The string may be treated as static by the caller.
99358 **
99359 ** Also try to estimate the size of the returned value and return that
99360 ** result in *pEstWidth.
99361 **
99362 ** The declaration type is the exact datatype definition extracted from the
99363 ** original CREATE TABLE statement if the expression is a column. The
99364 ** declaration type for a ROWID field is INTEGER. Exactly when an expression
99365 ** is considered a column can be complex in the presence of subqueries. The
@@ -98927,25 +99370,40 @@
99370 ** SELECT (SELECT col FROM tbl;
99371 ** SELECT (SELECT col FROM tbl);
99372 ** SELECT abc FROM (SELECT col AS abc FROM tbl);
99373 **
99374 ** The declaration type for any expression other than a column is NULL.
99375 **
99376 ** This routine has either 3 or 6 parameters depending on whether or not
99377 ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
99378 */
99379 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99380 # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
99381 static const char *columnTypeImpl(
99382 NameContext *pNC,
99383 Expr *pExpr,
99384 const char **pzOrigDb,
99385 const char **pzOrigTab,
99386 const char **pzOrigCol,
99387 u8 *pEstWidth
99388 ){
99389 char const *zOrigDb = 0;
99390 char const *zOrigTab = 0;
99391 char const *zOrigCol = 0;
99392 #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99393 # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
99394 static const char *columnTypeImpl(
99395 NameContext *pNC,
99396 Expr *pExpr,
99397 u8 *pEstWidth
 
 
99398 ){
99399 #endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
99400 char const *zType = 0;
 
 
 
99401 int j;
99402 u8 estWidth = 1;
99403
99404 if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
 
99405 switch( pExpr->op ){
99406 case TK_AGG_COLUMN:
99407 case TK_COLUMN: {
99408 /* The expression is a column. Locate the table the column is being
99409 ** extracted from in NameContext.pSrcList. This table may be real
@@ -99002,29 +99460,39 @@
99460 NameContext sNC;
99461 Expr *p = pS->pEList->a[iCol].pExpr;
99462 sNC.pSrcList = pS->pSrc;
99463 sNC.pNext = pNC;
99464 sNC.pParse = pNC->pParse;
99465 zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
99466 }
99467 }else if( ALWAYS(pTab->pSchema) ){
99468 /* A real table */
99469 assert( !pS );
99470 if( iCol<0 ) iCol = pTab->iPKey;
99471 assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
99472 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99473 if( iCol<0 ){
99474 zType = "INTEGER";
99475 zOrigCol = "rowid";
99476 }else{
99477 zType = pTab->aCol[iCol].zType;
99478 zOrigCol = pTab->aCol[iCol].zName;
99479 estWidth = pTab->aCol[iCol].szEst;
99480 }
99481 zOrigTab = pTab->zName;
99482 if( pNC->pParse ){
99483 int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
99484 zOrigDb = pNC->pParse->db->aDb[iDb].zName;
99485 }
99486 #else
99487 if( iCol<0 ){
99488 zType = "INTEGER";
99489 }else{
99490 zType = pTab->aCol[iCol].zType;
99491 estWidth = pTab->aCol[iCol].szEst;
99492 }
99493 #endif
99494 }
99495 break;
99496 }
99497 #ifndef SQLITE_OMIT_SUBQUERY
99498 case TK_SELECT: {
@@ -99037,22 +99505,25 @@
99505 Expr *p = pS->pEList->a[0].pExpr;
99506 assert( ExprHasProperty(pExpr, EP_xIsSelect) );
99507 sNC.pSrcList = pS->pSrc;
99508 sNC.pNext = pNC;
99509 sNC.pParse = pNC->pParse;
99510 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
99511 break;
99512 }
99513 #endif
99514 }
99515
99516 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99517 if( pzOrigDb ){
99518 assert( pzOrigTab && pzOrigCol );
99519 *pzOrigDb = zOrigDb;
99520 *pzOrigTab = zOrigTab;
99521 *pzOrigCol = zOrigCol;
99522 }
99523 #endif
99524 if( pEstWidth ) *pEstWidth = estWidth;
99525 return zType;
99526 }
99527
99528 /*
99529 ** Generate code that will tell the VDBE the declaration types of columns
@@ -99074,25 +99545,25 @@
99545 const char *zType;
99546 #ifdef SQLITE_ENABLE_COLUMN_METADATA
99547 const char *zOrigDb = 0;
99548 const char *zOrigTab = 0;
99549 const char *zOrigCol = 0;
99550 zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
99551
99552 /* The vdbe must make its own copy of the column-type and other
99553 ** column specific strings, in case the schema is reset before this
99554 ** virtual machine is deleted.
99555 */
99556 sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
99557 sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
99558 sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
99559 #else
99560 zType = columnType(&sNC, p, 0, 0, 0, 0);
99561 #endif
99562 sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
99563 }
99564 #endif /* !defined(SQLITE_OMIT_DECLTYPE) */
99565 }
99566
99567 /*
99568 ** Generate code that will tell the VDBE the names of columns
99569 ** in the result set. This information is used to provide the
@@ -99277,39 +99748,41 @@
99748 ** This routine requires that all identifiers in the SELECT
99749 ** statement be resolved.
99750 */
99751 static void selectAddColumnTypeAndCollation(
99752 Parse *pParse, /* Parsing contexts */
99753 Table *pTab, /* Add column type information to this table */
 
99754 Select *pSelect /* SELECT used to determine types and collations */
99755 ){
99756 sqlite3 *db = pParse->db;
99757 NameContext sNC;
99758 Column *pCol;
99759 CollSeq *pColl;
99760 int i;
99761 Expr *p;
99762 struct ExprList_item *a;
99763 u64 szAll = 0;
99764
99765 assert( pSelect!=0 );
99766 assert( (pSelect->selFlags & SF_Resolved)!=0 );
99767 assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
99768 if( db->mallocFailed ) return;
99769 memset(&sNC, 0, sizeof(sNC));
99770 sNC.pSrcList = pSelect->pSrc;
99771 a = pSelect->pEList->a;
99772 for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
99773 p = a[i].pExpr;
99774 pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
99775 szAll += pCol->szEst;
99776 pCol->affinity = sqlite3ExprAffinity(p);
99777 if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
99778 pColl = sqlite3ExprCollSeq(pParse, p);
99779 if( pColl ){
99780 pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
99781 }
99782 }
99783 pTab->szTabRow = sqlite3LogEst(szAll*4);
99784 }
99785
99786 /*
99787 ** Given a SELECT statement, generate a Table structure that describes
99788 ** the result set of that SELECT.
@@ -99333,13 +99806,13 @@
99806 /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
99807 ** is disabled */
99808 assert( db->lookaside.bEnabled==0 );
99809 pTab->nRef = 1;
99810 pTab->zName = 0;
99811 pTab->nRowEst = 1048576;
99812 selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
99813 selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
99814 pTab->iPKey = -1;
99815 if( db->mallocFailed ){
99816 sqlite3DeleteTable(db, pTab);
99817 return 0;
99818 }
@@ -101247,15 +101720,15 @@
101720 assert( pFrom->pTab==0 );
101721 sqlite3WalkSelect(pWalker, pSel);
101722 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
101723 if( pTab==0 ) return WRC_Abort;
101724 pTab->nRef = 1;
101725 pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
101726 while( pSel->pPrior ){ pSel = pSel->pPrior; }
101727 selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
101728 pTab->iPKey = -1;
101729 pTab->nRowEst = 1048576;
101730 pTab->tabFlags |= TF_Ephemeral;
101731 #endif
101732 }else{
101733 /* An ordinary table or view name in the FROM clause */
101734 assert( pFrom->pTab==0 );
@@ -101535,11 +102008,11 @@
102008 if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
102009 /* A sub-query in the FROM clause of a SELECT */
102010 Select *pSel = pFrom->pSelect;
102011 assert( pSel );
102012 while( pSel->pPrior ) pSel = pSel->pPrior;
102013 selectAddColumnTypeAndCollation(pParse, pTab, pSel);
102014 }
102015 }
102016 }
102017 return WRC_Continue;
102018 }
@@ -102450,29 +102923,29 @@
102923 int iRoot = pTab->tnum; /* Root page of scanned b-tree */
102924
102925 sqlite3CodeVerifySchema(pParse, iDb);
102926 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102927
102928 /* Search for the index that has the lowest scan cost.
 
 
 
 
 
 
102929 **
102930 ** (2011-04-15) Do not do a full scan of an unordered index.
102931 **
102932 ** (2013-10-03) Do not count the entires in a partial index.
102933 **
102934 ** In practice the KeyInfo structure will not be used. It is only
102935 ** passed to keep OP_OpenRead happy.
102936 */
102937 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
102938 if( pIdx->bUnordered==0
102939 && pIdx->szIdxRow<pTab->szTabRow
102940 && pIdx->pPartIdxWhere==0
102941 && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
102942 ){
102943 pBest = pIdx;
102944 }
102945 }
102946 if( pBest ){
102947 iRoot = pBest->tnum;
102948 pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
102949 }
102950
102951 /* Open a read-only cursor, execute the OP_Count, close the cursor. */
@@ -103046,12 +103519,12 @@
103519 }
103520
103521 /* Ensure the table name matches database name and that the table exists */
103522 if( db->mallocFailed ) goto trigger_cleanup;
103523 assert( pTableName->nSrc==1 );
103524 sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
103525 if( sqlite3FixSrcList(&sFix, pTableName) ){
103526 goto trigger_cleanup;
103527 }
103528 pTab = sqlite3SrcListLookup(pParse, pTableName);
103529 if( !pTab ){
103530 /* The table does not exist. */
@@ -103189,12 +103662,14 @@
103662 pStepList->pTrig = pTrig;
103663 pStepList = pStepList->pNext;
103664 }
103665 nameToken.z = pTrig->zName;
103666 nameToken.n = sqlite3Strlen30(nameToken.z);
103667 sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
103668 if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
103669 || sqlite3FixExpr(&sFix, pTrig->pWhen)
103670 ){
103671 goto triggerfinish_cleanup;
103672 }
103673
103674 /* if we are not initializing,
103675 ** build the sqlite_master entry
@@ -104781,18 +105256,38 @@
105256
105257 return vacuumFinalize(db, pStmt, pzErrMsg);
105258 }
105259
105260 /*
105261 ** The VACUUM command is used to clean up the database,
105262 ** collapse free space, etc. It is modelled after the VACUUM command
105263 ** in PostgreSQL. The VACUUM command works as follows:
105264 **
105265 ** (1) Create a new transient database file
105266 ** (2) Copy all content from the database being vacuumed into
105267 ** the new transient database file
105268 ** (3) Copy content from the transient database back into the
105269 ** original database.
105270 **
105271 ** The transient database requires temporary disk space approximately
105272 ** equal to the size of the original database. The copy operation of
105273 ** step (3) requires additional temporary disk space approximately equal
105274 ** to the size of the original database for the rollback journal.
105275 ** Hence, temporary disk space that is approximately 2x the size of the
105276 ** orginal database is required. Every page of the database is written
105277 ** approximately 3 times: Once for step (2) and twice for step (3).
105278 ** Two writes per page are required in step (3) because the original
105279 ** database content must be written into the rollback journal prior to
105280 ** overwriting the database with the vacuumed content.
105281 **
105282 ** Only 1x temporary space and only 1x writes would be required if
105283 ** the copy of step (3) were replace by deleting the original database
105284 ** and renaming the transient database as the original. But that will
105285 ** not work if other processes are attached to the original database.
105286 ** And a power loss in between deleting the original and renaming the
105287 ** transient would cause the database file to appear to be deleted
105288 ** following reboot.
105289 */
105290 SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
105291 Vdbe *v = sqlite3GetVdbe(pParse);
105292 if( v ){
105293 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
@@ -106206,30 +106701,10 @@
106701 typedef struct WhereLoopBuilder WhereLoopBuilder;
106702 typedef struct WhereScan WhereScan;
106703 typedef struct WhereOrCost WhereOrCost;
106704 typedef struct WhereOrSet WhereOrSet;
106705
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106706 /*
106707 ** This object contains information needed to implement a single nested
106708 ** loop in WHERE clause.
106709 **
106710 ** Contrast this object with WhereLoop. This object describes the
@@ -106290,13 +106765,13 @@
106765 #ifdef SQLITE_DEBUG
106766 char cId; /* Symbolic ID of this loop for debugging use */
106767 #endif
106768 u8 iTab; /* Position in FROM clause of table for this loop */
106769 u8 iSortIdx; /* Sorting index number. 0==None */
106770 LogEst rSetup; /* One-time setup cost (ex: create transient index) */
106771 LogEst rRun; /* Cost of running each loop */
106772 LogEst nOut; /* Estimated number of output rows */
106773 union {
106774 struct { /* Information for internal btree tables */
106775 int nEq; /* Number of equality constraints */
106776 Index *pIndex; /* Index used, or NULL */
106777 } btree;
@@ -106322,12 +106797,12 @@
106797 ** subquery on one operand of an OR operator in the WHERE clause.
106798 ** See WhereOrSet for additional information
106799 */
106800 struct WhereOrCost {
106801 Bitmask prereq; /* Prerequisites */
106802 LogEst rRun; /* Cost of running this subquery */
106803 LogEst nOut; /* Number of outputs for this subquery */
106804 };
106805
106806 /* The WhereOrSet object holds a set of possible WhereOrCosts that
106807 ** correspond to the subquery(s) of OR-clause processing. Only the
106808 ** best N_OR_COST elements are retained.
@@ -106361,12 +106836,12 @@
106836 ** at the end is the choosen query plan.
106837 */
106838 struct WherePath {
106839 Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
106840 Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
106841 LogEst nRow; /* Estimated number of rows generated by this path */
106842 LogEst rCost; /* Total cost of this path */
106843 u8 isOrdered; /* True if this path satisfies ORDER BY */
106844 u8 isOrderedValid; /* True if the isOrdered field is valid */
106845 WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
106846 };
106847
@@ -106428,11 +106903,11 @@
106903 union {
106904 int leftColumn; /* Column number of X in "X <op> <expr>" */
106905 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
106906 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
106907 } u;
106908 LogEst truthProb; /* Probability of truth for this expression */
106909 u16 eOperator; /* A WO_xx value describing <op> */
106910 u8 wtFlags; /* TERM_xxx bit flags. See below */
106911 u8 nChild; /* Number of children that must disable us */
106912 WhereClause *pWC; /* The clause this term is part of */
106913 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -106576,11 +107051,11 @@
107051 SrcList *pTabList; /* List of tables in the join */
107052 ExprList *pOrderBy; /* The ORDER BY clause or NULL */
107053 ExprList *pResultSet; /* Result set. DISTINCT operates on these */
107054 WhereLoop *pLoops; /* List of all WhereLoop objects */
107055 Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
107056 LogEst nRowOut; /* Estimated number of output rows */
107057 u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
107058 u8 bOBSat; /* ORDER BY satisfied by indices */
107059 u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
107060 u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
107061 u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -106636,30 +107111,15 @@
107111 #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
107112 #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
107113 #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
107114 #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
107115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107116 /*
107117 ** Return the estimated number of output rows from a WHERE clause
107118 */
107119 SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
107120 return sqlite3LogEstToInt(pWInfo->nRowOut);
107121 }
107122
107123 /*
107124 ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
107125 ** WHERE clause returns outputs for DISTINCT processing.
@@ -106717,12 +107177,12 @@
107177 ** so that pSet keeps the N_OR_COST best entries seen so far.
107178 */
107179 static int whereOrInsert(
107180 WhereOrSet *pSet, /* The WhereOrSet to be updated */
107181 Bitmask prereq, /* Prerequisites of the new entry */
107182 LogEst rRun, /* Run-cost of the new entry */
107183 LogEst nOut /* Number of outputs for the new entry */
107184 ){
107185 u16 i;
107186 WhereOrCost *p;
107187 for(i=pSet->n, p=pSet->a; i>0; i--, p++){
107188 if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
@@ -106803,13 +107263,10 @@
107263 if( pWC->a!=pWC->aStatic ){
107264 sqlite3DbFree(db, pWC->a);
107265 }
107266 }
107267
 
 
 
107268 /*
107269 ** Add a single new WhereTerm entry to the WhereClause object pWC.
107270 ** The new WhereTerm object is constructed from Expr p and with wtFlags.
107271 ** The index in pWC->a[] of the new WhereTerm is returned on success.
107272 ** 0 is returned if the new WhereTerm could not be added due to a memory
@@ -106848,11 +107305,11 @@
107305 }
107306 pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
107307 }
107308 pTerm = &pWC->a[idx = pWC->nTerm++];
107309 if( p && ExprHasProperty(p, EP_Unlikely) ){
107310 pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
107311 }else{
107312 pTerm->truthProb = -1;
107313 }
107314 pTerm->pExpr = sqlite3ExprSkipCollate(p);
107315 pTerm->wtFlags = wtFlags;
@@ -108112,79 +108569,16 @@
108569 }
108570
108571 return 0;
108572 }
108573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108574
108575 /*
108576 ** Estimate the logarithm of the input value to base 2.
108577 */
108578 static LogEst estLog(LogEst N){
108579 LogEst x = sqlite3LogEst(N);
108580 return x>33 ? x - 33 : 0;
108581 }
108582
108583 /*
108584 ** Two routines for printing the content of an sqlite3_index_info
@@ -108596,10 +108990,13 @@
108990 int iMin = 0; /* Smallest sample not yet tested */
108991 int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
108992 int iTest; /* Next sample to test */
108993 int res; /* Result of comparison operation */
108994
108995 #ifndef SQLITE_DEBUG
108996 UNUSED_PARAMETER( pParse );
108997 #endif
108998 assert( pRec!=0 || pParse->db->mallocFailed );
108999 if( pRec==0 ) return;
109000 iCol = pRec->nField - 1;
109001 assert( pIdx->nSample>0 );
109002 assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
@@ -108693,11 +109090,11 @@
109090 **
109091 ** ... FROM t1 WHERE a > ? AND a < ? ...
109092 **
109093 ** then nEq is set to 0.
109094 **
109095 ** When this function is called, *pnOut is set to the sqlite3LogEst() of the
109096 ** number of rows that the index scan is expected to visit without
109097 ** considering the range constraints. If nEq is 0, this is the number of
109098 ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
109099 ** to account for the range contraints pLower and pUpper.
109100 **
@@ -108709,19 +109106,19 @@
109106 static int whereRangeScanEst(
109107 Parse *pParse, /* Parsing & code generating context */
109108 WhereLoopBuilder *pBuilder,
109109 WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
109110 WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
109111 WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
109112 ){
109113 int rc = SQLITE_OK;
109114 int nOut = pLoop->nOut;
109115 LogEst nNew;
109116
109117 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
109118 Index *p = pLoop->u.btree.pIndex;
109119 int nEq = pLoop->u.btree.nEq;
109120
109121 if( p->nSample>0
109122 && nEq==pBuilder->nRecValid
109123 && nEq<p->nSampleCol
109124 && OptimizationEnabled(pParse->db, SQLITE_Stat3)
@@ -108798,18 +109195,18 @@
109195 }
109196
109197 pBuilder->pRec = pRec;
109198 if( rc==SQLITE_OK ){
109199 if( iUpper>iLower ){
109200 nNew = sqlite3LogEst(iUpper - iLower);
109201 }else{
109202 nNew = 10; assert( 10==sqlite3LogEst(2) );
109203 }
109204 if( nNew<nOut ){
109205 nOut = nNew;
109206 }
109207 pLoop->nOut = (LogEst)nOut;
109208 WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
109209 (u32)iLower, (u32)iUpper, nOut));
109210 return SQLITE_OK;
109211 }
109212 }
@@ -108820,20 +109217,20 @@
109217 assert( pLower || pUpper );
109218 /* TUNING: Each inequality constraint reduces the search space 4-fold.
109219 ** A BETWEEN operator, therefore, reduces the search space 16-fold */
109220 nNew = nOut;
109221 if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
109222 nNew -= 20; assert( 20==sqlite3LogEst(4) );
109223 nOut--;
109224 }
109225 if( pUpper ){
109226 nNew -= 20; assert( 20==sqlite3LogEst(4) );
109227 nOut--;
109228 }
109229 if( nNew<10 ) nNew = 10;
109230 if( nNew<nOut ) nOut = nNew;
109231 pLoop->nOut = (LogEst)nOut;
109232 return rc;
109233 }
109234
109235 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
109236 /*
@@ -110441,11 +110838,11 @@
110838 **
110839 ** In the current implementation, the first extra WHERE clause term reduces
110840 ** the number of output rows by a factor of 10 and each additional term
110841 ** reduces the number of output rows by sqrt(2).
110842 */
110843 static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
110844 WhereTerm *pTerm, *pX;
110845 Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
110846 int i, j;
110847
110848 if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
@@ -110473,11 +110870,11 @@
110870 */
110871 static int whereLoopAddBtreeIndex(
110872 WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
110873 struct SrcList_item *pSrc, /* FROM clause term being analyzed */
110874 Index *pProbe, /* An index on pSrc */
110875 LogEst nInMul /* log(Number of iterations due to IN) */
110876 ){
110877 WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
110878 Parse *pParse = pWInfo->pParse; /* Parsing context */
110879 sqlite3 *db = pParse->db; /* Database connection malloc context */
110880 WhereLoop *pNew; /* Template WhereLoop under construction */
@@ -110486,15 +110883,15 @@
110883 WhereScan scan; /* Iterator for WHERE terms */
110884 Bitmask saved_prereq; /* Original value of pNew->prereq */
110885 u16 saved_nLTerm; /* Original value of pNew->nLTerm */
110886 int saved_nEq; /* Original value of pNew->u.btree.nEq */
110887 u32 saved_wsFlags; /* Original value of pNew->wsFlags */
110888 LogEst saved_nOut; /* Original value of pNew->nOut */
110889 int iCol; /* Index of the column in the table */
110890 int rc = SQLITE_OK; /* Return code */
110891 LogEst nRowEst; /* Estimated index selectivity */
110892 LogEst rLogSize; /* Logarithm of table size */
110893 WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
110894
110895 pNew = pBuilder->pNew;
110896 if( db->mallocFailed ) return SQLITE_NOMEM;
110897
@@ -110510,11 +110907,11 @@
110907 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
110908
110909 assert( pNew->u.btree.nEq<=pProbe->nColumn );
110910 if( pNew->u.btree.nEq < pProbe->nColumn ){
110911 iCol = pProbe->aiColumn[pNew->u.btree.nEq];
110912 nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
110913 if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
110914 }else{
110915 iCol = -1;
110916 nRowEst = 0;
110917 }
@@ -110524,11 +110921,11 @@
110921 saved_nLTerm = pNew->nLTerm;
110922 saved_wsFlags = pNew->wsFlags;
110923 saved_prereq = pNew->prereq;
110924 saved_nOut = pNew->nOut;
110925 pNew->rSetup = 0;
110926 rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
110927 for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
110928 int nIn = 0;
110929 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
110930 int nRecValid = pBuilder->nRecValid;
110931 #endif
@@ -110551,14 +110948,14 @@
110948 if( pTerm->eOperator & WO_IN ){
110949 Expr *pExpr = pTerm->pExpr;
110950 pNew->wsFlags |= WHERE_COLUMN_IN;
110951 if( ExprHasProperty(pExpr, EP_xIsSelect) ){
110952 /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
110953 nIn = 46; assert( 46==sqlite3LogEst(25) );
110954 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
110955 /* "x IN (value, value, ...)" */
110956 nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
110957 }
110958 pNew->rRun += nIn;
110959 pNew->u.btree.nEq++;
110960 pNew->nOut = nRowEst + nInMul + nIn;
110961 }else if( pTerm->eOperator & (WO_EQ) ){
@@ -110576,11 +110973,11 @@
110973 pNew->nOut = nRowEst + nInMul;
110974 }else if( pTerm->eOperator & (WO_ISNULL) ){
110975 pNew->wsFlags |= WHERE_COLUMN_NULL;
110976 pNew->u.btree.nEq++;
110977 /* TUNING: IS NULL selects 2 rows */
110978 nIn = 10; assert( 10==sqlite3LogEst(2) );
110979 pNew->nOut = nRowEst + nInMul + nIn;
110980 }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
110981 testcase( pTerm->eOperator & WO_GT );
110982 testcase( pTerm->eOperator & WO_GE );
110983 pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
@@ -110596,11 +110993,11 @@
110993 pNew->aLTerm[pNew->nLTerm-2] : 0;
110994 }
110995 if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
110996 /* Adjust nOut and rRun for STAT3 range values */
110997 assert( pNew->nOut==saved_nOut );
110998 whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
110999 }
111000 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
111001 if( nInMul==0
111002 && pProbe->nSample
111003 && pNew->u.btree.nEq<=pProbe->nSampleCol
@@ -110616,23 +111013,23 @@
111013 && !ExprHasProperty(pExpr, EP_xIsSelect) ){
111014 rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
111015 }
111016 assert( nOut==0 || rc==SQLITE_OK );
111017 if( nOut ){
111018 pNew->nOut = sqlite3LogEst(nOut);
111019 if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
111020 }
111021 }
111022 #endif
111023 if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
111024 /* Each row involves a step of the index, then a binary search of
111025 ** the main table */
111026 pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
111027 }
111028 /* Step cost for each output row */
111029 pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
111030 whereLoopOutputAdjust(pBuilder->pWC, pNew);
111031 rc = whereLoopInsert(pBuilder, pNew);
111032 if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
111033 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
111034 ){
111035 whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
@@ -110727,18 +111124,20 @@
111124 struct SrcList_item *pSrc; /* The FROM clause btree term to add */
111125 WhereLoop *pNew; /* Template WhereLoop object */
111126 int rc = SQLITE_OK; /* Return code */
111127 int iSortIdx = 1; /* Index number */
111128 int b; /* A boolean value */
111129 LogEst rSize; /* number of rows in the table */
111130 LogEst rLogSize; /* Logarithm of the number of rows in the table */
111131 WhereClause *pWC; /* The parsed WHERE clause */
111132 Table *pTab; /* Table being queried */
111133
111134 pNew = pBuilder->pNew;
111135 pWInfo = pBuilder->pWInfo;
111136 pTabList = pWInfo->pTabList;
111137 pSrc = pTabList->a + pNew->iTab;
111138 pTab = pSrc->pTab;
111139 pWC = pBuilder->pWC;
111140 assert( !IsVirtual(pSrc->pTab) );
111141
111142 if( pSrc->pIndex ){
111143 /* An INDEXED BY clause specifies a particular index to use */
@@ -110752,22 +111151,22 @@
111151 memset(&sPk, 0, sizeof(Index));
111152 sPk.nColumn = 1;
111153 sPk.aiColumn = &aiColumnPk;
111154 sPk.aiRowEst = aiRowEstPk;
111155 sPk.onError = OE_Replace;
111156 sPk.pTable = pTab;
111157 aiRowEstPk[0] = pTab->nRowEst;
111158 aiRowEstPk[1] = 1;
111159 pFirst = pSrc->pTab->pIndex;
111160 if( pSrc->notIndexed==0 ){
111161 /* The real indices of the table are only considered if the
111162 ** NOT INDEXED qualifier is omitted from the FROM clause */
111163 sPk.pNext = pFirst;
111164 }
111165 pProbe = &sPk;
111166 }
111167 rSize = sqlite3LogEst(pTab->nRowEst);
111168 rLogSize = estLog(rSize);
111169
111170 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
111171 /* Automatic indexes */
111172 if( !pBuilder->pOrSet
@@ -110788,17 +111187,17 @@
111187 pNew->nLTerm = 1;
111188 pNew->aLTerm[0] = pTerm;
111189 /* TUNING: One-time cost for computing the automatic index is
111190 ** approximately 7*N*log2(N) where N is the number of rows in
111191 ** the table being indexed. */
111192 pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
111193 /* TUNING: Each index lookup yields 20 rows in the table. This
111194 ** is more than the usual guess of 10 rows, since we have no way
111195 ** of knowning how selective the index will ultimately be. It would
111196 ** not be unreasonable to make this value much larger. */
111197 pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
111198 pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
111199 pNew->wsFlags = WHERE_AUTO_INDEX;
111200 pNew->prereq = mExtra | pTerm->prereqRight;
111201 rc = whereLoopInsert(pBuilder, pNew);
111202 }
111203 }
@@ -110828,15 +111227,13 @@
111227
111228 /* Full table scan */
111229 pNew->iSortIdx = b ? iSortIdx : 0;
111230 /* TUNING: Cost of full table scan is 3*(N + log2(N)).
111231 ** + The extra 3 factor is to encourage the use of indexed lookups
111232 ** over full scans. FIXME */
111233 pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
111234 whereLoopOutputAdjust(pWC, pNew);
 
 
111235 rc = whereLoopInsert(pBuilder, pNew);
111236 pNew->nOut = rSize;
111237 if( rc ) break;
111238 }else{
111239 Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
@@ -110844,33 +111241,32 @@
111241
111242 /* Full scan via index */
111243 if( b
111244 || ( m==0
111245 && pProbe->bUnordered==0
111246 && pProbe->szIdxRow<pTab->szTabRow
111247 && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
111248 && sqlite3GlobalConfig.bUseCis
111249 && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
111250 )
111251 ){
111252 pNew->iSortIdx = b ? iSortIdx : 0;
111253 if( m==0 ){
111254 /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
111255 ** + The extra factor K of between 1.1 and 3.0 that depends
111256 ** on the relative sizes of the table and the index. K
111257 ** is smaller for smaller indices, thus favoring them.
111258 */
111259 pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
111260 (15*pProbe->szIdxRow)/pTab->szTabRow;
 
 
111261 }else{
111262 assert( b!=0 );
111263 /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
111264 ** which we will simplify to just N*log2(N) */
111265 pNew->rRun = rSize + rLogSize;
111266 }
111267 whereLoopOutputAdjust(pWC, pNew);
111268 rc = whereLoopInsert(pBuilder, pNew);
111269 pNew->nOut = rSize;
111270 if( rc ) break;
111271 }
111272 }
@@ -111037,13 +111433,13 @@
111433 pIdxInfo->needToFreeIdxStr = 0;
111434 pNew->u.vtab.idxStr = pIdxInfo->idxStr;
111435 pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
111436 && pIdxInfo->orderByConsumed);
111437 pNew->rSetup = 0;
111438 pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
111439 /* TUNING: Every virtual table query returns 25 rows */
111440 pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
111441 whereLoopInsert(pBuilder, pNew);
111442 if( pNew->u.vtab.needFree ){
111443 sqlite3_free(pNew->u.vtab.idxStr);
111444 pNew->u.vtab.needFree = 0;
111445 }
@@ -111076,10 +111472,12 @@
111472 pWC = pBuilder->pWC;
111473 if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
111474 pWCEnd = pWC->a + pWC->nTerm;
111475 pNew = pBuilder->pNew;
111476 memset(&sSum, 0, sizeof(sSum));
111477 pItem = pWInfo->pTabList->a + pNew->iTab;
111478 iCur = pItem->iCursor;
111479
111480 for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
111481 if( (pTerm->eOperator & WO_OR)!=0
111482 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
111483 ){
@@ -111087,12 +111485,10 @@
111485 WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
111486 WhereTerm *pOrTerm;
111487 int once = 1;
111488 int i, j;
111489
 
 
111490 sSubBuild = *pBuilder;
111491 sSubBuild.pOrderBy = 0;
111492 sSubBuild.pOrSet = &sCur;
111493
111494 for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
@@ -111129,12 +111525,12 @@
111525 whereOrMove(&sPrev, &sSum);
111526 sSum.n = 0;
111527 for(i=0; i<sPrev.n; i++){
111528 for(j=0; j<sCur.n; j++){
111529 whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
111530 sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
111531 sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
111532 }
111533 }
111534 }
111535 }
111536 pNew->nLTerm = 1;
@@ -111468,23 +111864,23 @@
111864 ** costs if nRowEst==0.
111865 **
111866 ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
111867 ** error occurs.
111868 */
111869 static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
111870 int mxChoice; /* Maximum number of simultaneous paths tracked */
111871 int nLoop; /* Number of terms in the join */
111872 Parse *pParse; /* Parsing context */
111873 sqlite3 *db; /* The database connection */
111874 int iLoop; /* Loop counter over the terms of the join */
111875 int ii, jj; /* Loop counters */
111876 int mxI = 0; /* Index of next entry to replace */
111877 LogEst rCost; /* Cost of a path */
111878 LogEst nOut; /* Number of outputs */
111879 LogEst mxCost = 0; /* Maximum cost of a set of paths */
111880 LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
111881 LogEst rSortCost; /* Cost to do a sort */
111882 int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
111883 WherePath *aFrom; /* All nFrom paths at the previous level */
111884 WherePath *aTo; /* The nTo best paths at the current level */
111885 WherePath *pFrom; /* An element of aFrom[] that we are working on */
111886 WherePath *pTo; /* An element of aTo[] that we are working on */
@@ -111517,21 +111913,23 @@
111913 /* Seed the search with a single WherePath containing zero WhereLoops.
111914 **
111915 ** TUNING: Do not let the number of iterations go above 25. If the cost
111916 ** of computing an automatic index is not paid back within the first 25
111917 ** rows, then do not use the automatic index. */
111918 aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
111919 nFrom = 1;
111920
111921 /* Precompute the cost of sorting the final result set, if the caller
111922 ** to sqlite3WhereBegin() was concerned about sorting */
111923 rSortCost = 0;
111924 if( pWInfo->pOrderBy==0 || nRowEst==0 ){
111925 aFrom[0].isOrderedValid = 1;
111926 }else{
111927 /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
111928 ** number of output rows. The 48 is the expected size of a row to sort.
111929 ** FIXME: compute a better estimate of the 48 multiplier based on the
111930 ** result set expressions. */
111931 rSortCost = nRowEst + estLog(nRowEst);
111932 WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
111933 }
111934
111935 /* Compute successively longer WherePaths using the previous generation
@@ -111547,12 +111945,12 @@
111945 u8 isOrdered = pFrom->isOrdered;
111946 if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
111947 if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
111948 /* At this point, pWLoop is a candidate to be the next loop.
111949 ** Compute its cost */
111950 rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
111951 rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
111952 nOut = pFrom->nRow + pWLoop->nOut;
111953 maskNew = pFrom->maskLoop | pWLoop->maskSelf;
111954 if( !isOrderedValid ){
111955 switch( wherePathSatisfiesOrderBy(pWInfo,
111956 pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
@@ -111562,11 +111960,11 @@
111960 isOrderedValid = 1;
111961 break;
111962 case 0: /* No. pFrom+pWLoop will require a separate sort */
111963 isOrdered = 0;
111964 isOrderedValid = 1;
111965 rCost = sqlite3LogEstAdd(rCost, rSortCost);
111966 break;
111967 default: /* Cannot tell yet. Try again on the next iteration */
111968 break;
111969 }
111970 }else{
@@ -111769,11 +112167,11 @@
112167 pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
112168 pLoop->aLTerm[0] = pTerm;
112169 pLoop->nLTerm = 1;
112170 pLoop->u.btree.nEq = 1;
112171 /* TUNING: Cost of a rowid lookup is 10 */
112172 pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
112173 }else{
112174 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
112175 assert( pLoop->aLTermSpace==pLoop->aLTerm );
112176 assert( ArraySize(pLoop->aLTermSpace)==4 );
112177 if( pIdx->onError==OE_None
@@ -111792,16 +112190,16 @@
112190 }
112191 pLoop->nLTerm = j;
112192 pLoop->u.btree.nEq = j;
112193 pLoop->u.btree.pIndex = pIdx;
112194 /* TUNING: Cost of a unique index lookup is 15 */
112195 pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
112196 break;
112197 }
112198 }
112199 if( pLoop->wsFlags ){
112200 pLoop->nOut = (LogEst)1;
112201 pWInfo->a[0].pWLoop = pLoop;
112202 pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
112203 pWInfo->a[0].iTabCur = iCur;
112204 pWInfo->nRowOut = 1;
112205 if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
@@ -112165,11 +112563,11 @@
112563 WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
112564 pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
112565
112566 /* If the caller is an UPDATE or DELETE statement that is requesting
112567 ** to use a one-pass algorithm, determine if this is appropriate.
112568 ** The one-pass algorithm only works if the WHERE clause constrains
112569 ** the statement to update a single row.
112570 */
112571 assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
112572 if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
112573 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
@@ -121583,10 +121981,16 @@
121981 ** verifying the operation of the SQLite core.
121982 */
121983 int inTransaction; /* True after xBegin but before xCommit/xRollback */
121984 int mxSavepoint; /* Largest valid xSavepoint integer */
121985 #endif
121986
121987 #ifdef SQLITE_TEST
121988 /* True to disable the incremental doclist optimization. This is controled
121989 ** by special insert command 'test-no-incr-doclist'. */
121990 int bNoIncrDoclist;
121991 #endif
121992 };
121993
121994 /*
121995 ** When the core wants to read from the virtual table, it creates a
121996 ** virtual table cursor (an instance of the following structure) using
@@ -121608,11 +122012,12 @@
122012 int nDoclist; /* Size of buffer at aDoclist */
122013 u8 bDesc; /* True to sort in descending order */
122014 int eEvalmode; /* An FTS3_EVAL_XX constant */
122015 int nRowAvg; /* Average size of database rows, in pages */
122016 sqlite3_int64 nDoc; /* Documents in table */
122017 i64 iMinDocid; /* Minimum docid to return */
122018 i64 iMaxDocid; /* Maximum docid to return */
122019 int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
122020 u32 *aMatchinfo; /* Information about most recent match */
122021 int nMatchinfo; /* Number of elements in aMatchinfo[] */
122022 char *zMatchinfo; /* Matchinfo specification */
122023 };
@@ -121638,10 +122043,19 @@
122043 */
122044 #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
122045 #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
122046 #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
122047
122048 /*
122049 ** The lower 16-bits of the sqlite3_index_info.idxNum value set by
122050 ** the xBestIndex() method contains the Fts3Cursor.eSearch value described
122051 ** above. The upper 16-bits contain a combination of the following
122052 ** bits, used to describe extra constraints on full-text searches.
122053 */
122054 #define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
122055 #define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
122056 #define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
122057
122058 struct Fts3Doclist {
122059 char *aAll; /* Array containing doclist (or NULL) */
122060 int nAll; /* Size of a[] in bytes */
122061 char *pNextDocid; /* Pointer to next docid */
@@ -123058,27 +123472,31 @@
123472 */
123473 static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
123474 Fts3Table *p = (Fts3Table *)pVTab;
123475 int i; /* Iterator variable */
123476 int iCons = -1; /* Index of constraint to use */
123477
123478 int iLangidCons = -1; /* Index of langid=x constraint, if present */
123479 int iDocidGe = -1; /* Index of docid>=x constraint, if present */
123480 int iDocidLe = -1; /* Index of docid<=x constraint, if present */
123481 int iIdx;
123482
123483 /* By default use a full table scan. This is an expensive option,
123484 ** so search through the constraints to see if a more efficient
123485 ** strategy is possible.
123486 */
123487 pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
123488 pInfo->estimatedCost = 5000000;
123489 for(i=0; i<pInfo->nConstraint; i++){
123490 int bDocid; /* True if this constraint is on docid */
123491 struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
123492 if( pCons->usable==0 ) continue;
123493
123494 bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
123495
123496 /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
123497 if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
 
 
 
123498 pInfo->idxNum = FTS3_DOCID_SEARCH;
123499 pInfo->estimatedCost = 1.0;
123500 iCons = i;
123501 }
123502
@@ -123103,18 +123521,42 @@
123521 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
123522 && pCons->iColumn==p->nColumn + 2
123523 ){
123524 iLangidCons = i;
123525 }
123526
123527 if( bDocid ){
123528 switch( pCons->op ){
123529 case SQLITE_INDEX_CONSTRAINT_GE:
123530 case SQLITE_INDEX_CONSTRAINT_GT:
123531 iDocidGe = i;
123532 break;
123533
123534 case SQLITE_INDEX_CONSTRAINT_LE:
123535 case SQLITE_INDEX_CONSTRAINT_LT:
123536 iDocidLe = i;
123537 break;
123538 }
123539 }
123540 }
123541
123542 iIdx = 1;
123543 if( iCons>=0 ){
123544 pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
123545 pInfo->aConstraintUsage[iCons].omit = 1;
123546 }
123547 if( iLangidCons>=0 ){
123548 pInfo->idxNum |= FTS3_HAVE_LANGID;
123549 pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
123550 }
123551 if( iDocidGe>=0 ){
123552 pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
123553 pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
123554 }
123555 if( iDocidLe>=0 ){
123556 pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
123557 pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
123558 }
123559
123560 /* Regardless of the strategy selected, FTS can deliver rows in rowid (or
123561 ** docid) order. Both ascending and descending are possible.
123562 */
@@ -124556,10 +124998,37 @@
124998 rc = fts3EvalNext((Fts3Cursor *)pCursor);
124999 }
125000 assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
125001 return rc;
125002 }
125003
125004 /*
125005 ** The following are copied from sqliteInt.h.
125006 **
125007 ** Constants for the largest and smallest possible 64-bit signed integers.
125008 ** These macros are designed to work correctly on both 32-bit and 64-bit
125009 ** compilers.
125010 */
125011 #ifndef SQLITE_AMALGAMATION
125012 # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
125013 # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
125014 #endif
125015
125016 /*
125017 ** If the numeric type of argument pVal is "integer", then return it
125018 ** converted to a 64-bit signed integer. Otherwise, return a copy of
125019 ** the second parameter, iDefault.
125020 */
125021 static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
125022 if( pVal ){
125023 int eType = sqlite3_value_numeric_type(pVal);
125024 if( eType==SQLITE_INTEGER ){
125025 return sqlite3_value_int64(pVal);
125026 }
125027 }
125028 return iDefault;
125029 }
125030
125031 /*
125032 ** This is the xFilter interface for the virtual table. See
125033 ** the virtual table xFilter method documentation for additional
125034 ** information.
@@ -124582,44 +125051,62 @@
125051 int nVal, /* Number of elements in apVal */
125052 sqlite3_value **apVal /* Arguments for the indexing scheme */
125053 ){
125054 int rc;
125055 char *zSql; /* SQL statement used to access %_content */
125056 int eSearch;
125057 Fts3Table *p = (Fts3Table *)pCursor->pVtab;
125058 Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
125059
125060 sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
125061 sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
125062 sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
125063 sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
125064 int iIdx;
125065
125066 UNUSED_PARAMETER(idxStr);
125067 UNUSED_PARAMETER(nVal);
125068
125069 eSearch = (idxNum & 0x0000FFFF);
125070 assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
 
125071 assert( p->pSegments==0 );
125072
125073 /* Collect arguments into local variables */
125074 iIdx = 0;
125075 if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
125076 if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
125077 if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
125078 if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
125079 assert( iIdx==nVal );
125080
125081 /* In case the cursor has been used before, clear it now. */
125082 sqlite3_finalize(pCsr->pStmt);
125083 sqlite3_free(pCsr->aDoclist);
125084 sqlite3Fts3ExprFree(pCsr->pExpr);
125085 memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
125086
125087 /* Set the lower and upper bounds on docids to return */
125088 pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
125089 pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
125090
125091 if( idxStr ){
125092 pCsr->bDesc = (idxStr[0]=='D');
125093 }else{
125094 pCsr->bDesc = p->bDescIdx;
125095 }
125096 pCsr->eSearch = (i16)eSearch;
125097
125098 if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
125099 int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
125100 const char *zQuery = (const char *)sqlite3_value_text(pCons);
125101
125102 if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
125103 return SQLITE_NOMEM;
125104 }
125105
125106 pCsr->iLangid = 0;
125107 if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
125108
125109 assert( p->base.zErrMsg==0 );
125110 rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
125111 p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
125112 &p->base.zErrMsg
@@ -124638,11 +125125,11 @@
125125 /* Compile a SELECT statement for this cursor. For a full-table-scan, the
125126 ** statement loops through all rows of the %_content table. For a
125127 ** full-text query or docid lookup, the statement retrieves a single
125128 ** row by docid.
125129 */
125130 if( eSearch==FTS3_FULLSCAN_SEARCH ){
125131 zSql = sqlite3_mprintf(
125132 "SELECT %s ORDER BY rowid %s",
125133 p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
125134 );
125135 if( zSql ){
@@ -124649,14 +125136,14 @@
125136 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
125137 sqlite3_free(zSql);
125138 }else{
125139 rc = SQLITE_NOMEM;
125140 }
125141 }else if( eSearch==FTS3_DOCID_SEARCH ){
125142 rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
125143 if( rc==SQLITE_OK ){
125144 rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
125145 }
125146 }
125147 if( rc!=SQLITE_OK ) return rc;
125148
125149 return fts3NextMethod(pCursor);
@@ -125543,10 +126030,16 @@
126030 }
126031
126032 return SQLITE_OK;
126033 }
126034
126035 /*
126036 ** Maximum number of tokens a phrase may have to be considered for the
126037 ** incremental doclists strategy.
126038 */
126039 #define MAX_INCR_PHRASE_TOKENS 4
126040
126041 /*
126042 ** This function is called for each Fts3Phrase in a full-text query
126043 ** expression to initialize the mechanism for returning rows. Once this
126044 ** function has been called successfully on an Fts3Phrase, it may be
126045 ** used with fts3EvalPhraseNext() to iterate through the matching docids.
@@ -125556,27 +126049,47 @@
126049 ** memory within this call.
126050 **
126051 ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
126052 */
126053 static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
 
 
126054 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126055 int rc = SQLITE_OK; /* Error code */
126056 int i;
126057
126058 /* Determine if doclists may be loaded from disk incrementally. This is
126059 ** possible if the bOptOk argument is true, the FTS doclists will be
126060 ** scanned in forward order, and the phrase consists of
126061 ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
126062 ** tokens or prefix tokens that cannot use a prefix-index. */
126063 int bHaveIncr = 0;
126064 int bIncrOk = (bOptOk
126065 && pCsr->bDesc==pTab->bDescIdx
126066 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
126067 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
126068 #ifdef SQLITE_TEST
126069 && pTab->bNoIncrDoclist==0
126070 #endif
126071 );
126072 for(i=0; bIncrOk==1 && i<p->nToken; i++){
126073 Fts3PhraseToken *pToken = &p->aToken[i];
126074 if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
126075 bIncrOk = 0;
126076 }
126077 if( pToken->pSegcsr ) bHaveIncr = 1;
126078 }
126079
126080 if( bIncrOk && bHaveIncr ){
126081 /* Use the incremental approach. */
126082 int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
126083 for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
126084 Fts3PhraseToken *pToken = &p->aToken[i];
126085 Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
126086 if( pSegcsr ){
126087 rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
126088 }
126089 }
126090 p->bIncr = 1;
 
126091 }else{
126092 /* Load the full doclist for the phrase into memory. */
126093 rc = fts3EvalPhraseLoad(pCsr, p);
126094 p->bIncr = 0;
126095 }
@@ -125680,10 +126193,220 @@
126193 }
126194 }
126195
126196 *ppIter = p;
126197 }
126198
126199 /*
126200 ** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
126201 ** to true if EOF is reached.
126202 */
126203 static void fts3EvalDlPhraseNext(
126204 Fts3Table *pTab,
126205 Fts3Doclist *pDL,
126206 u8 *pbEof
126207 ){
126208 char *pIter; /* Used to iterate through aAll */
126209 char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
126210
126211 if( pDL->pNextDocid ){
126212 pIter = pDL->pNextDocid;
126213 }else{
126214 pIter = pDL->aAll;
126215 }
126216
126217 if( pIter>=pEnd ){
126218 /* We have already reached the end of this doclist. EOF. */
126219 *pbEof = 1;
126220 }else{
126221 sqlite3_int64 iDelta;
126222 pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
126223 if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
126224 pDL->iDocid += iDelta;
126225 }else{
126226 pDL->iDocid -= iDelta;
126227 }
126228 pDL->pList = pIter;
126229 fts3PoslistCopy(0, &pIter);
126230 pDL->nList = (int)(pIter - pDL->pList);
126231
126232 /* pIter now points just past the 0x00 that terminates the position-
126233 ** list for document pDL->iDocid. However, if this position-list was
126234 ** edited in place by fts3EvalNearTrim(), then pIter may not actually
126235 ** point to the start of the next docid value. The following line deals
126236 ** with this case by advancing pIter past the zero-padding added by
126237 ** fts3EvalNearTrim(). */
126238 while( pIter<pEnd && *pIter==0 ) pIter++;
126239
126240 pDL->pNextDocid = pIter;
126241 assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
126242 *pbEof = 0;
126243 }
126244 }
126245
126246 /*
126247 ** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
126248 */
126249 typedef struct TokenDoclist TokenDoclist;
126250 struct TokenDoclist {
126251 int bIgnore;
126252 sqlite3_int64 iDocid;
126253 char *pList;
126254 int nList;
126255 };
126256
126257 /*
126258 ** Token pToken is an incrementally loaded token that is part of a
126259 ** multi-token phrase. Advance it to the next matching document in the
126260 ** database and populate output variable *p with the details of the new
126261 ** entry. Or, if the iterator has reached EOF, set *pbEof to true.
126262 **
126263 ** If an error occurs, return an SQLite error code. Otherwise, return
126264 ** SQLITE_OK.
126265 */
126266 static int incrPhraseTokenNext(
126267 Fts3Table *pTab, /* Virtual table handle */
126268 Fts3Phrase *pPhrase, /* Phrase to advance token of */
126269 int iToken, /* Specific token to advance */
126270 TokenDoclist *p, /* OUT: Docid and doclist for new entry */
126271 u8 *pbEof /* OUT: True if iterator is at EOF */
126272 ){
126273 int rc = SQLITE_OK;
126274
126275 if( pPhrase->iDoclistToken==iToken ){
126276 assert( p->bIgnore==0 );
126277 assert( pPhrase->aToken[iToken].pSegcsr==0 );
126278 fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
126279 p->pList = pPhrase->doclist.pList;
126280 p->nList = pPhrase->doclist.nList;
126281 p->iDocid = pPhrase->doclist.iDocid;
126282 }else{
126283 Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
126284 assert( pToken->pDeferred==0 );
126285 assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
126286 if( pToken->pSegcsr ){
126287 assert( p->bIgnore==0 );
126288 rc = sqlite3Fts3MsrIncrNext(
126289 pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
126290 );
126291 if( p->pList==0 ) *pbEof = 1;
126292 }else{
126293 p->bIgnore = 1;
126294 }
126295 }
126296
126297 return rc;
126298 }
126299
126300
126301 /*
126302 ** The phrase iterator passed as the second argument:
126303 **
126304 ** * features at least one token that uses an incremental doclist, and
126305 **
126306 ** * does not contain any deferred tokens.
126307 **
126308 ** Advance it to the next matching documnent in the database and populate
126309 ** the Fts3Doclist.pList and nList fields.
126310 **
126311 ** If there is no "next" entry and no error occurs, then *pbEof is set to
126312 ** 1 before returning. Otherwise, if no error occurs and the iterator is
126313 ** successfully advanced, *pbEof is set to 0.
126314 **
126315 ** If an error occurs, return an SQLite error code. Otherwise, return
126316 ** SQLITE_OK.
126317 */
126318 static int fts3EvalIncrPhraseNext(
126319 Fts3Cursor *pCsr, /* FTS Cursor handle */
126320 Fts3Phrase *p, /* Phrase object to advance to next docid */
126321 u8 *pbEof /* OUT: Set to 1 if EOF */
126322 ){
126323 int rc = SQLITE_OK;
126324 Fts3Doclist *pDL = &p->doclist;
126325 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126326 u8 bEof = 0;
126327
126328 /* This is only called if it is guaranteed that the phrase has at least
126329 ** one incremental token. In which case the bIncr flag is set. */
126330 assert( p->bIncr==1 );
126331
126332 if( p->nToken==1 && p->bIncr ){
126333 rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
126334 &pDL->iDocid, &pDL->pList, &pDL->nList
126335 );
126336 if( pDL->pList==0 ) bEof = 1;
126337 }else{
126338 int bDescDoclist = pCsr->bDesc;
126339 struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
126340
126341 memset(a, 0, sizeof(a));
126342 assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
126343 assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
126344
126345 while( bEof==0 ){
126346 int bMaxSet = 0;
126347 sqlite3_int64 iMax = 0; /* Largest docid for all iterators */
126348 int i; /* Used to iterate through tokens */
126349
126350 /* Advance the iterator for each token in the phrase once. */
126351 for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
126352 rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126353 if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
126354 iMax = a[i].iDocid;
126355 bMaxSet = 1;
126356 }
126357 }
126358 assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
126359 assert( rc!=SQLITE_OK || bMaxSet );
126360
126361 /* Keep advancing iterators until they all point to the same document */
126362 for(i=0; i<p->nToken; i++){
126363 while( rc==SQLITE_OK && bEof==0
126364 && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
126365 ){
126366 rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
126367 if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
126368 iMax = a[i].iDocid;
126369 i = 0;
126370 }
126371 }
126372 }
126373
126374 /* Check if the current entries really are a phrase match */
126375 if( bEof==0 ){
126376 int nList = 0;
126377 int nByte = a[p->nToken-1].nList;
126378 char *aDoclist = sqlite3_malloc(nByte+1);
126379 if( !aDoclist ) return SQLITE_NOMEM;
126380 memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
126381
126382 for(i=0; i<(p->nToken-1); i++){
126383 if( a[i].bIgnore==0 ){
126384 char *pL = a[i].pList;
126385 char *pR = aDoclist;
126386 char *pOut = aDoclist;
126387 int nDist = p->nToken-1-i;
126388 int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
126389 if( res==0 ) break;
126390 nList = (int)(pOut - aDoclist);
126391 }
126392 }
126393 if( i==(p->nToken-1) ){
126394 pDL->iDocid = iMax;
126395 pDL->pList = aDoclist;
126396 pDL->nList = nList;
126397 pDL->bFreeList = 1;
126398 break;
126399 }
126400 sqlite3_free(aDoclist);
126401 }
126402 }
126403 }
126404
126405 *pbEof = bEof;
126406 return rc;
126407 }
126408
126409 /*
126410 ** Attempt to move the phrase iterator to point to the next matching docid.
126411 ** If an error occurs, return an SQLite error code. Otherwise, return
126412 ** SQLITE_OK.
@@ -125700,59 +126423,18 @@
126423 int rc = SQLITE_OK;
126424 Fts3Doclist *pDL = &p->doclist;
126425 Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
126426
126427 if( p->bIncr ){
126428 rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
 
 
 
 
 
 
 
126429 }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
126430 sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
126431 &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
126432 );
126433 pDL->pList = pDL->pNextDocid;
126434 }else{
126435 fts3EvalDlPhraseNext(pTab, pDL, pbEof);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126436 }
126437
126438 return rc;
126439 }
126440
@@ -125773,11 +126455,10 @@
126455 ** code before returning.
126456 */
126457 static void fts3EvalStartReaders(
126458 Fts3Cursor *pCsr, /* FTS Cursor handle */
126459 Fts3Expr *pExpr, /* Expression to initialize phrases in */
 
126460 int *pRc /* IN/OUT: Error code */
126461 ){
126462 if( pExpr && SQLITE_OK==*pRc ){
126463 if( pExpr->eType==FTSQUERY_PHRASE ){
126464 int i;
@@ -125784,14 +126465,14 @@
126465 int nToken = pExpr->pPhrase->nToken;
126466 for(i=0; i<nToken; i++){
126467 if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
126468 }
126469 pExpr->bDeferred = (i==nToken);
126470 *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
126471 }else{
126472 fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
126473 fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
126474 pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
126475 }
126476 }
126477 }
126478
@@ -126029,11 +126710,11 @@
126710 /* Set nLoad4 to the value of (4^nOther) for the next iteration of the
126711 ** for-loop. Except, limit the value to 2^24 to prevent it from
126712 ** overflowing the 32-bit integer it is stored in. */
126713 if( ii<12 ) nLoad4 = nLoad4*4;
126714
126715 if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
126716 /* Either this is the cheapest token in the entire query, or it is
126717 ** part of a multi-token phrase. Either way, the entire doclist will
126718 ** (eventually) be loaded into memory. It may as well be now. */
126719 Fts3PhraseToken *pToken = pTC->pToken;
126720 int nList = 0;
@@ -126109,11 +126790,11 @@
126790 sqlite3_free(aTC);
126791 }
126792 }
126793 #endif
126794
126795 fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
126796 return rc;
126797 }
126798
126799 /*
126800 ** Invalidate the current position list for phrase pPhrase.
@@ -126592,10 +127273,20 @@
127273 pCsr->isRequireSeek = 1;
127274 pCsr->isMatchinfoNeeded = 1;
127275 pCsr->iPrevId = pExpr->iDocid;
127276 }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
127277 }
127278
127279 /* Check if the cursor is past the end of the docid range specified
127280 ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
127281 if( rc==SQLITE_OK && (
127282 (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
127283 || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
127284 )){
127285 pCsr->isEof = 1;
127286 }
127287
127288 return rc;
127289 }
127290
127291 /*
127292 ** Restart interation for expression pExpr so that the next call to
@@ -126615,16 +127306,20 @@
127306 Fts3Phrase *pPhrase = pExpr->pPhrase;
127307
127308 if( pPhrase ){
127309 fts3EvalInvalidatePoslist(pPhrase);
127310 if( pPhrase->bIncr ){
127311 int i;
127312 for(i=0; i<pPhrase->nToken; i++){
127313 Fts3PhraseToken *pToken = &pPhrase->aToken[i];
127314 assert( pToken->pDeferred==0 );
127315 if( pToken->pSegcsr ){
127316 sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
127317 }
127318 }
127319 *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
127320 }
 
127321 pPhrase->doclist.pNextDocid = 0;
127322 pPhrase->doclist.iDocid = 0;
127323 }
127324
127325 pExpr->iDocid = 0;
@@ -126869,19 +127564,27 @@
127564
127565 iDocid = pExpr->iDocid;
127566 pIter = pPhrase->doclist.pList;
127567 if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
127568 int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
127569 int iMul; /* +1 if csr dir matches index dir, else -1 */
127570 int bOr = 0;
127571 u8 bEof = 0;
127572 u8 bTreeEof = 0;
127573 Fts3Expr *p; /* Used to iterate from pExpr to root */
127574 Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
127575
127576 /* Check if this phrase descends from an OR expression node. If not,
127577 ** return NULL. Otherwise, the entry that corresponds to docid
127578 ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
127579 ** tree that the node is part of has been marked as EOF, but the node
127580 ** itself is not EOF, then it may point to an earlier entry. */
127581 pNear = pExpr;
127582 for(p=pExpr->pParent; p; p=p->pParent){
127583 if( p->eType==FTSQUERY_OR ) bOr = 1;
127584 if( p->eType==FTSQUERY_NEAR ) pNear = p;
127585 if( p->bEof ) bTreeEof = 1;
127586 }
127587 if( bOr==0 ) return SQLITE_OK;
127588
127589 /* This is the descendent of an OR node. In this case we cannot use
127590 ** an incremental phrase. Load the entire doclist for the phrase
@@ -126896,33 +127599,63 @@
127599 }
127600 pIter = pPhrase->doclist.pList;
127601 assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
127602 if( rc!=SQLITE_OK ) return rc;
127603 }
127604
127605 iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
127606 while( bTreeEof==1
127607 && pNear->bEof==0
127608 && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
127609 ){
127610 int rc = SQLITE_OK;
127611 fts3EvalNextRow(pCsr, pExpr, &rc);
127612 if( rc!=SQLITE_OK ) return rc;
127613 iDocid = pExpr->iDocid;
127614 pIter = pPhrase->doclist.pList;
127615 }
127616
 
 
 
 
127617 bEof = (pPhrase->doclist.nAll==0);
127618 assert( bDescDoclist==0 || bDescDoclist==1 );
127619 assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
127620
127621 if( bEof==0 ){
127622 if( pCsr->bDesc==bDescDoclist ){
127623 int dummy;
127624 if( pNear->bEof ){
127625 /* This expression is already at EOF. So position it to point to the
127626 ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
127627 ** iDocid is already set for this entry, so all that is required is
127628 ** to set pIter to point to the first byte of the last position-list
127629 ** in the doclist.
127630 **
127631 ** It would also be correct to set pIter and iDocid to zero. In
127632 ** this case, the first call to sqltie3Fts4DoclistPrev() below
127633 ** would also move the iterator to point to the last entry in the
127634 ** doclist. However, this is expensive, as to do so it has to
127635 ** iterate through the entire doclist from start to finish (since
127636 ** it does not know the docid for the last entry). */
127637 pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
127638 fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
127639 }
127640 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
127641 sqlite3Fts3DoclistPrev(
127642 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127643 &pIter, &iDocid, &dummy, &bEof
127644 );
127645 }
127646 }else{
127647 if( pNear->bEof ){
127648 pIter = 0;
127649 iDocid = 0;
127650 }
127651 while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
127652 sqlite3Fts3DoclistNext(
127653 bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
127654 &pIter, &iDocid, &bEof
127655 );
127656 }
127657 }
127658 }
127659
127660 if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0;
127661 }
@@ -127026,10 +127759,11 @@
127759 sqlite3_vtab_cursor base; /* Base class used by SQLite core */
127760 Fts3MultiSegReader csr; /* Must be right after "base" */
127761 Fts3SegFilter filter;
127762 char *zStop;
127763 int nStop; /* Byte-length of string zStop */
127764 int iLangid; /* Language id to query */
127765 int isEof; /* True if cursor is at EOF */
127766 sqlite3_int64 iRowid; /* Current rowid */
127767
127768 int iCol; /* Current value of 'col' column */
127769 int nStat; /* Size of aStat[] array */
@@ -127040,11 +127774,12 @@
127774 };
127775
127776 /*
127777 ** Schema of the terms table.
127778 */
127779 #define FTS3_AUX_SCHEMA \
127780 "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
127781
127782 /*
127783 ** This function does all the work for both the xConnect and xCreate methods.
127784 ** These tables have no persistent representation of their own, so xConnect
127785 ** and xCreate are identical operations.
@@ -127087,11 +127822,11 @@
127822 }else{
127823 zFts3 = argv[3];
127824 }
127825 nFts3 = (int)strlen(zFts3);
127826
127827 rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
127828 if( rc!=SQLITE_OK ) return rc;
127829
127830 nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
127831 p = (Fts3auxTable *)sqlite3_malloc(nByte);
127832 if( !p ) return SQLITE_NOMEM;
@@ -127147,10 +127882,12 @@
127882 ){
127883 int i;
127884 int iEq = -1;
127885 int iGe = -1;
127886 int iLe = -1;
127887 int iLangid = -1;
127888 int iNext = 1; /* Next free argvIndex value */
127889
127890 UNUSED_PARAMETER(pVTab);
127891
127892 /* This vtab delivers always results in "ORDER BY term ASC" order. */
127893 if( pInfo->nOrderBy==1
@@ -127158,40 +127895,52 @@
127895 && pInfo->aOrderBy[0].desc==0
127896 ){
127897 pInfo->orderByConsumed = 1;
127898 }
127899
127900 /* Search for equality and range constraints on the "term" column.
127901 ** And equality constraints on the hidden "languageid" column. */
127902 for(i=0; i<pInfo->nConstraint; i++){
127903 if( pInfo->aConstraint[i].usable ){
127904 int op = pInfo->aConstraint[i].op;
127905 int iCol = pInfo->aConstraint[i].iColumn;
127906
127907 if( iCol==0 ){
127908 if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
127909 if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
127910 if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
127911 if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
127912 if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
127913 }
127914 if( iCol==4 ){
127915 if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
127916 }
127917 }
127918 }
127919
127920 if( iEq>=0 ){
127921 pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
127922 pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
127923 pInfo->estimatedCost = 5;
127924 }else{
127925 pInfo->idxNum = 0;
127926 pInfo->estimatedCost = 20000;
127927 if( iGe>=0 ){
127928 pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
127929 pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
127930 pInfo->estimatedCost /= 2;
127931 }
127932 if( iLe>=0 ){
127933 pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
127934 pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
127935 pInfo->estimatedCost /= 2;
127936 }
127937 }
127938 if( iLangid>=0 ){
127939 pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
127940 pInfo->estimatedCost--;
127941 }
127942
127943 return SQLITE_OK;
127944 }
127945
127946 /*
@@ -127347,21 +128096,42 @@
128096 sqlite3_value **apVal /* Arguments for the indexing scheme */
128097 ){
128098 Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
128099 Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
128100 int rc;
128101 int isScan = 0;
128102 int iLangVal = 0; /* Language id to query */
128103
128104 int iEq = -1; /* Index of term=? value in apVal */
128105 int iGe = -1; /* Index of term>=? value in apVal */
128106 int iLe = -1; /* Index of term<=? value in apVal */
128107 int iLangid = -1; /* Index of languageid=? value in apVal */
128108 int iNext = 0;
128109
128110 UNUSED_PARAMETER(nVal);
128111 UNUSED_PARAMETER(idxStr);
128112
128113 assert( idxStr==0 );
128114 assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
128115 || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
128116 || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
128117 );
128118
128119 if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
128120 iEq = iNext++;
128121 }else{
128122 isScan = 1;
128123 if( idxNum & FTS4AUX_GE_CONSTRAINT ){
128124 iGe = iNext++;
128125 }
128126 if( idxNum & FTS4AUX_LE_CONSTRAINT ){
128127 iLe = iNext++;
128128 }
128129 }
128130 if( iNext<nVal ){
128131 iLangid = iNext++;
128132 }
128133
128134 /* In case this cursor is being reused, close and zero it. */
128135 testcase(pCsr->filter.zTerm);
128136 sqlite3Fts3SegReaderFinish(&pCsr->csr);
128137 sqlite3_free((void *)pCsr->filter.zTerm);
@@ -127369,26 +128139,39 @@
128139 memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
128140
128141 pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
128142 if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
128143
128144 if( iEq>=0 || iGe>=0 ){
128145 const unsigned char *zStr = sqlite3_value_text(apVal[0]);
128146 assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
128147 if( zStr ){
128148 pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
128149 pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
128150 if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
128151 }
128152 }
128153
128154 if( iLe>=0 ){
128155 pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
128156 pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
128157 if( pCsr->zStop==0 ) return SQLITE_NOMEM;
128158 }
128159
128160 if( iLangid>=0 ){
128161 iLangVal = sqlite3_value_int(apVal[iLangid]);
128162
128163 /* If the user specified a negative value for the languageid, use zero
128164 ** instead. This works, as the "languageid=?" constraint will also
128165 ** be tested by the VDBE layer. The test will always be false (since
128166 ** this module will not return a row with a negative languageid), and
128167 ** so the overall query will return zero rows. */
128168 if( iLangVal<0 ) iLangVal = 0;
128169 }
128170 pCsr->iLangid = iLangVal;
128171
128172 rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
128173 pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
128174 );
128175 if( rc==SQLITE_OK ){
128176 rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
128177 }
@@ -127408,28 +128191,41 @@
128191 /*
128192 ** xColumn - Return a column value.
128193 */
128194 static int fts3auxColumnMethod(
128195 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
128196 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
128197 int iCol /* Index of column to read value from */
128198 ){
128199 Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
128200
128201 assert( p->isEof==0 );
128202 switch( iCol ){
128203 case 0: /* term */
128204 sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
128205 break;
128206
128207 case 1: /* col */
128208 if( p->iCol ){
128209 sqlite3_result_int(pCtx, p->iCol-1);
128210 }else{
128211 sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
128212 }
128213 break;
128214
128215 case 2: /* documents */
128216 sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
128217 break;
128218
128219 case 3: /* occurrences */
128220 sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
128221 break;
128222
128223 default: /* languageid */
128224 assert( iCol==4 );
128225 sqlite3_result_int(pCtx, p->iLangid);
128226 break;
128227 }
128228
128229 return SQLITE_OK;
128230 }
128231
@@ -135756,11 +136552,11 @@
136552 assert( p->bFts4==0 );
136553 sqlite3Fts3CreateStatTable(&rc, p);
136554 if( rc ) return rc;
136555 }
136556 rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
136557 if( rc ) return rc;
136558 sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
136559 sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
136560 sqlite3_step(pStmt);
136561 rc = sqlite3_reset(pStmt);
136562 return rc;
@@ -136025,10 +136821,13 @@
136821 }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
136822 p->nNodeSize = atoi(&zVal[9]);
136823 rc = SQLITE_OK;
136824 }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
136825 p->nMaxPendingData = atoi(&zVal[11]);
136826 rc = SQLITE_OK;
136827 }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
136828 p->bNoIncrDoclist = atoi(&zVal[21]);
136829 rc = SQLITE_OK;
136830 #endif
136831 }else{
136832 rc = SQLITE_ERROR;
136833 }
136834
+14 -14
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.8.1"
111111
#define SQLITE_VERSION_NUMBER 3008001
112
-#define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
112
+#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -1615,31 +1615,31 @@
16151615
** supplied by the application must not invoke any SQLite interface.
16161616
** In a multi-threaded application, the application-defined logger
16171617
** function must be threadsafe. </dd>
16181618
**
16191619
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1620
-** <dd> This option takes a single argument of type int. If non-zero, then
1620
+** <dd>^(This option takes a single argument of type int. If non-zero, then
16211621
** URI handling is globally enabled. If the parameter is zero, then URI handling
1622
-** is globally disabled. If URI handling is globally enabled, all filenames
1622
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
16231623
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
16241624
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
16251625
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1626
-** connection is opened. If it is globally disabled, filenames are
1626
+** connection is opened. ^If it is globally disabled, filenames are
16271627
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1628
-** database connection is opened. By default, URI handling is globally
1628
+** database connection is opened. ^(By default, URI handling is globally
16291629
** disabled. The default value may be changed by compiling with the
1630
-** [SQLITE_USE_URI] symbol defined.
1630
+** [SQLITE_USE_URI] symbol defined.)^
16311631
**
16321632
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1633
-** <dd> This option takes a single integer argument which is interpreted as
1633
+** <dd>^This option takes a single integer argument which is interpreted as
16341634
** a boolean in order to enable or disable the use of covering indices for
1635
-** full table scans in the query optimizer. The default setting is determined
1635
+** full table scans in the query optimizer. ^The default setting is determined
16361636
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
16371637
** if that compile-time option is omitted.
16381638
** The ability to disable the use of covering indices for full table scans
16391639
** is because some incorrectly coded legacy applications might malfunction
1640
-** malfunction when the optimization is enabled. Providing the ability to
1640
+** when the optimization is enabled. Providing the ability to
16411641
** disable the optimization allows the older, buggy application code to work
16421642
** without change even with newer versions of SQLite.
16431643
**
16441644
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
16451645
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -1664,20 +1664,20 @@
16641664
** configuration option can be seen in the "test_sqllog.c" source file in
16651665
** the canonical SQLite source tree.</dd>
16661666
**
16671667
** [[SQLITE_CONFIG_MMAP_SIZE]]
16681668
** <dt>SQLITE_CONFIG_MMAP_SIZE
1669
-** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
1669
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
16701670
** that are the default mmap size limit (the default setting for
16711671
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
1672
-** The default setting can be overridden by each database connection using
1672
+** ^The default setting can be overridden by each database connection using
16731673
** either the [PRAGMA mmap_size] command, or by using the
1674
-** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
1674
+** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
16751675
** cannot be changed at run-time. Nor may the maximum allowed mmap size
16761676
** exceed the compile-time maximum mmap size set by the
1677
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.
1678
-** If either argument to this option is negative, then that argument is
1677
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
1678
+** ^If either argument to this option is negative, then that argument is
16791679
** changed to its compile-time default.
16801680
** </dl>
16811681
*/
16821682
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
16831683
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
16841684
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.1"
111 #define SQLITE_VERSION_NUMBER 3008001
112 #define SQLITE_SOURCE_ID "2013-09-16 12:57:19 daf6ba413cb3cb6065774ba07495eab4a28b49b0"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -1615,31 +1615,31 @@
1615 ** supplied by the application must not invoke any SQLite interface.
1616 ** In a multi-threaded application, the application-defined logger
1617 ** function must be threadsafe. </dd>
1618 **
1619 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1620 ** <dd> This option takes a single argument of type int. If non-zero, then
1621 ** URI handling is globally enabled. If the parameter is zero, then URI handling
1622 ** is globally disabled. If URI handling is globally enabled, all filenames
1623 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1624 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1625 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1626 ** connection is opened. If it is globally disabled, filenames are
1627 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1628 ** database connection is opened. By default, URI handling is globally
1629 ** disabled. The default value may be changed by compiling with the
1630 ** [SQLITE_USE_URI] symbol defined.
1631 **
1632 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1633 ** <dd> This option takes a single integer argument which is interpreted as
1634 ** a boolean in order to enable or disable the use of covering indices for
1635 ** full table scans in the query optimizer. The default setting is determined
1636 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
1637 ** if that compile-time option is omitted.
1638 ** The ability to disable the use of covering indices for full table scans
1639 ** is because some incorrectly coded legacy applications might malfunction
1640 ** malfunction when the optimization is enabled. Providing the ability to
1641 ** disable the optimization allows the older, buggy application code to work
1642 ** without change even with newer versions of SQLite.
1643 **
1644 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
1645 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -1664,20 +1664,20 @@
1664 ** configuration option can be seen in the "test_sqllog.c" source file in
1665 ** the canonical SQLite source tree.</dd>
1666 **
1667 ** [[SQLITE_CONFIG_MMAP_SIZE]]
1668 ** <dt>SQLITE_CONFIG_MMAP_SIZE
1669 ** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
1670 ** that are the default mmap size limit (the default setting for
1671 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
1672 ** The default setting can be overridden by each database connection using
1673 ** either the [PRAGMA mmap_size] command, or by using the
1674 ** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
1675 ** cannot be changed at run-time. Nor may the maximum allowed mmap size
1676 ** exceed the compile-time maximum mmap size set by the
1677 ** [SQLITE_MAX_MMAP_SIZE] compile-time option.
1678 ** If either argument to this option is negative, then that argument is
1679 ** changed to its compile-time default.
1680 ** </dl>
1681 */
1682 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1683 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1684
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.1"
111 #define SQLITE_VERSION_NUMBER 3008001
112 #define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -1615,31 +1615,31 @@
1615 ** supplied by the application must not invoke any SQLite interface.
1616 ** In a multi-threaded application, the application-defined logger
1617 ** function must be threadsafe. </dd>
1618 **
1619 ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
1620 ** <dd>^(This option takes a single argument of type int. If non-zero, then
1621 ** URI handling is globally enabled. If the parameter is zero, then URI handling
1622 ** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
1623 ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
1624 ** specified as part of [ATTACH] commands are interpreted as URIs, regardless
1625 ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
1626 ** connection is opened. ^If it is globally disabled, filenames are
1627 ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
1628 ** database connection is opened. ^(By default, URI handling is globally
1629 ** disabled. The default value may be changed by compiling with the
1630 ** [SQLITE_USE_URI] symbol defined.)^
1631 **
1632 ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
1633 ** <dd>^This option takes a single integer argument which is interpreted as
1634 ** a boolean in order to enable or disable the use of covering indices for
1635 ** full table scans in the query optimizer. ^The default setting is determined
1636 ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
1637 ** if that compile-time option is omitted.
1638 ** The ability to disable the use of covering indices for full table scans
1639 ** is because some incorrectly coded legacy applications might malfunction
1640 ** when the optimization is enabled. Providing the ability to
1641 ** disable the optimization allows the older, buggy application code to work
1642 ** without change even with newer versions of SQLite.
1643 **
1644 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
1645 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
@@ -1664,20 +1664,20 @@
1664 ** configuration option can be seen in the "test_sqllog.c" source file in
1665 ** the canonical SQLite source tree.</dd>
1666 **
1667 ** [[SQLITE_CONFIG_MMAP_SIZE]]
1668 ** <dt>SQLITE_CONFIG_MMAP_SIZE
1669 ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
1670 ** that are the default mmap size limit (the default setting for
1671 ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
1672 ** ^The default setting can be overridden by each database connection using
1673 ** either the [PRAGMA mmap_size] command, or by using the
1674 ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
1675 ** cannot be changed at run-time. Nor may the maximum allowed mmap size
1676 ** exceed the compile-time maximum mmap size set by the
1677 ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
1678 ** ^If either argument to this option is negative, then that argument is
1679 ** changed to its compile-time default.
1680 ** </dl>
1681 */
1682 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
1683 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
1684
+1 -1
--- src/stat.c
+++ src/stat.c
@@ -16,12 +16,12 @@
1616
*******************************************************************************
1717
**
1818
** This file contains code to implement the stat web page
1919
**
2020
*/
21
-#include <string.h>
2221
#include "config.h"
22
+#include <string.h>
2323
#include "stat.h"
2424
2525
/*
2626
** For a sufficiently large integer, provide an alternative
2727
** representation as MB or GB or TB.
2828
--- src/stat.c
+++ src/stat.c
@@ -16,12 +16,12 @@
16 *******************************************************************************
17 **
18 ** This file contains code to implement the stat web page
19 **
20 */
21 #include <string.h>
22 #include "config.h"
 
23 #include "stat.h"
24
25 /*
26 ** For a sufficiently large integer, provide an alternative
27 ** representation as MB or GB or TB.
28
--- src/stat.c
+++ src/stat.c
@@ -16,12 +16,12 @@
16 *******************************************************************************
17 **
18 ** This file contains code to implement the stat web page
19 **
20 */
 
21 #include "config.h"
22 #include <string.h>
23 #include "stat.h"
24
25 /*
26 ** For a sufficiently large integer, provide an alternative
27 ** representation as MB or GB or TB.
28
+2 -1
--- src/style.c
+++ src/style.c
@@ -686,10 +686,11 @@
686686
},
687687
{ "td.timelineTime",
688688
"the format for the timeline time display",
689689
@ vertical-align: top;
690690
@ text-align: right;
691
+ @ white-space: nowrap;
691692
},
692693
{ "td.timelineGraph",
693694
"the format for the grap placeholder cells in timelines",
694695
@ width: 20px;
695696
@ text-align: left;
@@ -1225,7 +1226,7 @@
12251226
**
12261227
** WEBPAGE: honeypot
12271228
*/
12281229
void honeypot_page(void){
12291230
cgi_set_status(403, "Forbidden");
1230
- @ <p>Access by spiders and robots is forbidden</p>
1231
+ @ <p>Please enable javascript or log in to see this content</p>
12311232
}
12321233
--- src/style.c
+++ src/style.c
@@ -686,10 +686,11 @@
686 },
687 { "td.timelineTime",
688 "the format for the timeline time display",
689 @ vertical-align: top;
690 @ text-align: right;
 
691 },
692 { "td.timelineGraph",
693 "the format for the grap placeholder cells in timelines",
694 @ width: 20px;
695 @ text-align: left;
@@ -1225,7 +1226,7 @@
1225 **
1226 ** WEBPAGE: honeypot
1227 */
1228 void honeypot_page(void){
1229 cgi_set_status(403, "Forbidden");
1230 @ <p>Access by spiders and robots is forbidden</p>
1231 }
1232
--- src/style.c
+++ src/style.c
@@ -686,10 +686,11 @@
686 },
687 { "td.timelineTime",
688 "the format for the timeline time display",
689 @ vertical-align: top;
690 @ text-align: right;
691 @ white-space: nowrap;
692 },
693 { "td.timelineGraph",
694 "the format for the grap placeholder cells in timelines",
695 @ width: 20px;
696 @ text-align: left;
@@ -1225,7 +1226,7 @@
1226 **
1227 ** WEBPAGE: honeypot
1228 */
1229 void honeypot_page(void){
1230 cgi_set_status(403, "Forbidden");
1231 @ <p>Please enable javascript or log in to see this content</p>
1232 }
1233
+6
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
5151
}
5252
url_parse(0, URL_REMEMBER);
5353
if( g.urlProtocol==0 ) return 0;
5454
if( g.urlUser!=0 && g.urlPasswd==0 ){
5555
g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
56
+ g.urlFlags |= URL_PROMPT_PW;
57
+ url_prompt_for_password();
5658
}
5759
#if 0 /* Disabled for now */
5860
if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
5961
/* When doing an automatic pull, also automatically pull shuns from
6062
** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
101103
*/
102104
if( find_option("verily",0,0)!=0 ){
103105
*pSyncFlags |= SYNC_RESYNC;
104106
}
105107
url_proxy_options();
108
+ clone_ssh_find_options();
106109
db_find_and_open_repository(0, 0);
107110
db_open_config(0);
108111
if( g.argc==2 ){
109112
if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
110113
}else if( g.argc==3 ){
111114
zUrl = g.argv[2];
115
+ }
116
+ if( urlFlags & URL_REMEMBER ){
117
+ clone_ssh_db_set_options();
112118
}
113119
url_parse(zUrl, urlFlags);
114120
if( g.urlProtocol==0 ){
115121
if( urlOptional ) fossil_exit(0);
116122
usage("URL");
117123
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
51 }
52 url_parse(0, URL_REMEMBER);
53 if( g.urlProtocol==0 ) return 0;
54 if( g.urlUser!=0 && g.urlPasswd==0 ){
55 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
 
 
56 }
57 #if 0 /* Disabled for now */
58 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
59 /* When doing an automatic pull, also automatically pull shuns from
60 ** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
101 */
102 if( find_option("verily",0,0)!=0 ){
103 *pSyncFlags |= SYNC_RESYNC;
104 }
105 url_proxy_options();
 
106 db_find_and_open_repository(0, 0);
107 db_open_config(0);
108 if( g.argc==2 ){
109 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
110 }else if( g.argc==3 ){
111 zUrl = g.argv[2];
 
 
 
112 }
113 url_parse(zUrl, urlFlags);
114 if( g.urlProtocol==0 ){
115 if( urlOptional ) fossil_exit(0);
116 usage("URL");
117
--- src/sync.c
+++ src/sync.c
@@ -51,10 +51,12 @@
51 }
52 url_parse(0, URL_REMEMBER);
53 if( g.urlProtocol==0 ) return 0;
54 if( g.urlUser!=0 && g.urlPasswd==0 ){
55 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
56 g.urlFlags |= URL_PROMPT_PW;
57 url_prompt_for_password();
58 }
59 #if 0 /* Disabled for now */
60 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
61 /* When doing an automatic pull, also automatically pull shuns from
62 ** the server if pull_shuns is enabled.
@@ -101,16 +103,20 @@
103 */
104 if( find_option("verily",0,0)!=0 ){
105 *pSyncFlags |= SYNC_RESYNC;
106 }
107 url_proxy_options();
108 clone_ssh_find_options();
109 db_find_and_open_repository(0, 0);
110 db_open_config(0);
111 if( g.argc==2 ){
112 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
113 }else if( g.argc==3 ){
114 zUrl = g.argv[2];
115 }
116 if( urlFlags & URL_REMEMBER ){
117 clone_ssh_db_set_options();
118 }
119 url_parse(zUrl, urlFlags);
120 if( g.urlProtocol==0 ){
121 if( urlOptional ) fossil_exit(0);
122 usage("URL");
123
+3 -6
--- src/tag.c
+++ src/tag.c
@@ -389,11 +389,11 @@
389389
int n;
390390
int fRaw = find_option("raw","",0)!=0;
391391
int fPropagate = find_option("propagate","",0)!=0;
392392
const char *zPrefix = fRaw ? "" : "sym-";
393393
char const * zFindLimit = find_option("limit","n",1);
394
- int const nFindLimit = zFindLimit ? atoi(zFindLimit) : 0;
394
+ int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
395395
396396
db_find_and_open_repository(0, 0);
397397
if( g.argc<3 ){
398398
goto tag_cmd_usage;
399399
}
@@ -444,11 +444,11 @@
444444
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
445445
" AND tagxref.tagtype>0"
446446
" AND blob.rid=tagxref.rid",
447447
g.argv[3]
448448
);
449
- if(nFindLimit>0){
449
+ if( nFindLimit>0 ){
450450
blob_appendf(&sql, " LIMIT %d", nFindLimit);
451451
}
452452
db_prepare(&q, "%s", blob_str(&sql));
453453
blob_reset(&sql);
454454
while( db_step(&q)==SQLITE_ROW ){
@@ -467,16 +467,13 @@
467467
" WHERE tagtype>0 AND tagid=%d"
468468
")"
469469
" ORDER BY event.mtime DESC",
470470
timeline_query_for_tty(), zType, tagid
471471
);
472
- if(nFindLimit>0){
473
- blob_appendf(&sql, " LIMIT %d", nFindLimit);
474
- }
475472
db_prepare(&q, "%s", blob_str(&sql));
476473
blob_reset(&sql);
477
- print_timeline(&q, 2000, 0);
474
+ print_timeline(&q, nFindLimit, 79, 0);
478475
db_finalize(&q);
479476
}
480477
}
481478
}else
482479
483480
--- src/tag.c
+++ src/tag.c
@@ -389,11 +389,11 @@
389 int n;
390 int fRaw = find_option("raw","",0)!=0;
391 int fPropagate = find_option("propagate","",0)!=0;
392 const char *zPrefix = fRaw ? "" : "sym-";
393 char const * zFindLimit = find_option("limit","n",1);
394 int const nFindLimit = zFindLimit ? atoi(zFindLimit) : 0;
395
396 db_find_and_open_repository(0, 0);
397 if( g.argc<3 ){
398 goto tag_cmd_usage;
399 }
@@ -444,11 +444,11 @@
444 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
445 " AND tagxref.tagtype>0"
446 " AND blob.rid=tagxref.rid",
447 g.argv[3]
448 );
449 if(nFindLimit>0){
450 blob_appendf(&sql, " LIMIT %d", nFindLimit);
451 }
452 db_prepare(&q, "%s", blob_str(&sql));
453 blob_reset(&sql);
454 while( db_step(&q)==SQLITE_ROW ){
@@ -467,16 +467,13 @@
467 " WHERE tagtype>0 AND tagid=%d"
468 ")"
469 " ORDER BY event.mtime DESC",
470 timeline_query_for_tty(), zType, tagid
471 );
472 if(nFindLimit>0){
473 blob_appendf(&sql, " LIMIT %d", nFindLimit);
474 }
475 db_prepare(&q, "%s", blob_str(&sql));
476 blob_reset(&sql);
477 print_timeline(&q, 2000, 0);
478 db_finalize(&q);
479 }
480 }
481 }else
482
483
--- src/tag.c
+++ src/tag.c
@@ -389,11 +389,11 @@
389 int n;
390 int fRaw = find_option("raw","",0)!=0;
391 int fPropagate = find_option("propagate","",0)!=0;
392 const char *zPrefix = fRaw ? "" : "sym-";
393 char const * zFindLimit = find_option("limit","n",1);
394 int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
395
396 db_find_and_open_repository(0, 0);
397 if( g.argc<3 ){
398 goto tag_cmd_usage;
399 }
@@ -444,11 +444,11 @@
444 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
445 " AND tagxref.tagtype>0"
446 " AND blob.rid=tagxref.rid",
447 g.argv[3]
448 );
449 if( nFindLimit>0 ){
450 blob_appendf(&sql, " LIMIT %d", nFindLimit);
451 }
452 db_prepare(&q, "%s", blob_str(&sql));
453 blob_reset(&sql);
454 while( db_step(&q)==SQLITE_ROW ){
@@ -467,16 +467,13 @@
467 " WHERE tagtype>0 AND tagid=%d"
468 ")"
469 " ORDER BY event.mtime DESC",
470 timeline_query_for_tty(), zType, tagid
471 );
 
 
 
472 db_prepare(&q, "%s", blob_str(&sql));
473 blob_reset(&sql);
474 print_timeline(&q, nFindLimit, 79, 0);
475 db_finalize(&q);
476 }
477 }
478 }else
479
480
+2 -2
--- src/tar.c
+++ src/tar.c
@@ -15,13 +15,13 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code used to generate tarballs.
1919
*/
20
+#include "config.h"
2021
#include <assert.h>
2122
#include <zlib.h>
22
-#include "config.h"
2323
#include "tar.h"
2424
2525
/*
2626
** State information for the tarball builder.
2727
*/
@@ -479,11 +479,11 @@
479479
if( zDir && zDir[0] ){
480480
blob_appendf(&filename, "%s/", zDir);
481481
}
482482
nPrefix = blob_size(&filename);
483483
484
- pManifest = manifest_get(rid, CFTYPE_MANIFEST);
484
+ pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
485485
if( pManifest ){
486486
mTime = (pManifest->rDate - 2440587.5)*86400.0;
487487
tar_begin(mTime);
488488
if( db_get_boolean("manifest", 0) ){
489489
blob_append(&filename, "manifest", -1);
490490
--- src/tar.c
+++ src/tar.c
@@ -15,13 +15,13 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to generate tarballs.
19 */
 
20 #include <assert.h>
21 #include <zlib.h>
22 #include "config.h"
23 #include "tar.h"
24
25 /*
26 ** State information for the tarball builder.
27 */
@@ -479,11 +479,11 @@
479 if( zDir && zDir[0] ){
480 blob_appendf(&filename, "%s/", zDir);
481 }
482 nPrefix = blob_size(&filename);
483
484 pManifest = manifest_get(rid, CFTYPE_MANIFEST);
485 if( pManifest ){
486 mTime = (pManifest->rDate - 2440587.5)*86400.0;
487 tar_begin(mTime);
488 if( db_get_boolean("manifest", 0) ){
489 blob_append(&filename, "manifest", -1);
490
--- src/tar.c
+++ src/tar.c
@@ -15,13 +15,13 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to generate tarballs.
19 */
20 #include "config.h"
21 #include <assert.h>
22 #include <zlib.h>
 
23 #include "tar.h"
24
25 /*
26 ** State information for the tarball builder.
27 */
@@ -479,11 +479,11 @@
479 if( zDir && zDir[0] ){
480 blob_appendf(&filename, "%s/", zDir);
481 }
482 nPrefix = blob_size(&filename);
483
484 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
485 if( pManifest ){
486 mTime = (pManifest->rDate - 2440587.5)*86400.0;
487 tar_begin(mTime);
488 if( db_get_boolean("manifest", 0) ){
489 blob_append(&filename, "manifest", -1);
490
+1 -1
--- src/th.c
+++ src/th.c
@@ -2,10 +2,11 @@
22
/*
33
** The implementation of the TH core. This file contains the parser, and
44
** the implementation of the interface in th.h.
55
*/
66
7
+#include "config.h"
78
#include "th.h"
89
#include <string.h>
910
#include <assert.h>
1011
1112
typedef struct Th_Command Th_Command;
@@ -2354,11 +2355,10 @@
23542355
}
23552356
23562357
#ifndef LONGDOUBLE_TYPE
23572358
# define LONGDOUBLE_TYPE long double
23582359
#endif
2359
-typedef char u8;
23602360
23612361
23622362
/*
23632363
** Return TRUE if z is a pure numeric string. Return FALSE if the
23642364
** string contains any character which is not part of a number. If
23652365
--- src/th.c
+++ src/th.c
@@ -2,10 +2,11 @@
2 /*
3 ** The implementation of the TH core. This file contains the parser, and
4 ** the implementation of the interface in th.h.
5 */
6
 
7 #include "th.h"
8 #include <string.h>
9 #include <assert.h>
10
11 typedef struct Th_Command Th_Command;
@@ -2354,11 +2355,10 @@
2354 }
2355
2356 #ifndef LONGDOUBLE_TYPE
2357 # define LONGDOUBLE_TYPE long double
2358 #endif
2359 typedef char u8;
2360
2361
2362 /*
2363 ** Return TRUE if z is a pure numeric string. Return FALSE if the
2364 ** string contains any character which is not part of a number. If
2365
--- src/th.c
+++ src/th.c
@@ -2,10 +2,11 @@
2 /*
3 ** The implementation of the TH core. This file contains the parser, and
4 ** the implementation of the interface in th.h.
5 */
6
7 #include "config.h"
8 #include "th.h"
9 #include <string.h>
10 #include <assert.h>
11
12 typedef struct Th_Command Th_Command;
@@ -2354,11 +2355,10 @@
2355 }
2356
2357 #ifndef LONGDOUBLE_TYPE
2358 # define LONGDOUBLE_TYPE long double
2359 #endif
 
2360
2361
2362 /*
2363 ** Return TRUE if z is a pure numeric string. Return FALSE if the
2364 ** string contains any character which is not part of a number. If
2365
+1 -2
--- src/th_main.c
+++ src/th_main.c
@@ -529,16 +529,15 @@
529529
void *p,
530530
int argc,
531531
const char **argv,
532532
int *argl
533533
){
534
- int openRepository;
535
-
536534
if( argc!=1 && argc!=2 ){
537535
return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
538536
}
539537
if( argc==2 ){
538
+ int openRepository = 0;
540539
if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){
541540
return TH_ERROR;
542541
}
543542
if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
544543
}
545544
--- src/th_main.c
+++ src/th_main.c
@@ -529,16 +529,15 @@
529 void *p,
530 int argc,
531 const char **argv,
532 int *argl
533 ){
534 int openRepository;
535
536 if( argc!=1 && argc!=2 ){
537 return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
538 }
539 if( argc==2 ){
 
540 if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){
541 return TH_ERROR;
542 }
543 if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
544 }
545
--- src/th_main.c
+++ src/th_main.c
@@ -529,16 +529,15 @@
529 void *p,
530 int argc,
531 const char **argv,
532 int *argl
533 ){
 
 
534 if( argc!=1 && argc!=2 ){
535 return Th_WrongNumArgs(interp, "repository ?BOOLEAN?");
536 }
537 if( argc==2 ){
538 int openRepository = 0;
539 if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){
540 return TH_ERROR;
541 }
542 if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
543 }
544
+19 -19
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -30,24 +30,24 @@
3030
** arguments from TH1 to Tcl.
3131
*/
3232
#define USE_ARGV_TO_OBJV() \
3333
int objc; \
3434
Tcl_Obj **objv; \
35
- int i;
35
+ int obji;
3636
3737
#define COPY_ARGV_TO_OBJV() \
3838
objc = argc-1; \
3939
objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \
40
- for(i=1; i<argc; i++){ \
41
- objv[i-1] = Tcl_NewStringObj(argv[i], argl[i]); \
42
- Tcl_IncrRefCount(objv[i-1]); \
40
+ for(obji=1; obji<argc; obji++){ \
41
+ objv[obji-1] = Tcl_NewStringObj(argv[obji], argl[obji]); \
42
+ Tcl_IncrRefCount(objv[obji-1]); \
4343
}
4444
45
-#define FREE_ARGV_TO_OBJV() \
46
- for(i=1; i<argc; i++){ \
47
- Tcl_DecrRefCount(objv[i-1]); \
48
- } \
45
+#define FREE_ARGV_TO_OBJV() \
46
+ for(obji=1; obji<argc; obji++){ \
47
+ Tcl_DecrRefCount(objv[obji-1]); \
48
+ } \
4949
ckfree((char *)objv);
5050
5151
/*
5252
** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl
5353
** context.
@@ -109,20 +109,20 @@
109109
# define TCL_MINOR_OFFSET (8)
110110
# endif
111111
# endif /* defined(__CYGWIN__) */
112112
# endif /* defined(_WIN32) */
113113
# ifndef TCL_FINDEXECUTABLE_NAME
114
-# define TCL_FINDEXECUTABLE_NAME "_Tcl_FindExecutable"
114
+# define TCL_FINDEXECUTABLE_NAME "_Tcl_FindExecutable\0"
115115
# endif
116116
# ifndef TCL_CREATEINTERP_NAME
117
-# define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp"
117
+# define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp\0"
118118
# endif
119119
# ifndef TCL_DELETEINTERP_NAME
120
-# define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp"
120
+# define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp\0"
121121
# endif
122122
# ifndef TCL_FINALIZE_NAME
123
-# define TCL_FINALIZE_NAME "_Tcl_Finalize"
123
+# define TCL_FINALIZE_NAME "_Tcl_Finalize\0"
124124
# endif
125125
#endif /* defined(USE_TCL_STUBS) */
126126
127127
/*
128128
** The function types for Tcl_FindExecutable and Tcl_CreateInterp are needed
@@ -311,17 +311,17 @@
311311
int rc
312312
){
313313
struct TclContext *tclContext = (struct TclContext *)ctx;
314314
tcl_NotifyProc *xNotifyProc;
315315
316
- if ( !tclContext ){
316
+ if( !tclContext ){
317317
Th_ErrorMessage(interp,
318318
"invalid Tcl context", (const char *)"", 0);
319319
return TH_ERROR;
320320
}
321321
xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
322
- if ( xNotifyProc ){
322
+ if( xNotifyProc ){
323323
rc = xNotifyProc(bIsPost ?
324324
tclContext->pPostContext : tclContext->pPreContext,
325325
interp, ctx, argc, argv, argl, rc);
326326
}
327327
return rc;
@@ -783,16 +783,16 @@
783783
char **argv;
784784
char *argv0 = 0;
785785
Tcl_Interp *tclInterp;
786786
char *setup;
787787
788
- if ( !tclContext ){
788
+ if( !tclContext ){
789789
Th_ErrorMessage(interp,
790790
"invalid Tcl context", (const char *)"", 0);
791791
return TH_ERROR;
792792
}
793
- if ( tclContext->interp ){
793
+ if( tclContext->interp ){
794794
return TH_OK;
795795
}
796796
if( loadTcl(interp, &tclContext->library, &tclContext->xFindExecutable,
797797
&tclContext->xCreateInterp, &tclContext->xDeleteInterp,
798798
&tclContext->xFinalize)!=TH_OK ){
@@ -882,11 +882,11 @@
882882
tcl_FinalizeProc *xFinalize;
883883
#if defined(USE_TCL_STUBS)
884884
void *library;
885885
#endif /* defined(USE_TCL_STUBS) */
886886
887
- if ( !tclContext ){
887
+ if( !tclContext ){
888888
Th_ErrorMessage(interp,
889889
"invalid Tcl context", (const char *)"", 0);
890890
return TH_ERROR;
891891
}
892892
/*
@@ -897,11 +897,11 @@
897897
xFinalize = tclContext->xFinalize;
898898
/*
899899
** If the Tcl interpreter has been created, formally delete it now.
900900
*/
901901
tclInterp = tclContext->interp;
902
- if ( tclInterp ){
902
+ if( tclInterp ){
903903
Tcl_DeleteInterp(tclInterp);
904904
tclContext->interp = tclInterp = 0;
905905
}
906906
/*
907907
** If the Tcl library is not finalized prior to unloading it, a deadlock
@@ -939,15 +939,15 @@
939939
int i;
940940
941941
/* Add the Tcl integration commands to TH1. */
942942
for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
943943
void *ctx;
944
- if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
944
+ if( !aCommand[i].zName || !aCommand[i].xProc ) continue;
945945
ctx = aCommand[i].pContext;
946946
/* Use Tcl interpreter for context? */
947947
if( !ctx ) ctx = pContext;
948948
Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0);
949949
}
950950
return TH_OK;
951951
}
952952
953953
#endif /* FOSSIL_ENABLE_TCL */
954954
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -30,24 +30,24 @@
30 ** arguments from TH1 to Tcl.
31 */
32 #define USE_ARGV_TO_OBJV() \
33 int objc; \
34 Tcl_Obj **objv; \
35 int i;
36
37 #define COPY_ARGV_TO_OBJV() \
38 objc = argc-1; \
39 objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \
40 for(i=1; i<argc; i++){ \
41 objv[i-1] = Tcl_NewStringObj(argv[i], argl[i]); \
42 Tcl_IncrRefCount(objv[i-1]); \
43 }
44
45 #define FREE_ARGV_TO_OBJV() \
46 for(i=1; i<argc; i++){ \
47 Tcl_DecrRefCount(objv[i-1]); \
48 } \
49 ckfree((char *)objv);
50
51 /*
52 ** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl
53 ** context.
@@ -109,20 +109,20 @@
109 # define TCL_MINOR_OFFSET (8)
110 # endif
111 # endif /* defined(__CYGWIN__) */
112 # endif /* defined(_WIN32) */
113 # ifndef TCL_FINDEXECUTABLE_NAME
114 # define TCL_FINDEXECUTABLE_NAME "_Tcl_FindExecutable"
115 # endif
116 # ifndef TCL_CREATEINTERP_NAME
117 # define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp"
118 # endif
119 # ifndef TCL_DELETEINTERP_NAME
120 # define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp"
121 # endif
122 # ifndef TCL_FINALIZE_NAME
123 # define TCL_FINALIZE_NAME "_Tcl_Finalize"
124 # endif
125 #endif /* defined(USE_TCL_STUBS) */
126
127 /*
128 ** The function types for Tcl_FindExecutable and Tcl_CreateInterp are needed
@@ -311,17 +311,17 @@
311 int rc
312 ){
313 struct TclContext *tclContext = (struct TclContext *)ctx;
314 tcl_NotifyProc *xNotifyProc;
315
316 if ( !tclContext ){
317 Th_ErrorMessage(interp,
318 "invalid Tcl context", (const char *)"", 0);
319 return TH_ERROR;
320 }
321 xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
322 if ( xNotifyProc ){
323 rc = xNotifyProc(bIsPost ?
324 tclContext->pPostContext : tclContext->pPreContext,
325 interp, ctx, argc, argv, argl, rc);
326 }
327 return rc;
@@ -783,16 +783,16 @@
783 char **argv;
784 char *argv0 = 0;
785 Tcl_Interp *tclInterp;
786 char *setup;
787
788 if ( !tclContext ){
789 Th_ErrorMessage(interp,
790 "invalid Tcl context", (const char *)"", 0);
791 return TH_ERROR;
792 }
793 if ( tclContext->interp ){
794 return TH_OK;
795 }
796 if( loadTcl(interp, &tclContext->library, &tclContext->xFindExecutable,
797 &tclContext->xCreateInterp, &tclContext->xDeleteInterp,
798 &tclContext->xFinalize)!=TH_OK ){
@@ -882,11 +882,11 @@
882 tcl_FinalizeProc *xFinalize;
883 #if defined(USE_TCL_STUBS)
884 void *library;
885 #endif /* defined(USE_TCL_STUBS) */
886
887 if ( !tclContext ){
888 Th_ErrorMessage(interp,
889 "invalid Tcl context", (const char *)"", 0);
890 return TH_ERROR;
891 }
892 /*
@@ -897,11 +897,11 @@
897 xFinalize = tclContext->xFinalize;
898 /*
899 ** If the Tcl interpreter has been created, formally delete it now.
900 */
901 tclInterp = tclContext->interp;
902 if ( tclInterp ){
903 Tcl_DeleteInterp(tclInterp);
904 tclContext->interp = tclInterp = 0;
905 }
906 /*
907 ** If the Tcl library is not finalized prior to unloading it, a deadlock
@@ -939,15 +939,15 @@
939 int i;
940
941 /* Add the Tcl integration commands to TH1. */
942 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
943 void *ctx;
944 if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
945 ctx = aCommand[i].pContext;
946 /* Use Tcl interpreter for context? */
947 if( !ctx ) ctx = pContext;
948 Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0);
949 }
950 return TH_OK;
951 }
952
953 #endif /* FOSSIL_ENABLE_TCL */
954
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -30,24 +30,24 @@
30 ** arguments from TH1 to Tcl.
31 */
32 #define USE_ARGV_TO_OBJV() \
33 int objc; \
34 Tcl_Obj **objv; \
35 int obji;
36
37 #define COPY_ARGV_TO_OBJV() \
38 objc = argc-1; \
39 objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \
40 for(obji=1; obji<argc; obji++){ \
41 objv[obji-1] = Tcl_NewStringObj(argv[obji], argl[obji]); \
42 Tcl_IncrRefCount(objv[obji-1]); \
43 }
44
45 #define FREE_ARGV_TO_OBJV() \
46 for(obji=1; obji<argc; obji++){ \
47 Tcl_DecrRefCount(objv[obji-1]); \
48 } \
49 ckfree((char *)objv);
50
51 /*
52 ** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl
53 ** context.
@@ -109,20 +109,20 @@
109 # define TCL_MINOR_OFFSET (8)
110 # endif
111 # endif /* defined(__CYGWIN__) */
112 # endif /* defined(_WIN32) */
113 # ifndef TCL_FINDEXECUTABLE_NAME
114 # define TCL_FINDEXECUTABLE_NAME "_Tcl_FindExecutable\0"
115 # endif
116 # ifndef TCL_CREATEINTERP_NAME
117 # define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp\0"
118 # endif
119 # ifndef TCL_DELETEINTERP_NAME
120 # define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp\0"
121 # endif
122 # ifndef TCL_FINALIZE_NAME
123 # define TCL_FINALIZE_NAME "_Tcl_Finalize\0"
124 # endif
125 #endif /* defined(USE_TCL_STUBS) */
126
127 /*
128 ** The function types for Tcl_FindExecutable and Tcl_CreateInterp are needed
@@ -311,17 +311,17 @@
311 int rc
312 ){
313 struct TclContext *tclContext = (struct TclContext *)ctx;
314 tcl_NotifyProc *xNotifyProc;
315
316 if( !tclContext ){
317 Th_ErrorMessage(interp,
318 "invalid Tcl context", (const char *)"", 0);
319 return TH_ERROR;
320 }
321 xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
322 if( xNotifyProc ){
323 rc = xNotifyProc(bIsPost ?
324 tclContext->pPostContext : tclContext->pPreContext,
325 interp, ctx, argc, argv, argl, rc);
326 }
327 return rc;
@@ -783,16 +783,16 @@
783 char **argv;
784 char *argv0 = 0;
785 Tcl_Interp *tclInterp;
786 char *setup;
787
788 if( !tclContext ){
789 Th_ErrorMessage(interp,
790 "invalid Tcl context", (const char *)"", 0);
791 return TH_ERROR;
792 }
793 if( tclContext->interp ){
794 return TH_OK;
795 }
796 if( loadTcl(interp, &tclContext->library, &tclContext->xFindExecutable,
797 &tclContext->xCreateInterp, &tclContext->xDeleteInterp,
798 &tclContext->xFinalize)!=TH_OK ){
@@ -882,11 +882,11 @@
882 tcl_FinalizeProc *xFinalize;
883 #if defined(USE_TCL_STUBS)
884 void *library;
885 #endif /* defined(USE_TCL_STUBS) */
886
887 if( !tclContext ){
888 Th_ErrorMessage(interp,
889 "invalid Tcl context", (const char *)"", 0);
890 return TH_ERROR;
891 }
892 /*
@@ -897,11 +897,11 @@
897 xFinalize = tclContext->xFinalize;
898 /*
899 ** If the Tcl interpreter has been created, formally delete it now.
900 */
901 tclInterp = tclContext->interp;
902 if( tclInterp ){
903 Tcl_DeleteInterp(tclInterp);
904 tclContext->interp = tclInterp = 0;
905 }
906 /*
907 ** If the Tcl library is not finalized prior to unloading it, a deadlock
@@ -939,15 +939,15 @@
939 int i;
940
941 /* Add the Tcl integration commands to TH1. */
942 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
943 void *ctx;
944 if( !aCommand[i].zName || !aCommand[i].xProc ) continue;
945 ctx = aCommand[i].pContext;
946 /* Use Tcl interpreter for context? */
947 if( !ctx ) ctx = pContext;
948 Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0);
949 }
950 return TH_OK;
951 }
952
953 #endif /* FOSSIL_ENABLE_TCL */
954
+262 -42
--- src/timeline.c
+++ src/timeline.c
@@ -16,13 +16,13 @@
1616
*******************************************************************************
1717
**
1818
** This file contains code to implement the timeline web page
1919
**
2020
*/
21
+#include "config.h"
2122
#include <string.h>
2223
#include <time.h>
23
-#include "config.h"
2424
#include "timeline.h"
2525
2626
/*
2727
** Shorten a UUID so that is the minimum length needed to contain
2828
** at least one digit in the range 'a'..'f'. The minimum length is 10.
@@ -246,16 +246,20 @@
246246
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
247247
Stmt fchngQuery; /* Query for file changes on check-ins */
248248
static Stmt qbranch;
249249
int pendingEndTr = 0; /* True if a </td></tr> is needed */
250250
int vid = 0; /* Current checkout version */
251
+ int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
252
+ 2: YYYY-MM-DD HH:MM
253
+ 3: YYMMDD HH:MM */
251254
252255
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
253256
vid = db_lget_int("checkout", 0);
254257
}
255258
zPrevDate[0] = 0;
256259
mxWikiLen = db_get_int("timeline-max-comment", 0);
260
+ dateFormat = db_get_int("timeline-date-format", 0);
257261
if( tmFlags & TIMELINE_GRAPH ){
258262
pGraph = graph_init();
259263
/* style is not moved to css, because this is
260264
** a technical div for the timeline graph
261265
*/
@@ -282,11 +286,11 @@
282286
int tagid = db_column_int(pQuery, 9);
283287
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
284288
const char *zBr = 0; /* Branch */
285289
int commentColumn = 3; /* Column containing comment text */
286290
int modPending; /* Pending moderation */
287
- char zTime[8];
291
+ char zTime[20];
288292
289293
modPending = moderation_pending(rid);
290294
if( tagid ){
291295
if( modPending ) tagid = -tagid;
292296
if( tagid==prevTagid ){
@@ -314,18 +318,34 @@
314318
}
315319
prevWasDivider = 1;
316320
continue;
317321
}
318322
prevWasDivider = 0;
319
- if( memcmp(zDate, zPrevDate, 10) ){
320
- sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
321
- @ <tr><td>
322
- @ <div class="divider">%s(zPrevDate)</div>
323
- @ </td><td></td><td></td></tr>
324
- }
325
- memcpy(zTime, &zDate[11], 5);
326
- zTime[5] = 0;
323
+ if( dateFormat<2 ){
324
+ if( memcmp(zDate, zPrevDate, 10) ){
325
+ sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
326
+ @ <tr><td>
327
+ @ <div class="divider timelineDate">%s(zPrevDate)</div>
328
+ @ </td><td></td><td></td></tr>
329
+ }
330
+ memcpy(zTime, &zDate[11], 5+dateFormat*3);
331
+ zTime[5+dateFormat*3] = 0;
332
+ }else if(3==dateFormat){
333
+ /* YYMMDD HH:MM */
334
+ int pos = 0;
335
+ zTime[pos++] = zDate[2]; zTime[pos++] = zDate[3]; /* YY */
336
+ zTime[pos++] = zDate[5]; zTime[pos++] = zDate[6]; /* MM */
337
+ zTime[pos++] = zDate[8]; zTime[pos++] = zDate[9]; /* DD */
338
+ zTime[pos++] = ' ';
339
+ zTime[pos++] = zDate[11]; zTime[pos++] = zDate[12]; /* HH */
340
+ zTime[pos++] = ':';
341
+ zTime[pos++] = zDate[14]; zTime[pos++] = zDate[15]; /* MM */
342
+ zTime[pos++] = 0;
343
+ }else{
344
+ /* YYYY-MM-DD HH:MM */
345
+ sqlite3_snprintf(sizeof(zTime), zTime, "%.16s", zDate);
346
+ }
327347
if( rid == vid ){
328348
@ <tr class="timelineCurrent">
329349
}else {
330350
@ <tr>
331351
}
@@ -1474,11 +1494,17 @@
14741494
14751495
/*
14761496
** The input query q selects various records. Print a human-readable
14771497
** summary of those records.
14781498
**
1479
-** Limit the number of entries printed to nLine.
1499
+** Limit number of lines or entries printed to nLimit. If nLimit is zero
1500
+** there is no limit. If nLimit is greater than zero, limit the number of
1501
+** complete entries printed. If nLimit is less than zero, attempt to limit
1502
+** the number of lines printed (this is basically the legacy behavior).
1503
+** The line limit, if used, is approximate because it is only checked on a
1504
+** per-entry basis. If verbose mode, the file name details are considered
1505
+** to be part of the entry.
14801506
**
14811507
** The query should return these columns:
14821508
**
14831509
** 0. rid
14841510
** 1. uuid
@@ -1487,12 +1513,14 @@
14871513
** 4. Number of non-merge children
14881514
** 5. Number of parents
14891515
** 6. mtime
14901516
** 7. branch
14911517
*/
1492
-void print_timeline(Stmt *q, int mxLine, int verboseFlag){
1518
+void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
1519
+ int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
14931520
int nLine = 0;
1521
+ int nEntry = 0;
14941522
char zPrevDate[20];
14951523
const char *zCurrentUuid=0;
14961524
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
14971525
Stmt fchngQuery; /* Query for file changes on check-ins */
14981526
zPrevDate[0] = 0;
@@ -1500,11 +1528,11 @@
15001528
if( g.localOpen ){
15011529
int rid = db_lget_int("checkout", 0);
15021530
zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
15031531
}
15041532
1505
- while( db_step(q)==SQLITE_ROW && nLine<=mxLine ){
1533
+ while( db_step(q)==SQLITE_ROW ){
15061534
int rid = db_column_int(q, 0);
15071535
const char *zId = db_column_text(q, 1);
15081536
const char *zDate = db_column_text(q, 2);
15091537
const char *zCom = db_column_text(q, 3);
15101538
int nChild = db_column_int(q, 4);
@@ -1512,15 +1540,24 @@
15121540
char *zFree = 0;
15131541
int n = 0;
15141542
char zPrefix[80];
15151543
char zUuid[UUID_SIZE+1];
15161544
1545
+ if( nAbsLimit!=0 ){
1546
+ if( nLimit<0 && nLine>=nAbsLimit ){
1547
+ fossil_print("=== line limit (%d) reached ===\n", nAbsLimit);
1548
+ break; /* line count limit hit, stop. */
1549
+ }else if( nEntry>=nAbsLimit ){
1550
+ fossil_print("=== entry limit (%d) reached ===\n", nAbsLimit);
1551
+ break; /* entry count limit hit, stop. */
1552
+ }
1553
+ }
15171554
sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
15181555
if( memcmp(zDate, zPrevDate, 10) ){
15191556
fossil_print("=== %.10s ===\n", zDate);
15201557
memcpy(zPrevDate, zDate, 10);
1521
- nLine++;
1558
+ nLine++; /* record another line */
15221559
}
15231560
if( zCom==0 ) zCom = "";
15241561
fossil_print("%.8s ", &zDate[11]);
15251562
zPrefix[0] = 0;
15261563
if( nParent>1 ){
@@ -1540,11 +1577,11 @@
15401577
if( fossil_strcmp(zCurrentUuid,zId)==0 ){
15411578
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
15421579
n += strlen(zPrefix);
15431580
}
15441581
zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
1545
- nLine += comment_print(zFree, 9, 79);
1582
+ nLine += comment_print(zFree, 9, width); /* record another X lines */
15461583
sqlite3_free(zFree);
15471584
15481585
if(verboseFlag){
15491586
if( !fchngQueryInit ){
15501587
db_prepare(&fchngQuery,
@@ -1569,13 +1606,15 @@
15691606
}else if( isDel ){
15701607
fossil_print(" DELETED %s\n",zFilename);
15711608
}else{
15721609
fossil_print(" EDITED %s\n", zFilename);
15731610
}
1611
+ nLine++; /* record another line */
15741612
}
15751613
db_reset(&fchngQuery);
15761614
}
1615
+ nEntry++; /* record another complete entry */
15771616
}
15781617
if( fchngQueryInit ) db_finalize(&fchngQuery);
15791618
}
15801619
15811620
/*
@@ -1642,24 +1681,27 @@
16421681
** The DATETIME should be in the ISO8601 format. For
16431682
** examples: "2007-08-18 07:21:21". You can also say "current"
16441683
** for the current version or "now" for the current time.
16451684
**
16461685
** Options:
1647
-** -n|--limit N Output the first N changes (default 20)
1686
+** -n|--limit N Output the first N entries (default 20 lines).
1687
+** N=0 means no limit.
16481688
** -t|--type TYPE Output items from the given types only, such as:
16491689
** ci = file commits only
16501690
** e = events only
16511691
** t = tickets only
16521692
** w = wiki commits only
16531693
** -v|--verbose Output the list of files changed by each commit
16541694
** and the type of each change (edited, deleted,
16551695
** etc.) after the checkin comment.
1696
+** -W|--width <num> With of lines (default 79). Must be >20 or 0.
16561697
*/
16571698
void timeline_cmd(void){
16581699
Stmt q;
1659
- int n, k;
1700
+ int n, k, width;
16601701
const char *zLimit;
1702
+ const char *zWidth;
16611703
const char *zType;
16621704
char *zOrigin;
16631705
char *zDate;
16641706
Blob sql;
16651707
int objid = 0;
@@ -1670,18 +1712,27 @@
16701712
if( !verboseFlag){
16711713
verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
16721714
}
16731715
db_find_and_open_repository(0, 0);
16741716
zLimit = find_option("limit","n",1);
1717
+ zWidth = find_option("width","W",1);
16751718
zType = find_option("type","t",1);
16761719
if ( !zLimit ){
16771720
zLimit = find_option("count",0,1);
16781721
}
16791722
if( zLimit ){
16801723
n = atoi(zLimit);
16811724
}else{
1682
- n = 20;
1725
+ n = -20;
1726
+ }
1727
+ if( zWidth ){
1728
+ width = atoi(zWidth);
1729
+ if( (width!=0) && (width<=20) ){
1730
+ fossil_fatal("--width|-W value must be >20 or 0");
1731
+ }
1732
+ }else{
1733
+ width = 79;
16831734
}
16841735
if( g.argc>=4 ){
16851736
k = strlen(g.argv[2]);
16861737
if( strncmp(g.argv[2],"before",k)==0 ){
16871738
mode = 1;
@@ -1694,11 +1745,11 @@
16941745
}else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
16951746
mode = 4;
16961747
}else if( strncmp(g.argv[2],"parents",k)==0 ){
16971748
mode = 4;
16981749
}else if(!zType && !zLimit){
1699
- usage("?WHEN? ?BASELINE|DATETIME? ?-n|--limit N? ?-t|--type TYPE?");
1750
+ usage("?WHEN? ?BASELINE|DATETIME? ?-n|--limit #? ?-t|--type TYPE? ?-W|--width WIDTH?");
17001751
}
17011752
if( '-' != *g.argv[3] ){
17021753
zOrigin = g.argv[3];
17031754
}else{
17041755
zOrigin = "now";
@@ -1756,11 +1807,11 @@
17561807
blob_appendf(&sql, " AND event.type=%Q ", zType);
17571808
}
17581809
blob_appendf(&sql, " ORDER BY event.mtime DESC");
17591810
db_prepare(&q, blob_str(&sql));
17601811
blob_reset(&sql);
1761
- print_timeline(&q, n, verboseFlag);
1812
+ print_timeline(&q, n, width, verboseFlag);
17621813
db_finalize(&q);
17631814
}
17641815
17651816
/*
17661817
** This is a version of the "localtime()" function from the standard
@@ -1850,10 +1901,154 @@
18501901
@ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
18511902
}
18521903
db_finalize(&q);
18531904
style_footer();
18541905
}
1906
+
1907
+
1908
+/*
1909
+** Used by stats_report_xxxxx() to remember which type of events
1910
+** to show. Populated by stats_report_init_view() and holds the
1911
+** return value of that function.
1912
+*/
1913
+static int statsReportType = 0;
1914
+
1915
+/*
1916
+** Set by stats_report_init_view() to one of the y=XXXX values
1917
+** accepted by /timeline?y=XXXX.
1918
+*/
1919
+static char const * statsReportTimelineYFlag = NULL;
1920
+
1921
+/*
1922
+** Creates a TEMP VIEW named v_reports which is a wrapper around the
1923
+** EVENT table filtered on event.type. It looks for the request
1924
+** parameter 'type' (reminder: we "should" use 'y' for consistency
1925
+** with /timeline, but /reports uses 'y' for the year) and expects it
1926
+** to contain one of the conventional values from event.type or the
1927
+** value "all", which is treated as equivalent to "*". By default (if
1928
+** no 'y' is specified), "*" is assumed (that is also the default for
1929
+** invalid/unknown filter values). That 'y' filter is the one used for
1930
+** the event list. Note that a filter of "*" or "all" is equivalent to
1931
+** querying against the full event table. The view, however, adds an
1932
+** abstraction level to simplify the implementation code for the
1933
+** various /reports pages.
1934
+**
1935
+** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1936
+** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1937
+** used).
1938
+*/
1939
+static int stats_report_init_view(){
1940
+ char const * zType = PD("type","*"); /* analog to /timeline?y=... */
1941
+ char const * zRealType = NULL; /* normalized form of zType */
1942
+ int rc = 0; /* result code */
1943
+ assert( !statsReportType && "Must not be called more than once." );
1944
+ switch( (zType && *zType) ? *zType : 0 ){
1945
+ case 'c':
1946
+ case 'C':
1947
+ zRealType = "ci";
1948
+ rc = *zRealType;
1949
+ break;
1950
+ case 'e':
1951
+ case 'E':
1952
+ zRealType = "e";
1953
+ rc = *zRealType;
1954
+ break;
1955
+ case 'g':
1956
+ case 'G':
1957
+ zRealType = "g";
1958
+ rc = *zRealType;
1959
+ break;
1960
+ case 't':
1961
+ case 'T':
1962
+ zRealType = "t";
1963
+ rc = *zRealType;
1964
+ break;
1965
+ case 'w':
1966
+ case 'W':
1967
+ zRealType = "w";
1968
+ rc = *zRealType;
1969
+ break;
1970
+ default:
1971
+ rc = '*';
1972
+ break;
1973
+ }
1974
+ assert(0 != rc);
1975
+ if(zRealType){
1976
+ statsReportTimelineYFlag = zRealType;
1977
+ db_multi_exec("CREATE TEMP VIEW v_reports AS "
1978
+ "SELECT * FROM event WHERE type GLOB %Q",
1979
+ zRealType);
1980
+ }else{
1981
+ statsReportTimelineYFlag = "a";
1982
+ db_multi_exec("CREATE TEMP VIEW v_reports AS "
1983
+ "SELECT * FROM event");
1984
+ }
1985
+ return statsReportType = rc;
1986
+}
1987
+
1988
+/*
1989
+** Returns a string suitable (for a given value of suitable) for
1990
+** use in a label with the header of the /reports pages, dependent
1991
+** on the 'type' flag. See stats_report_init_view().
1992
+** The returned bytes are static.
1993
+*/
1994
+static char const * stats_report_label_for_type(){
1995
+ assert( statsReportType && "Must call stats_report_init_view() first." );
1996
+ switch( statsReportType ){
1997
+ case 'c':
1998
+ return "checkins";
1999
+ case 'w':
2000
+ return "wiki changes";
2001
+ case 't':
2002
+ return "ticket changes";
2003
+ case 'g':
2004
+ return "tag changes";
2005
+ default:
2006
+ return "all types";
2007
+ }
2008
+}
2009
+
2010
+/*
2011
+** A helper for the /reports family of pages which prints out a menu
2012
+** of links for the various type=XXX flags. zCurrentViewName must be
2013
+** the name/value of the 'view' parameter which is in effect at
2014
+** the time this is called. e.g. if called from the 'byuser' view
2015
+** then zCurrentViewName must be "byuser".
2016
+*/
2017
+static void stats_report_event_types_menu(char const * zCurrentViewName){
2018
+ char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName);
2019
+ cgi_printf("<div>");
2020
+ cgi_printf("<span>Event types:</span> ");
2021
+ if('*' == statsReportType){
2022
+ cgi_printf(" <strong>all</strong>", zTop);
2023
+ }else{
2024
+ cgi_printf(" <a href='%s'>all</a>", zTop);
2025
+ }
2026
+ if('c' == statsReportType){
2027
+ cgi_printf(" <strong>checkins</strong>", zTop);
2028
+ }else{
2029
+ cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
2030
+ }
2031
+ if( 't' == statsReportType ){
2032
+ cgi_printf(" <strong>tickets</strong>", zTop);
2033
+ }else{
2034
+ cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
2035
+ }
2036
+ if( 'g' == statsReportType ){
2037
+ cgi_printf(" <strong>tags</strong>", zTop);
2038
+ }else{
2039
+ cgi_printf(" <a href='%s&type=g'>tags</a>", zTop);
2040
+ }
2041
+ if( 'w' == statsReportType ){
2042
+ cgi_printf(" <strong>wiki</strong>", zTop);
2043
+ }else{
2044
+ cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop);
2045
+ }
2046
+ fossil_free(zTop);
2047
+ cgi_printf("</div>");
2048
+}
2049
+
18552050
18562051
/*
18572052
** Helper for stats_report_by_month_year(), which generates a list of
18582053
** week numbers. zTimeframe should be either a timeframe in the form YYYY
18592054
** or YYYY-MM.
@@ -1864,22 +2059,22 @@
18642059
memcpy(yearPart, zTimeframe, 4);
18652060
db_prepare(&stWeek,
18662061
"SELECT DISTINCT strftime('%%W',mtime) AS wk, "
18672062
"count(*) AS n, "
18682063
"substr(date(mtime),1,%d) AS ym "
1869
- "FROM event "
2064
+ "FROM v_reports "
18702065
"WHERE ym=%Q AND mtime < current_timestamp "
18712066
"GROUP BY wk ORDER BY wk",
18722067
strlen(zTimeframe),
18732068
zTimeframe);
18742069
while( SQLITE_ROW == db_step(&stWeek) ){
18752070
const char * zWeek = db_column_text(&stWeek,0);
18762071
const int nCount = db_column_int(&stWeek,1);
18772072
cgi_printf("<a href='%s/timeline?"
1878
- "yw=%t-%t&n=%d'>%s</a>",
2073
+ "yw=%t-%t&n=%d&y=%s'>%s</a>",
18792074
g.zTop, yearPart, zWeek,
1880
- nCount, zWeek);
2075
+ nCount, statsReportTimelineYFlag, zWeek);
18812076
}
18822077
db_finalize(&stWeek);
18832078
}
18842079
18852080
/*
@@ -1908,16 +2103,19 @@
19082103
Blob header = empty_blob; /* Page header text */
19092104
int nMaxEvents = 1; /* for calculating length of graph
19102105
bars. */
19112106
int iterations = 0; /* number of weeks/months we iterate
19122107
over */
1913
- blob_appendf(&header, "Timeline Events by year%s",
2108
+ stats_report_init_view();
2109
+ stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" );
2110
+ blob_appendf(&header, "Timeline Events (%s) by year%s",
2111
+ stats_report_label_for_type(),
19142112
(includeMonth ? "/month" : ""));
19152113
blob_appendf(&sql,
19162114
"SELECT substr(date(mtime),1,%d) AS timeframe, "
19172115
"count(*) AS eventCount "
1918
- "FROM event ",
2116
+ "FROM v_reports ",
19192117
includeMonth ? 7 : 4);
19202118
if(zUserName&&*zUserName){
19212119
blob_appendf(&sql, " WHERE user=%Q ", zUserName);
19222120
blob_appendf(&header," for user %q", zUserName);
19232121
}
@@ -1950,14 +2148,15 @@
19502148
}
19512149
db_reset(&query);
19522150
while( SQLITE_ROW == db_step(&query) ){
19532151
const char * zTimeframe = db_column_text(&query, 0);
19542152
const int nCount = db_column_int(&query, 1);
1955
- const int nSize = nCount
2153
+ int nSize = nCount
19562154
? (int)(100 * nCount / nMaxEvents)
19572155
: 1;
19582156
showYearTotal = 0;
2157
+ if(!nSize) nSize = 1;
19592158
if(includeMonth){
19602159
/* For Month/year view, add a separator for each distinct year. */
19612160
if(!*zPrevYear ||
19622161
(0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
19632162
showYearTotal = *zPrevYear;
@@ -1981,21 +2180,23 @@
19812180
nEventsPerYear += nCount;
19822181
@<tr class='row%d(rowClass)'>
19832182
@ <td>
19842183
if(includeMonth){
19852184
cgi_printf("<a href='%s/timeline?"
1986
- "ym=%t&n=%d",
1987
- g.zTop, zTimeframe, nCount );
2185
+ "ym=%t&n=%d&y=%s",
2186
+ g.zTop, zTimeframe, nCount,
2187
+ statsReportTimelineYFlag );
19882188
/* Reminder: n=nCount is not actually correct for bymonth unless
19892189
that was the only user who caused events.
19902190
*/
19912191
if( zUserName && *zUserName ){
19922192
cgi_printf("&u=%t", zUserName);
19932193
}
19942194
cgi_printf("' target='_new'>%s</a>",zTimeframe);
19952195
}else {
1996
- cgi_printf("<a href='?view=byweek&y=%s", zTimeframe);
2196
+ cgi_printf("<a href='?view=byweek&y=%s&type=%c",
2197
+ zTimeframe, (char)statsReportType);
19972198
if(zUserName && *zUserName){
19982199
cgi_printf("&u=%t", zUserName);
19992200
}
20002201
cgi_printf("'>%s</a>", zTimeframe);
20012202
}
@@ -2053,19 +2254,22 @@
20532254
int rowClass = 0; /* counter for alternating
20542255
row colors */
20552256
Blob sql = empty_blob; /* SQL */
20562257
int nMaxEvents = 1; /* max number of events for
20572258
all rows. */
2259
+ stats_report_init_view();
2260
+ stats_report_event_types_menu("byuser");
20582261
blob_append(&sql,
20592262
"SELECT user, "
20602263
"COUNT(*) AS eventCount "
2061
- "FROM event "
2264
+ "FROM v_reports "
20622265
"GROUP BY user ORDER BY eventCount DESC",
20632266
-1);
20642267
db_prepare(&query, blob_str(&sql));
20652268
blob_reset(&sql);
2066
- @ <h1>Timeline Events by User</h1>
2269
+ @ <h1>Timeline Events
2270
+ @ (%s(stats_report_label_for_type())) by User</h1>
20672271
@ <table class='statistics-report-table-events' border='0'
20682272
@ cellpadding='2' cellspacing='0' id='statsTable'>
20692273
@ <thead><tr>
20702274
@ <th>User</th>
20712275
@ <th>Events</th>
@@ -2079,19 +2283,20 @@
20792283
}
20802284
db_reset(&query);
20812285
while( SQLITE_ROW == db_step(&query) ){
20822286
const char * zUser = db_column_text(&query, 0);
20832287
const int nCount = db_column_int(&query, 1);
2084
- const int nSize = nCount
2288
+ int nSize = nCount
20852289
? (int)(100 * nCount / nMaxEvents)
20862290
: 0;
20872291
if(!nCount) continue /* arguable! Possible? */;
2292
+ else if(!nSize) nSize = 1;
20882293
rowClass = ++nRowNumber % 2;
20892294
nEventTotal += nCount;
20902295
@<tr class='row%d(rowClass)'>
20912296
@ <td>
2092
- @ <a href="?view=bymonth&user=%h(zUser)">%h(zUser)</a>
2297
+ @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
20932298
@ </td><td>%d(nCount)</td>
20942299
@ <td>
20952300
@ <div class='statistics-report-graph-line'
20962301
@ style='height:16px;width:%d(nSize)%%;'>
20972302
@ </div></td>
@@ -2120,15 +2325,16 @@
21202325
char * zDefaultYear = NULL;
21212326
Blob sql = empty_blob;
21222327
int nMaxEvents = 1; /* max number of events for
21232328
all rows. */
21242329
int iterations = 0; /* # of active time periods. */
2125
-
2330
+ stats_report_init_view();
2331
+ stats_report_event_types_menu("byweek");
21262332
cgi_printf("Select year: ");
21272333
blob_append(&sql,
21282334
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
2129
- "FROM event WHERE 1 ", -1);
2335
+ "FROM v_reports WHERE 1 ", -1);
21302336
if(zUserName&&*zUserName){
21312337
blob_appendf(&sql,"AND user=%Q ", zUserName);
21322338
}
21332339
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
21342340
db_prepare(&qYears, blob_str(&sql));
@@ -2136,11 +2342,12 @@
21362342
while( SQLITE_ROW == db_step(&qYears) ){
21372343
const char * zT = db_column_text(&qYears, 0);
21382344
if( i++ ){
21392345
cgi_printf(" ");
21402346
}
2141
- cgi_printf("<a href='?view=byweek&y=%s", zT);
2347
+ cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2348
+ (char)statsReportType);
21422349
if(zUserName && *zUserName){
21432350
cgi_printf("&user=%t",zUserName);
21442351
}
21452352
cgi_printf("'>%s</a>",zT);
21462353
}
@@ -2154,16 +2361,17 @@
21542361
if(4 == nYear){
21552362
Stmt stWeek = empty_Stmt;
21562363
int rowCount = 0;
21572364
int total = 0;
21582365
Blob header = empty_blob;
2159
- blob_appendf(&header, "Timeline events for the calendar weeks "
2160
- "of %h", zYear);
2366
+ blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
2367
+ "of %h", stats_report_label_for_type(),
2368
+ zYear);
21612369
blob_appendf(&sql,
21622370
"SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
21632371
"count(*) AS n "
2164
- "FROM event "
2372
+ "FROM v_reports "
21652373
"WHERE %Q=substr(date(mtime),1,4) "
21662374
"AND mtime < current_timestamp ",
21672375
zYear);
21682376
if(zUserName&&*zUserName){
21692377
blob_appendf(&sql, " AND user=%Q ", zUserName);
@@ -2192,17 +2400,19 @@
21922400
}
21932401
db_reset(&stWeek);
21942402
while( SQLITE_ROW == db_step(&stWeek) ){
21952403
const char * zWeek = db_column_text(&stWeek,0);
21962404
const int nCount = db_column_int(&stWeek,1);
2197
- const int nSize = nCount
2405
+ int nSize = nCount
21982406
? (int)(100 * nCount / nMaxEvents)
21992407
: 0;
2408
+ if(!nSize) nSize = 1;
22002409
total += nCount;
22012410
cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2202
- cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d",
2203
- g.zTop, zYear, zWeek, nCount);
2411
+ cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d&y=%s",
2412
+ g.zTop, zYear, zWeek, nCount,
2413
+ statsReportTimelineYFlag);
22042414
if(zUserName && *zUserName){
22052415
cgi_printf("&u=%t",zUserName);
22062416
}
22072417
cgi_printf("'>%s</a></td>",zWeek);
22082418
@@ -2235,10 +2445,20 @@
22352445
**
22362446
** Query Parameters:
22372447
**
22382448
** view=REPORT_NAME Valid values: bymonth, byyear, byuser
22392449
** user=NAME Restricts statistics to the given user
2450
+** type=TYPE Restricts the report to a specific event type:
2451
+** ci (checkin), w (wiki), t (ticket), g (tag)
2452
+** Defaulting to all event types.
2453
+**
2454
+** The view-specific query parameters include:
2455
+**
2456
+** view=byweek:
2457
+**
2458
+** y=YYYY The year to report (default is the server's
2459
+** current year).
22402460
*/
22412461
void stats_report_page(){
22422462
HQuery url; /* URL for various branch links */
22432463
const char * zView = P("view"); /* Which view/report to show. */
22442464
const char *zUserName = P("user");
22452465
--- src/timeline.c
+++ src/timeline.c
@@ -16,13 +16,13 @@
16 *******************************************************************************
17 **
18 ** This file contains code to implement the timeline web page
19 **
20 */
 
21 #include <string.h>
22 #include <time.h>
23 #include "config.h"
24 #include "timeline.h"
25
26 /*
27 ** Shorten a UUID so that is the minimum length needed to contain
28 ** at least one digit in the range 'a'..'f'. The minimum length is 10.
@@ -246,16 +246,20 @@
246 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
247 Stmt fchngQuery; /* Query for file changes on check-ins */
248 static Stmt qbranch;
249 int pendingEndTr = 0; /* True if a </td></tr> is needed */
250 int vid = 0; /* Current checkout version */
 
 
 
251
252 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
253 vid = db_lget_int("checkout", 0);
254 }
255 zPrevDate[0] = 0;
256 mxWikiLen = db_get_int("timeline-max-comment", 0);
 
257 if( tmFlags & TIMELINE_GRAPH ){
258 pGraph = graph_init();
259 /* style is not moved to css, because this is
260 ** a technical div for the timeline graph
261 */
@@ -282,11 +286,11 @@
282 int tagid = db_column_int(pQuery, 9);
283 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
284 const char *zBr = 0; /* Branch */
285 int commentColumn = 3; /* Column containing comment text */
286 int modPending; /* Pending moderation */
287 char zTime[8];
288
289 modPending = moderation_pending(rid);
290 if( tagid ){
291 if( modPending ) tagid = -tagid;
292 if( tagid==prevTagid ){
@@ -314,18 +318,34 @@
314 }
315 prevWasDivider = 1;
316 continue;
317 }
318 prevWasDivider = 0;
319 if( memcmp(zDate, zPrevDate, 10) ){
320 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
321 @ <tr><td>
322 @ <div class="divider">%s(zPrevDate)</div>
323 @ </td><td></td><td></td></tr>
324 }
325 memcpy(zTime, &zDate[11], 5);
326 zTime[5] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327 if( rid == vid ){
328 @ <tr class="timelineCurrent">
329 }else {
330 @ <tr>
331 }
@@ -1474,11 +1494,17 @@
1474
1475 /*
1476 ** The input query q selects various records. Print a human-readable
1477 ** summary of those records.
1478 **
1479 ** Limit the number of entries printed to nLine.
 
 
 
 
 
 
1480 **
1481 ** The query should return these columns:
1482 **
1483 ** 0. rid
1484 ** 1. uuid
@@ -1487,12 +1513,14 @@
1487 ** 4. Number of non-merge children
1488 ** 5. Number of parents
1489 ** 6. mtime
1490 ** 7. branch
1491 */
1492 void print_timeline(Stmt *q, int mxLine, int verboseFlag){
 
1493 int nLine = 0;
 
1494 char zPrevDate[20];
1495 const char *zCurrentUuid=0;
1496 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
1497 Stmt fchngQuery; /* Query for file changes on check-ins */
1498 zPrevDate[0] = 0;
@@ -1500,11 +1528,11 @@
1500 if( g.localOpen ){
1501 int rid = db_lget_int("checkout", 0);
1502 zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1503 }
1504
1505 while( db_step(q)==SQLITE_ROW && nLine<=mxLine ){
1506 int rid = db_column_int(q, 0);
1507 const char *zId = db_column_text(q, 1);
1508 const char *zDate = db_column_text(q, 2);
1509 const char *zCom = db_column_text(q, 3);
1510 int nChild = db_column_int(q, 4);
@@ -1512,15 +1540,24 @@
1512 char *zFree = 0;
1513 int n = 0;
1514 char zPrefix[80];
1515 char zUuid[UUID_SIZE+1];
1516
 
 
 
 
 
 
 
 
 
1517 sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
1518 if( memcmp(zDate, zPrevDate, 10) ){
1519 fossil_print("=== %.10s ===\n", zDate);
1520 memcpy(zPrevDate, zDate, 10);
1521 nLine++;
1522 }
1523 if( zCom==0 ) zCom = "";
1524 fossil_print("%.8s ", &zDate[11]);
1525 zPrefix[0] = 0;
1526 if( nParent>1 ){
@@ -1540,11 +1577,11 @@
1540 if( fossil_strcmp(zCurrentUuid,zId)==0 ){
1541 sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
1542 n += strlen(zPrefix);
1543 }
1544 zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
1545 nLine += comment_print(zFree, 9, 79);
1546 sqlite3_free(zFree);
1547
1548 if(verboseFlag){
1549 if( !fchngQueryInit ){
1550 db_prepare(&fchngQuery,
@@ -1569,13 +1606,15 @@
1569 }else if( isDel ){
1570 fossil_print(" DELETED %s\n",zFilename);
1571 }else{
1572 fossil_print(" EDITED %s\n", zFilename);
1573 }
 
1574 }
1575 db_reset(&fchngQuery);
1576 }
 
1577 }
1578 if( fchngQueryInit ) db_finalize(&fchngQuery);
1579 }
1580
1581 /*
@@ -1642,24 +1681,27 @@
1642 ** The DATETIME should be in the ISO8601 format. For
1643 ** examples: "2007-08-18 07:21:21". You can also say "current"
1644 ** for the current version or "now" for the current time.
1645 **
1646 ** Options:
1647 ** -n|--limit N Output the first N changes (default 20)
 
1648 ** -t|--type TYPE Output items from the given types only, such as:
1649 ** ci = file commits only
1650 ** e = events only
1651 ** t = tickets only
1652 ** w = wiki commits only
1653 ** -v|--verbose Output the list of files changed by each commit
1654 ** and the type of each change (edited, deleted,
1655 ** etc.) after the checkin comment.
 
1656 */
1657 void timeline_cmd(void){
1658 Stmt q;
1659 int n, k;
1660 const char *zLimit;
 
1661 const char *zType;
1662 char *zOrigin;
1663 char *zDate;
1664 Blob sql;
1665 int objid = 0;
@@ -1670,18 +1712,27 @@
1670 if( !verboseFlag){
1671 verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
1672 }
1673 db_find_and_open_repository(0, 0);
1674 zLimit = find_option("limit","n",1);
 
1675 zType = find_option("type","t",1);
1676 if ( !zLimit ){
1677 zLimit = find_option("count",0,1);
1678 }
1679 if( zLimit ){
1680 n = atoi(zLimit);
1681 }else{
1682 n = 20;
 
 
 
 
 
 
 
 
1683 }
1684 if( g.argc>=4 ){
1685 k = strlen(g.argv[2]);
1686 if( strncmp(g.argv[2],"before",k)==0 ){
1687 mode = 1;
@@ -1694,11 +1745,11 @@
1694 }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
1695 mode = 4;
1696 }else if( strncmp(g.argv[2],"parents",k)==0 ){
1697 mode = 4;
1698 }else if(!zType && !zLimit){
1699 usage("?WHEN? ?BASELINE|DATETIME? ?-n|--limit N? ?-t|--type TYPE?");
1700 }
1701 if( '-' != *g.argv[3] ){
1702 zOrigin = g.argv[3];
1703 }else{
1704 zOrigin = "now";
@@ -1756,11 +1807,11 @@
1756 blob_appendf(&sql, " AND event.type=%Q ", zType);
1757 }
1758 blob_appendf(&sql, " ORDER BY event.mtime DESC");
1759 db_prepare(&q, blob_str(&sql));
1760 blob_reset(&sql);
1761 print_timeline(&q, n, verboseFlag);
1762 db_finalize(&q);
1763 }
1764
1765 /*
1766 ** This is a version of the "localtime()" function from the standard
@@ -1850,10 +1901,154 @@
1850 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1851 }
1852 db_finalize(&q);
1853 style_footer();
1854 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1855
1856 /*
1857 ** Helper for stats_report_by_month_year(), which generates a list of
1858 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
1859 ** or YYYY-MM.
@@ -1864,22 +2059,22 @@
1864 memcpy(yearPart, zTimeframe, 4);
1865 db_prepare(&stWeek,
1866 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
1867 "count(*) AS n, "
1868 "substr(date(mtime),1,%d) AS ym "
1869 "FROM event "
1870 "WHERE ym=%Q AND mtime < current_timestamp "
1871 "GROUP BY wk ORDER BY wk",
1872 strlen(zTimeframe),
1873 zTimeframe);
1874 while( SQLITE_ROW == db_step(&stWeek) ){
1875 const char * zWeek = db_column_text(&stWeek,0);
1876 const int nCount = db_column_int(&stWeek,1);
1877 cgi_printf("<a href='%s/timeline?"
1878 "yw=%t-%t&n=%d'>%s</a>",
1879 g.zTop, yearPart, zWeek,
1880 nCount, zWeek);
1881 }
1882 db_finalize(&stWeek);
1883 }
1884
1885 /*
@@ -1908,16 +2103,19 @@
1908 Blob header = empty_blob; /* Page header text */
1909 int nMaxEvents = 1; /* for calculating length of graph
1910 bars. */
1911 int iterations = 0; /* number of weeks/months we iterate
1912 over */
1913 blob_appendf(&header, "Timeline Events by year%s",
 
 
 
1914 (includeMonth ? "/month" : ""));
1915 blob_appendf(&sql,
1916 "SELECT substr(date(mtime),1,%d) AS timeframe, "
1917 "count(*) AS eventCount "
1918 "FROM event ",
1919 includeMonth ? 7 : 4);
1920 if(zUserName&&*zUserName){
1921 blob_appendf(&sql, " WHERE user=%Q ", zUserName);
1922 blob_appendf(&header," for user %q", zUserName);
1923 }
@@ -1950,14 +2148,15 @@
1950 }
1951 db_reset(&query);
1952 while( SQLITE_ROW == db_step(&query) ){
1953 const char * zTimeframe = db_column_text(&query, 0);
1954 const int nCount = db_column_int(&query, 1);
1955 const int nSize = nCount
1956 ? (int)(100 * nCount / nMaxEvents)
1957 : 1;
1958 showYearTotal = 0;
 
1959 if(includeMonth){
1960 /* For Month/year view, add a separator for each distinct year. */
1961 if(!*zPrevYear ||
1962 (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
1963 showYearTotal = *zPrevYear;
@@ -1981,21 +2180,23 @@
1981 nEventsPerYear += nCount;
1982 @<tr class='row%d(rowClass)'>
1983 @ <td>
1984 if(includeMonth){
1985 cgi_printf("<a href='%s/timeline?"
1986 "ym=%t&n=%d",
1987 g.zTop, zTimeframe, nCount );
 
1988 /* Reminder: n=nCount is not actually correct for bymonth unless
1989 that was the only user who caused events.
1990 */
1991 if( zUserName && *zUserName ){
1992 cgi_printf("&u=%t", zUserName);
1993 }
1994 cgi_printf("' target='_new'>%s</a>",zTimeframe);
1995 }else {
1996 cgi_printf("<a href='?view=byweek&y=%s", zTimeframe);
 
1997 if(zUserName && *zUserName){
1998 cgi_printf("&u=%t", zUserName);
1999 }
2000 cgi_printf("'>%s</a>", zTimeframe);
2001 }
@@ -2053,19 +2254,22 @@
2053 int rowClass = 0; /* counter for alternating
2054 row colors */
2055 Blob sql = empty_blob; /* SQL */
2056 int nMaxEvents = 1; /* max number of events for
2057 all rows. */
 
 
2058 blob_append(&sql,
2059 "SELECT user, "
2060 "COUNT(*) AS eventCount "
2061 "FROM event "
2062 "GROUP BY user ORDER BY eventCount DESC",
2063 -1);
2064 db_prepare(&query, blob_str(&sql));
2065 blob_reset(&sql);
2066 @ <h1>Timeline Events by User</h1>
 
2067 @ <table class='statistics-report-table-events' border='0'
2068 @ cellpadding='2' cellspacing='0' id='statsTable'>
2069 @ <thead><tr>
2070 @ <th>User</th>
2071 @ <th>Events</th>
@@ -2079,19 +2283,20 @@
2079 }
2080 db_reset(&query);
2081 while( SQLITE_ROW == db_step(&query) ){
2082 const char * zUser = db_column_text(&query, 0);
2083 const int nCount = db_column_int(&query, 1);
2084 const int nSize = nCount
2085 ? (int)(100 * nCount / nMaxEvents)
2086 : 0;
2087 if(!nCount) continue /* arguable! Possible? */;
 
2088 rowClass = ++nRowNumber % 2;
2089 nEventTotal += nCount;
2090 @<tr class='row%d(rowClass)'>
2091 @ <td>
2092 @ <a href="?view=bymonth&user=%h(zUser)">%h(zUser)</a>
2093 @ </td><td>%d(nCount)</td>
2094 @ <td>
2095 @ <div class='statistics-report-graph-line'
2096 @ style='height:16px;width:%d(nSize)%%;'>
2097 @ </div></td>
@@ -2120,15 +2325,16 @@
2120 char * zDefaultYear = NULL;
2121 Blob sql = empty_blob;
2122 int nMaxEvents = 1; /* max number of events for
2123 all rows. */
2124 int iterations = 0; /* # of active time periods. */
2125
 
2126 cgi_printf("Select year: ");
2127 blob_append(&sql,
2128 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2129 "FROM event WHERE 1 ", -1);
2130 if(zUserName&&*zUserName){
2131 blob_appendf(&sql,"AND user=%Q ", zUserName);
2132 }
2133 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2134 db_prepare(&qYears, blob_str(&sql));
@@ -2136,11 +2342,12 @@
2136 while( SQLITE_ROW == db_step(&qYears) ){
2137 const char * zT = db_column_text(&qYears, 0);
2138 if( i++ ){
2139 cgi_printf(" ");
2140 }
2141 cgi_printf("<a href='?view=byweek&y=%s", zT);
 
2142 if(zUserName && *zUserName){
2143 cgi_printf("&user=%t",zUserName);
2144 }
2145 cgi_printf("'>%s</a>",zT);
2146 }
@@ -2154,16 +2361,17 @@
2154 if(4 == nYear){
2155 Stmt stWeek = empty_Stmt;
2156 int rowCount = 0;
2157 int total = 0;
2158 Blob header = empty_blob;
2159 blob_appendf(&header, "Timeline events for the calendar weeks "
2160 "of %h", zYear);
 
2161 blob_appendf(&sql,
2162 "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
2163 "count(*) AS n "
2164 "FROM event "
2165 "WHERE %Q=substr(date(mtime),1,4) "
2166 "AND mtime < current_timestamp ",
2167 zYear);
2168 if(zUserName&&*zUserName){
2169 blob_appendf(&sql, " AND user=%Q ", zUserName);
@@ -2192,17 +2400,19 @@
2192 }
2193 db_reset(&stWeek);
2194 while( SQLITE_ROW == db_step(&stWeek) ){
2195 const char * zWeek = db_column_text(&stWeek,0);
2196 const int nCount = db_column_int(&stWeek,1);
2197 const int nSize = nCount
2198 ? (int)(100 * nCount / nMaxEvents)
2199 : 0;
 
2200 total += nCount;
2201 cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2202 cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d",
2203 g.zTop, zYear, zWeek, nCount);
 
2204 if(zUserName && *zUserName){
2205 cgi_printf("&u=%t",zUserName);
2206 }
2207 cgi_printf("'>%s</a></td>",zWeek);
2208
@@ -2235,10 +2445,20 @@
2235 **
2236 ** Query Parameters:
2237 **
2238 ** view=REPORT_NAME Valid values: bymonth, byyear, byuser
2239 ** user=NAME Restricts statistics to the given user
 
 
 
 
 
 
 
 
 
 
2240 */
2241 void stats_report_page(){
2242 HQuery url; /* URL for various branch links */
2243 const char * zView = P("view"); /* Which view/report to show. */
2244 const char *zUserName = P("user");
2245
--- src/timeline.c
+++ src/timeline.c
@@ -16,13 +16,13 @@
16 *******************************************************************************
17 **
18 ** This file contains code to implement the timeline web page
19 **
20 */
21 #include "config.h"
22 #include <string.h>
23 #include <time.h>
 
24 #include "timeline.h"
25
26 /*
27 ** Shorten a UUID so that is the minimum length needed to contain
28 ** at least one digit in the range 'a'..'f'. The minimum length is 10.
@@ -246,16 +246,20 @@
246 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
247 Stmt fchngQuery; /* Query for file changes on check-ins */
248 static Stmt qbranch;
249 int pendingEndTr = 0; /* True if a </td></tr> is needed */
250 int vid = 0; /* Current checkout version */
251 int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
252 2: YYYY-MM-DD HH:MM
253 3: YYMMDD HH:MM */
254
255 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
256 vid = db_lget_int("checkout", 0);
257 }
258 zPrevDate[0] = 0;
259 mxWikiLen = db_get_int("timeline-max-comment", 0);
260 dateFormat = db_get_int("timeline-date-format", 0);
261 if( tmFlags & TIMELINE_GRAPH ){
262 pGraph = graph_init();
263 /* style is not moved to css, because this is
264 ** a technical div for the timeline graph
265 */
@@ -282,11 +286,11 @@
286 int tagid = db_column_int(pQuery, 9);
287 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
288 const char *zBr = 0; /* Branch */
289 int commentColumn = 3; /* Column containing comment text */
290 int modPending; /* Pending moderation */
291 char zTime[20];
292
293 modPending = moderation_pending(rid);
294 if( tagid ){
295 if( modPending ) tagid = -tagid;
296 if( tagid==prevTagid ){
@@ -314,18 +318,34 @@
318 }
319 prevWasDivider = 1;
320 continue;
321 }
322 prevWasDivider = 0;
323 if( dateFormat<2 ){
324 if( memcmp(zDate, zPrevDate, 10) ){
325 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
326 @ <tr><td>
327 @ <div class="divider timelineDate">%s(zPrevDate)</div>
328 @ </td><td></td><td></td></tr>
329 }
330 memcpy(zTime, &zDate[11], 5+dateFormat*3);
331 zTime[5+dateFormat*3] = 0;
332 }else if(3==dateFormat){
333 /* YYMMDD HH:MM */
334 int pos = 0;
335 zTime[pos++] = zDate[2]; zTime[pos++] = zDate[3]; /* YY */
336 zTime[pos++] = zDate[5]; zTime[pos++] = zDate[6]; /* MM */
337 zTime[pos++] = zDate[8]; zTime[pos++] = zDate[9]; /* DD */
338 zTime[pos++] = ' ';
339 zTime[pos++] = zDate[11]; zTime[pos++] = zDate[12]; /* HH */
340 zTime[pos++] = ':';
341 zTime[pos++] = zDate[14]; zTime[pos++] = zDate[15]; /* MM */
342 zTime[pos++] = 0;
343 }else{
344 /* YYYY-MM-DD HH:MM */
345 sqlite3_snprintf(sizeof(zTime), zTime, "%.16s", zDate);
346 }
347 if( rid == vid ){
348 @ <tr class="timelineCurrent">
349 }else {
350 @ <tr>
351 }
@@ -1474,11 +1494,17 @@
1494
1495 /*
1496 ** The input query q selects various records. Print a human-readable
1497 ** summary of those records.
1498 **
1499 ** Limit number of lines or entries printed to nLimit. If nLimit is zero
1500 ** there is no limit. If nLimit is greater than zero, limit the number of
1501 ** complete entries printed. If nLimit is less than zero, attempt to limit
1502 ** the number of lines printed (this is basically the legacy behavior).
1503 ** The line limit, if used, is approximate because it is only checked on a
1504 ** per-entry basis. If verbose mode, the file name details are considered
1505 ** to be part of the entry.
1506 **
1507 ** The query should return these columns:
1508 **
1509 ** 0. rid
1510 ** 1. uuid
@@ -1487,12 +1513,14 @@
1513 ** 4. Number of non-merge children
1514 ** 5. Number of parents
1515 ** 6. mtime
1516 ** 7. branch
1517 */
1518 void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){
1519 int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
1520 int nLine = 0;
1521 int nEntry = 0;
1522 char zPrevDate[20];
1523 const char *zCurrentUuid=0;
1524 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
1525 Stmt fchngQuery; /* Query for file changes on check-ins */
1526 zPrevDate[0] = 0;
@@ -1500,11 +1528,11 @@
1528 if( g.localOpen ){
1529 int rid = db_lget_int("checkout", 0);
1530 zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1531 }
1532
1533 while( db_step(q)==SQLITE_ROW ){
1534 int rid = db_column_int(q, 0);
1535 const char *zId = db_column_text(q, 1);
1536 const char *zDate = db_column_text(q, 2);
1537 const char *zCom = db_column_text(q, 3);
1538 int nChild = db_column_int(q, 4);
@@ -1512,15 +1540,24 @@
1540 char *zFree = 0;
1541 int n = 0;
1542 char zPrefix[80];
1543 char zUuid[UUID_SIZE+1];
1544
1545 if( nAbsLimit!=0 ){
1546 if( nLimit<0 && nLine>=nAbsLimit ){
1547 fossil_print("=== line limit (%d) reached ===\n", nAbsLimit);
1548 break; /* line count limit hit, stop. */
1549 }else if( nEntry>=nAbsLimit ){
1550 fossil_print("=== entry limit (%d) reached ===\n", nAbsLimit);
1551 break; /* entry count limit hit, stop. */
1552 }
1553 }
1554 sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
1555 if( memcmp(zDate, zPrevDate, 10) ){
1556 fossil_print("=== %.10s ===\n", zDate);
1557 memcpy(zPrevDate, zDate, 10);
1558 nLine++; /* record another line */
1559 }
1560 if( zCom==0 ) zCom = "";
1561 fossil_print("%.8s ", &zDate[11]);
1562 zPrefix[0] = 0;
1563 if( nParent>1 ){
@@ -1540,11 +1577,11 @@
1577 if( fossil_strcmp(zCurrentUuid,zId)==0 ){
1578 sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
1579 n += strlen(zPrefix);
1580 }
1581 zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
1582 nLine += comment_print(zFree, 9, width); /* record another X lines */
1583 sqlite3_free(zFree);
1584
1585 if(verboseFlag){
1586 if( !fchngQueryInit ){
1587 db_prepare(&fchngQuery,
@@ -1569,13 +1606,15 @@
1606 }else if( isDel ){
1607 fossil_print(" DELETED %s\n",zFilename);
1608 }else{
1609 fossil_print(" EDITED %s\n", zFilename);
1610 }
1611 nLine++; /* record another line */
1612 }
1613 db_reset(&fchngQuery);
1614 }
1615 nEntry++; /* record another complete entry */
1616 }
1617 if( fchngQueryInit ) db_finalize(&fchngQuery);
1618 }
1619
1620 /*
@@ -1642,24 +1681,27 @@
1681 ** The DATETIME should be in the ISO8601 format. For
1682 ** examples: "2007-08-18 07:21:21". You can also say "current"
1683 ** for the current version or "now" for the current time.
1684 **
1685 ** Options:
1686 ** -n|--limit N Output the first N entries (default 20 lines).
1687 ** N=0 means no limit.
1688 ** -t|--type TYPE Output items from the given types only, such as:
1689 ** ci = file commits only
1690 ** e = events only
1691 ** t = tickets only
1692 ** w = wiki commits only
1693 ** -v|--verbose Output the list of files changed by each commit
1694 ** and the type of each change (edited, deleted,
1695 ** etc.) after the checkin comment.
1696 ** -W|--width <num> With of lines (default 79). Must be >20 or 0.
1697 */
1698 void timeline_cmd(void){
1699 Stmt q;
1700 int n, k, width;
1701 const char *zLimit;
1702 const char *zWidth;
1703 const char *zType;
1704 char *zOrigin;
1705 char *zDate;
1706 Blob sql;
1707 int objid = 0;
@@ -1670,18 +1712,27 @@
1712 if( !verboseFlag){
1713 verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
1714 }
1715 db_find_and_open_repository(0, 0);
1716 zLimit = find_option("limit","n",1);
1717 zWidth = find_option("width","W",1);
1718 zType = find_option("type","t",1);
1719 if ( !zLimit ){
1720 zLimit = find_option("count",0,1);
1721 }
1722 if( zLimit ){
1723 n = atoi(zLimit);
1724 }else{
1725 n = -20;
1726 }
1727 if( zWidth ){
1728 width = atoi(zWidth);
1729 if( (width!=0) && (width<=20) ){
1730 fossil_fatal("--width|-W value must be >20 or 0");
1731 }
1732 }else{
1733 width = 79;
1734 }
1735 if( g.argc>=4 ){
1736 k = strlen(g.argv[2]);
1737 if( strncmp(g.argv[2],"before",k)==0 ){
1738 mode = 1;
@@ -1694,11 +1745,11 @@
1745 }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){
1746 mode = 4;
1747 }else if( strncmp(g.argv[2],"parents",k)==0 ){
1748 mode = 4;
1749 }else if(!zType && !zLimit){
1750 usage("?WHEN? ?BASELINE|DATETIME? ?-n|--limit #? ?-t|--type TYPE? ?-W|--width WIDTH?");
1751 }
1752 if( '-' != *g.argv[3] ){
1753 zOrigin = g.argv[3];
1754 }else{
1755 zOrigin = "now";
@@ -1756,11 +1807,11 @@
1807 blob_appendf(&sql, " AND event.type=%Q ", zType);
1808 }
1809 blob_appendf(&sql, " ORDER BY event.mtime DESC");
1810 db_prepare(&q, blob_str(&sql));
1811 blob_reset(&sql);
1812 print_timeline(&q, n, width, verboseFlag);
1813 db_finalize(&q);
1814 }
1815
1816 /*
1817 ** This is a version of the "localtime()" function from the standard
@@ -1850,10 +1901,154 @@
1901 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1902 }
1903 db_finalize(&q);
1904 style_footer();
1905 }
1906
1907
1908 /*
1909 ** Used by stats_report_xxxxx() to remember which type of events
1910 ** to show. Populated by stats_report_init_view() and holds the
1911 ** return value of that function.
1912 */
1913 static int statsReportType = 0;
1914
1915 /*
1916 ** Set by stats_report_init_view() to one of the y=XXXX values
1917 ** accepted by /timeline?y=XXXX.
1918 */
1919 static char const * statsReportTimelineYFlag = NULL;
1920
1921 /*
1922 ** Creates a TEMP VIEW named v_reports which is a wrapper around the
1923 ** EVENT table filtered on event.type. It looks for the request
1924 ** parameter 'type' (reminder: we "should" use 'y' for consistency
1925 ** with /timeline, but /reports uses 'y' for the year) and expects it
1926 ** to contain one of the conventional values from event.type or the
1927 ** value "all", which is treated as equivalent to "*". By default (if
1928 ** no 'y' is specified), "*" is assumed (that is also the default for
1929 ** invalid/unknown filter values). That 'y' filter is the one used for
1930 ** the event list. Note that a filter of "*" or "all" is equivalent to
1931 ** querying against the full event table. The view, however, adds an
1932 ** abstraction level to simplify the implementation code for the
1933 ** various /reports pages.
1934 **
1935 ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
1936 ** filter it applies, or '*' if no filter is applied (i.e. if "all" is
1937 ** used).
1938 */
1939 static int stats_report_init_view(){
1940 char const * zType = PD("type","*"); /* analog to /timeline?y=... */
1941 char const * zRealType = NULL; /* normalized form of zType */
1942 int rc = 0; /* result code */
1943 assert( !statsReportType && "Must not be called more than once." );
1944 switch( (zType && *zType) ? *zType : 0 ){
1945 case 'c':
1946 case 'C':
1947 zRealType = "ci";
1948 rc = *zRealType;
1949 break;
1950 case 'e':
1951 case 'E':
1952 zRealType = "e";
1953 rc = *zRealType;
1954 break;
1955 case 'g':
1956 case 'G':
1957 zRealType = "g";
1958 rc = *zRealType;
1959 break;
1960 case 't':
1961 case 'T':
1962 zRealType = "t";
1963 rc = *zRealType;
1964 break;
1965 case 'w':
1966 case 'W':
1967 zRealType = "w";
1968 rc = *zRealType;
1969 break;
1970 default:
1971 rc = '*';
1972 break;
1973 }
1974 assert(0 != rc);
1975 if(zRealType){
1976 statsReportTimelineYFlag = zRealType;
1977 db_multi_exec("CREATE TEMP VIEW v_reports AS "
1978 "SELECT * FROM event WHERE type GLOB %Q",
1979 zRealType);
1980 }else{
1981 statsReportTimelineYFlag = "a";
1982 db_multi_exec("CREATE TEMP VIEW v_reports AS "
1983 "SELECT * FROM event");
1984 }
1985 return statsReportType = rc;
1986 }
1987
1988 /*
1989 ** Returns a string suitable (for a given value of suitable) for
1990 ** use in a label with the header of the /reports pages, dependent
1991 ** on the 'type' flag. See stats_report_init_view().
1992 ** The returned bytes are static.
1993 */
1994 static char const * stats_report_label_for_type(){
1995 assert( statsReportType && "Must call stats_report_init_view() first." );
1996 switch( statsReportType ){
1997 case 'c':
1998 return "checkins";
1999 case 'w':
2000 return "wiki changes";
2001 case 't':
2002 return "ticket changes";
2003 case 'g':
2004 return "tag changes";
2005 default:
2006 return "all types";
2007 }
2008 }
2009
2010 /*
2011 ** A helper for the /reports family of pages which prints out a menu
2012 ** of links for the various type=XXX flags. zCurrentViewName must be
2013 ** the name/value of the 'view' parameter which is in effect at
2014 ** the time this is called. e.g. if called from the 'byuser' view
2015 ** then zCurrentViewName must be "byuser".
2016 */
2017 static void stats_report_event_types_menu(char const * zCurrentViewName){
2018 char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName);
2019 cgi_printf("<div>");
2020 cgi_printf("<span>Event types:</span> ");
2021 if('*' == statsReportType){
2022 cgi_printf(" <strong>all</strong>", zTop);
2023 }else{
2024 cgi_printf(" <a href='%s'>all</a>", zTop);
2025 }
2026 if('c' == statsReportType){
2027 cgi_printf(" <strong>checkins</strong>", zTop);
2028 }else{
2029 cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
2030 }
2031 if( 't' == statsReportType ){
2032 cgi_printf(" <strong>tickets</strong>", zTop);
2033 }else{
2034 cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
2035 }
2036 if( 'g' == statsReportType ){
2037 cgi_printf(" <strong>tags</strong>", zTop);
2038 }else{
2039 cgi_printf(" <a href='%s&type=g'>tags</a>", zTop);
2040 }
2041 if( 'w' == statsReportType ){
2042 cgi_printf(" <strong>wiki</strong>", zTop);
2043 }else{
2044 cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop);
2045 }
2046 fossil_free(zTop);
2047 cgi_printf("</div>");
2048 }
2049
2050
2051 /*
2052 ** Helper for stats_report_by_month_year(), which generates a list of
2053 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2054 ** or YYYY-MM.
@@ -1864,22 +2059,22 @@
2059 memcpy(yearPart, zTimeframe, 4);
2060 db_prepare(&stWeek,
2061 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
2062 "count(*) AS n, "
2063 "substr(date(mtime),1,%d) AS ym "
2064 "FROM v_reports "
2065 "WHERE ym=%Q AND mtime < current_timestamp "
2066 "GROUP BY wk ORDER BY wk",
2067 strlen(zTimeframe),
2068 zTimeframe);
2069 while( SQLITE_ROW == db_step(&stWeek) ){
2070 const char * zWeek = db_column_text(&stWeek,0);
2071 const int nCount = db_column_int(&stWeek,1);
2072 cgi_printf("<a href='%s/timeline?"
2073 "yw=%t-%t&n=%d&y=%s'>%s</a>",
2074 g.zTop, yearPart, zWeek,
2075 nCount, statsReportTimelineYFlag, zWeek);
2076 }
2077 db_finalize(&stWeek);
2078 }
2079
2080 /*
@@ -1908,16 +2103,19 @@
2103 Blob header = empty_blob; /* Page header text */
2104 int nMaxEvents = 1; /* for calculating length of graph
2105 bars. */
2106 int iterations = 0; /* number of weeks/months we iterate
2107 over */
2108 stats_report_init_view();
2109 stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" );
2110 blob_appendf(&header, "Timeline Events (%s) by year%s",
2111 stats_report_label_for_type(),
2112 (includeMonth ? "/month" : ""));
2113 blob_appendf(&sql,
2114 "SELECT substr(date(mtime),1,%d) AS timeframe, "
2115 "count(*) AS eventCount "
2116 "FROM v_reports ",
2117 includeMonth ? 7 : 4);
2118 if(zUserName&&*zUserName){
2119 blob_appendf(&sql, " WHERE user=%Q ", zUserName);
2120 blob_appendf(&header," for user %q", zUserName);
2121 }
@@ -1950,14 +2148,15 @@
2148 }
2149 db_reset(&query);
2150 while( SQLITE_ROW == db_step(&query) ){
2151 const char * zTimeframe = db_column_text(&query, 0);
2152 const int nCount = db_column_int(&query, 1);
2153 int nSize = nCount
2154 ? (int)(100 * nCount / nMaxEvents)
2155 : 1;
2156 showYearTotal = 0;
2157 if(!nSize) nSize = 1;
2158 if(includeMonth){
2159 /* For Month/year view, add a separator for each distinct year. */
2160 if(!*zPrevYear ||
2161 (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
2162 showYearTotal = *zPrevYear;
@@ -1981,21 +2180,23 @@
2180 nEventsPerYear += nCount;
2181 @<tr class='row%d(rowClass)'>
2182 @ <td>
2183 if(includeMonth){
2184 cgi_printf("<a href='%s/timeline?"
2185 "ym=%t&n=%d&y=%s",
2186 g.zTop, zTimeframe, nCount,
2187 statsReportTimelineYFlag );
2188 /* Reminder: n=nCount is not actually correct for bymonth unless
2189 that was the only user who caused events.
2190 */
2191 if( zUserName && *zUserName ){
2192 cgi_printf("&u=%t", zUserName);
2193 }
2194 cgi_printf("' target='_new'>%s</a>",zTimeframe);
2195 }else {
2196 cgi_printf("<a href='?view=byweek&y=%s&type=%c",
2197 zTimeframe, (char)statsReportType);
2198 if(zUserName && *zUserName){
2199 cgi_printf("&u=%t", zUserName);
2200 }
2201 cgi_printf("'>%s</a>", zTimeframe);
2202 }
@@ -2053,19 +2254,22 @@
2254 int rowClass = 0; /* counter for alternating
2255 row colors */
2256 Blob sql = empty_blob; /* SQL */
2257 int nMaxEvents = 1; /* max number of events for
2258 all rows. */
2259 stats_report_init_view();
2260 stats_report_event_types_menu("byuser");
2261 blob_append(&sql,
2262 "SELECT user, "
2263 "COUNT(*) AS eventCount "
2264 "FROM v_reports "
2265 "GROUP BY user ORDER BY eventCount DESC",
2266 -1);
2267 db_prepare(&query, blob_str(&sql));
2268 blob_reset(&sql);
2269 @ <h1>Timeline Events
2270 @ (%s(stats_report_label_for_type())) by User</h1>
2271 @ <table class='statistics-report-table-events' border='0'
2272 @ cellpadding='2' cellspacing='0' id='statsTable'>
2273 @ <thead><tr>
2274 @ <th>User</th>
2275 @ <th>Events</th>
@@ -2079,19 +2283,20 @@
2283 }
2284 db_reset(&query);
2285 while( SQLITE_ROW == db_step(&query) ){
2286 const char * zUser = db_column_text(&query, 0);
2287 const int nCount = db_column_int(&query, 1);
2288 int nSize = nCount
2289 ? (int)(100 * nCount / nMaxEvents)
2290 : 0;
2291 if(!nCount) continue /* arguable! Possible? */;
2292 else if(!nSize) nSize = 1;
2293 rowClass = ++nRowNumber % 2;
2294 nEventTotal += nCount;
2295 @<tr class='row%d(rowClass)'>
2296 @ <td>
2297 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2298 @ </td><td>%d(nCount)</td>
2299 @ <td>
2300 @ <div class='statistics-report-graph-line'
2301 @ style='height:16px;width:%d(nSize)%%;'>
2302 @ </div></td>
@@ -2120,15 +2325,16 @@
2325 char * zDefaultYear = NULL;
2326 Blob sql = empty_blob;
2327 int nMaxEvents = 1; /* max number of events for
2328 all rows. */
2329 int iterations = 0; /* # of active time periods. */
2330 stats_report_init_view();
2331 stats_report_event_types_menu("byweek");
2332 cgi_printf("Select year: ");
2333 blob_append(&sql,
2334 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2335 "FROM v_reports WHERE 1 ", -1);
2336 if(zUserName&&*zUserName){
2337 blob_appendf(&sql,"AND user=%Q ", zUserName);
2338 }
2339 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2340 db_prepare(&qYears, blob_str(&sql));
@@ -2136,11 +2342,12 @@
2342 while( SQLITE_ROW == db_step(&qYears) ){
2343 const char * zT = db_column_text(&qYears, 0);
2344 if( i++ ){
2345 cgi_printf(" ");
2346 }
2347 cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2348 (char)statsReportType);
2349 if(zUserName && *zUserName){
2350 cgi_printf("&user=%t",zUserName);
2351 }
2352 cgi_printf("'>%s</a>",zT);
2353 }
@@ -2154,16 +2361,17 @@
2361 if(4 == nYear){
2362 Stmt stWeek = empty_Stmt;
2363 int rowCount = 0;
2364 int total = 0;
2365 Blob header = empty_blob;
2366 blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
2367 "of %h", stats_report_label_for_type(),
2368 zYear);
2369 blob_appendf(&sql,
2370 "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
2371 "count(*) AS n "
2372 "FROM v_reports "
2373 "WHERE %Q=substr(date(mtime),1,4) "
2374 "AND mtime < current_timestamp ",
2375 zYear);
2376 if(zUserName&&*zUserName){
2377 blob_appendf(&sql, " AND user=%Q ", zUserName);
@@ -2192,17 +2400,19 @@
2400 }
2401 db_reset(&stWeek);
2402 while( SQLITE_ROW == db_step(&stWeek) ){
2403 const char * zWeek = db_column_text(&stWeek,0);
2404 const int nCount = db_column_int(&stWeek,1);
2405 int nSize = nCount
2406 ? (int)(100 * nCount / nMaxEvents)
2407 : 0;
2408 if(!nSize) nSize = 1;
2409 total += nCount;
2410 cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2411 cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d&y=%s",
2412 g.zTop, zYear, zWeek, nCount,
2413 statsReportTimelineYFlag);
2414 if(zUserName && *zUserName){
2415 cgi_printf("&u=%t",zUserName);
2416 }
2417 cgi_printf("'>%s</a></td>",zWeek);
2418
@@ -2235,10 +2445,20 @@
2445 **
2446 ** Query Parameters:
2447 **
2448 ** view=REPORT_NAME Valid values: bymonth, byyear, byuser
2449 ** user=NAME Restricts statistics to the given user
2450 ** type=TYPE Restricts the report to a specific event type:
2451 ** ci (checkin), w (wiki), t (ticket), g (tag)
2452 ** Defaulting to all event types.
2453 **
2454 ** The view-specific query parameters include:
2455 **
2456 ** view=byweek:
2457 **
2458 ** y=YYYY The year to report (default is the server's
2459 ** current year).
2460 */
2461 void stats_report_page(){
2462 HQuery url; /* URL for various branch links */
2463 const char * zView = P("view"); /* Which view/report to show. */
2464 const char *zUserName = P("user");
2465
+8 -7
--- src/tkt.c
+++ src/tkt.c
@@ -296,11 +296,11 @@
296296
db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid);
297297
tktid = 0;
298298
db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
299299
while( db_step(&q)==SQLITE_ROW ){
300300
int rid = db_column_int(&q, 0);
301
- pTicket = manifest_get(rid, CFTYPE_TICKET);
301
+ pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
302302
if( pTicket ){
303303
tktid = ticket_insert(pTicket, rid, tktid);
304304
manifest_ticket_event(rid, pTicket, createFlag, tagid);
305305
manifest_destroy(pTicket);
306306
}
@@ -621,15 +621,16 @@
621621
@ <font color="blue">
622622
@ <p>Ticket artifact that would have been submitted:</p>
623623
@ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
624624
@ <hr /></font>
625625
return TH_OK;
626
- }else if( g.thTrace ){
627
- Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
628
- "}<br />\n",
629
- blob_str(&tktchng));
630626
}else{
627
+ if( g.thTrace ){
628
+ Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
629
+ "}<br />\n",
630
+ blob_str(&tktchng));
631
+ }
631632
ticket_put(&tktchng, zUuid,
632633
(g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1));
633634
}
634635
return ticket_change();
635636
}
@@ -943,11 +944,11 @@
943944
@ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
944945
@ (rid %d(rid)) by
945946
hyperlink_to_user(zUser,zDate," on");
946947
hyperlink_to_date(zDate, ".</p>");
947948
}else{
948
- pTicket = manifest_get(rid, CFTYPE_TICKET);
949
+ pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
949950
if( pTicket ){
950951
@
951952
@ <li><p>Ticket change
952953
@ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
953954
@ (rid %d(rid)) by
@@ -1243,11 +1244,11 @@
12431244
}else{
12441245
fossil_print("Add attachment %s\n", zFile);
12451246
}
12461247
fossil_print(" by %s on %s\n", zUser, zDate);
12471248
}else{
1248
- pTicket = manifest_get(rid, CFTYPE_TICKET);
1249
+ pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
12491250
if( pTicket ){
12501251
int i;
12511252
12521253
fossil_print("Ticket Change by %s on %s:\n",
12531254
pTicket->zUser, zDate);
12541255
--- src/tkt.c
+++ src/tkt.c
@@ -296,11 +296,11 @@
296 db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid);
297 tktid = 0;
298 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
299 while( db_step(&q)==SQLITE_ROW ){
300 int rid = db_column_int(&q, 0);
301 pTicket = manifest_get(rid, CFTYPE_TICKET);
302 if( pTicket ){
303 tktid = ticket_insert(pTicket, rid, tktid);
304 manifest_ticket_event(rid, pTicket, createFlag, tagid);
305 manifest_destroy(pTicket);
306 }
@@ -621,15 +621,16 @@
621 @ <font color="blue">
622 @ <p>Ticket artifact that would have been submitted:</p>
623 @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
624 @ <hr /></font>
625 return TH_OK;
626 }else if( g.thTrace ){
627 Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
628 "}<br />\n",
629 blob_str(&tktchng));
630 }else{
 
 
 
 
 
631 ticket_put(&tktchng, zUuid,
632 (g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1));
633 }
634 return ticket_change();
635 }
@@ -943,11 +944,11 @@
943 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
944 @ (rid %d(rid)) by
945 hyperlink_to_user(zUser,zDate," on");
946 hyperlink_to_date(zDate, ".</p>");
947 }else{
948 pTicket = manifest_get(rid, CFTYPE_TICKET);
949 if( pTicket ){
950 @
951 @ <li><p>Ticket change
952 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
953 @ (rid %d(rid)) by
@@ -1243,11 +1244,11 @@
1243 }else{
1244 fossil_print("Add attachment %s\n", zFile);
1245 }
1246 fossil_print(" by %s on %s\n", zUser, zDate);
1247 }else{
1248 pTicket = manifest_get(rid, CFTYPE_TICKET);
1249 if( pTicket ){
1250 int i;
1251
1252 fossil_print("Ticket Change by %s on %s:\n",
1253 pTicket->zUser, zDate);
1254
--- src/tkt.c
+++ src/tkt.c
@@ -296,11 +296,11 @@
296 db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid);
297 tktid = 0;
298 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
299 while( db_step(&q)==SQLITE_ROW ){
300 int rid = db_column_int(&q, 0);
301 pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
302 if( pTicket ){
303 tktid = ticket_insert(pTicket, rid, tktid);
304 manifest_ticket_event(rid, pTicket, createFlag, tagid);
305 manifest_destroy(pTicket);
306 }
@@ -621,15 +621,16 @@
621 @ <font color="blue">
622 @ <p>Ticket artifact that would have been submitted:</p>
623 @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
624 @ <hr /></font>
625 return TH_OK;
 
 
 
 
626 }else{
627 if( g.thTrace ){
628 Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
629 "}<br />\n",
630 blob_str(&tktchng));
631 }
632 ticket_put(&tktchng, zUuid,
633 (g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1));
634 }
635 return ticket_change();
636 }
@@ -943,11 +944,11 @@
944 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
945 @ (rid %d(rid)) by
946 hyperlink_to_user(zUser,zDate," on");
947 hyperlink_to_date(zDate, ".</p>");
948 }else{
949 pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
950 if( pTicket ){
951 @
952 @ <li><p>Ticket change
953 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
954 @ (rid %d(rid)) by
@@ -1243,11 +1244,11 @@
1244 }else{
1245 fossil_print("Add attachment %s\n", zFile);
1246 }
1247 fossil_print(" by %s on %s\n", zUser, zDate);
1248 }else{
1249 pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
1250 if( pTicket ){
1251 int i;
1252
1253 fossil_print("Ticket Change by %s on %s:\n",
1254 pTicket->zUser, zDate);
1255
+3 -6
--- src/update.c
+++ src/update.c
@@ -125,13 +125,10 @@
125125
debugFlag = find_option("debug",0,0)!=0;
126126
setmtimeFlag = find_option("setmtime",0,0)!=0;
127127
capture_case_sensitive_option();
128128
db_must_be_within_tree();
129129
vid = db_lget_int("checkout", 0);
130
- if( vid==0 ){
131
- fossil_fatal("cannot find current version");
132
- }
133130
user_select();
134131
if( !dryRunFlag && !internalUpdate ){
135132
autosync(SYNC_PULL + SYNC_VERBOSE*verboseFlag);
136133
}
137134
@@ -188,11 +185,11 @@
188185
"%s "
189186
" AND event.objid IN leaves"
190187
" ORDER BY event.mtime DESC",
191188
timeline_query_for_tty()
192189
);
193
- print_timeline(&q, 100, 0);
190
+ print_timeline(&q, -100, 79, 0);
194191
db_finalize(&q);
195192
fossil_fatal("Multiple descendants");
196193
}
197194
}
198195
tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -200,11 +197,11 @@
200197
" ORDER BY event.mtime DESC");
201198
if( tid==0 ) tid = vid;
202199
}
203200
204201
if( tid==0 ){
205
- fossil_panic("unable to find a version to update to.");
202
+ return;
206203
}
207204
208205
db_begin_transaction();
209206
vfile_check_signature(vid, CKSIG_ENOTFILE);
210207
if( !dryRunFlag && !internalUpdate ) undo_begin();
@@ -635,11 +632,11 @@
635632
}
636633
if( !is_a_version(rid) ){
637634
if( errCode>0 ) return errCode;
638635
fossil_fatal("no such checkin: %s", revision);
639636
}
640
- pManifest = manifest_get(rid, CFTYPE_MANIFEST);
637
+ pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
641638
642639
if( pManifest ){
643640
pFile = manifest_file_find(pManifest, file);
644641
if( pFile ){
645642
int rc;
646643
--- src/update.c
+++ src/update.c
@@ -125,13 +125,10 @@
125 debugFlag = find_option("debug",0,0)!=0;
126 setmtimeFlag = find_option("setmtime",0,0)!=0;
127 capture_case_sensitive_option();
128 db_must_be_within_tree();
129 vid = db_lget_int("checkout", 0);
130 if( vid==0 ){
131 fossil_fatal("cannot find current version");
132 }
133 user_select();
134 if( !dryRunFlag && !internalUpdate ){
135 autosync(SYNC_PULL + SYNC_VERBOSE*verboseFlag);
136 }
137
@@ -188,11 +185,11 @@
188 "%s "
189 " AND event.objid IN leaves"
190 " ORDER BY event.mtime DESC",
191 timeline_query_for_tty()
192 );
193 print_timeline(&q, 100, 0);
194 db_finalize(&q);
195 fossil_fatal("Multiple descendants");
196 }
197 }
198 tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -200,11 +197,11 @@
200 " ORDER BY event.mtime DESC");
201 if( tid==0 ) tid = vid;
202 }
203
204 if( tid==0 ){
205 fossil_panic("unable to find a version to update to.");
206 }
207
208 db_begin_transaction();
209 vfile_check_signature(vid, CKSIG_ENOTFILE);
210 if( !dryRunFlag && !internalUpdate ) undo_begin();
@@ -635,11 +632,11 @@
635 }
636 if( !is_a_version(rid) ){
637 if( errCode>0 ) return errCode;
638 fossil_fatal("no such checkin: %s", revision);
639 }
640 pManifest = manifest_get(rid, CFTYPE_MANIFEST);
641
642 if( pManifest ){
643 pFile = manifest_file_find(pManifest, file);
644 if( pFile ){
645 int rc;
646
--- src/update.c
+++ src/update.c
@@ -125,13 +125,10 @@
125 debugFlag = find_option("debug",0,0)!=0;
126 setmtimeFlag = find_option("setmtime",0,0)!=0;
127 capture_case_sensitive_option();
128 db_must_be_within_tree();
129 vid = db_lget_int("checkout", 0);
 
 
 
130 user_select();
131 if( !dryRunFlag && !internalUpdate ){
132 autosync(SYNC_PULL + SYNC_VERBOSE*verboseFlag);
133 }
134
@@ -188,11 +185,11 @@
185 "%s "
186 " AND event.objid IN leaves"
187 " ORDER BY event.mtime DESC",
188 timeline_query_for_tty()
189 );
190 print_timeline(&q, -100, 79, 0);
191 db_finalize(&q);
192 fossil_fatal("Multiple descendants");
193 }
194 }
195 tid = db_int(0, "SELECT rid FROM leaves, event"
@@ -200,11 +197,11 @@
197 " ORDER BY event.mtime DESC");
198 if( tid==0 ) tid = vid;
199 }
200
201 if( tid==0 ){
202 return;
203 }
204
205 db_begin_transaction();
206 vfile_check_signature(vid, CKSIG_ENOTFILE);
207 if( !dryRunFlag && !internalUpdate ) undo_begin();
@@ -635,11 +632,11 @@
632 }
633 if( !is_a_version(rid) ){
634 if( errCode>0 ) return errCode;
635 fossil_fatal("no such checkin: %s", revision);
636 }
637 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
638
639 if( pManifest ){
640 pFile = manifest_file_find(pManifest, file);
641 if( pFile ){
642 int rc;
643
+2 -20
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100100
}else if( zUrl[0]=='s' ){
101101
g.urlIsSsh = 1;
102102
g.urlProtocol = "ssh";
103103
g.urlDfltPort = 22;
104104
g.urlFossil = "fossil";
105
- g.urlShell = 0;
106105
iStart = 6;
107106
}else{
108107
g.urlIsHttps = 0;
109108
g.urlProtocol = "http";
110109
g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
173172
g.urlFossil = zValue;
174173
dehttpize(g.urlFossil);
175174
zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176175
cQuerySep = '&';
177176
}
178
- if( fossil_strcmp(zName,"shell")==0 ){
179
- g.urlShell = zValue;
180
- dehttpize(g.urlShell);
181
- zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182
- cQuerySep = '&';
183
- }
184177
}
185178
186179
dehttpize(g.urlPath);
187180
if( g.urlDfltPort==g.urlPort ){
188181
g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
444437
if( g.urlIsSsh || g.urlIsFile ) return;
445438
if( isatty(fileno(stdin))
446439
&& (g.urlFlags & URL_PROMPT_PW)!=0
447440
&& (g.urlFlags & URL_PROMPTED)==0
448441
){
449
- char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
450
- Blob x;
451
- fossil_force_newline();
452
- prompt_for_password(zPrompt, &x, 0);
453
- free(zPrompt);
454
- g.urlPasswd = mprintf("%b", &x);
455
- blob_reset(&x);
456442
g.urlFlags |= URL_PROMPTED;
443
+ g.urlPasswd = prompt_for_user_password(g.urlUser);
457444
if( g.urlPasswd[0]
458445
&& (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
459446
){
460
- char c;
461
- prompt_user("remember password (Y/n)? ", &x);
462
- c = blob_str(&x)[0];
463
- blob_reset(&x);
464
- if( c!='n' && c!='N' ){
447
+ if( save_password_prompt() ){
465448
g.urlFlags |= URL_REMEMBER_PW;
466449
if( g.urlFlags & URL_REMEMBER ){
467450
db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468451
}
469452
}
@@ -490,10 +473,9 @@
490473
*/
491474
void url_get_password_if_needed(void){
492475
if( (g.urlUser && g.urlUser[0])
493476
&& (g.urlPasswd==0 || g.urlPasswd[0]==0)
494477
&& isatty(fileno(stdin))
495
- && g.urlIsSsh==0
496478
){
497479
url_prompt_for_password();
498480
}
499481
}
500482
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
104 g.urlFossil = "fossil";
105 g.urlShell = 0;
106 iStart = 6;
107 }else{
108 g.urlIsHttps = 0;
109 g.urlProtocol = "http";
110 g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
173 g.urlFossil = zValue;
174 dehttpize(g.urlFossil);
175 zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176 cQuerySep = '&';
177 }
178 if( fossil_strcmp(zName,"shell")==0 ){
179 g.urlShell = zValue;
180 dehttpize(g.urlShell);
181 zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182 cQuerySep = '&';
183 }
184 }
185
186 dehttpize(g.urlPath);
187 if( g.urlDfltPort==g.urlPort ){
188 g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
444 if( g.urlIsSsh || g.urlIsFile ) return;
445 if( isatty(fileno(stdin))
446 && (g.urlFlags & URL_PROMPT_PW)!=0
447 && (g.urlFlags & URL_PROMPTED)==0
448 ){
449 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
450 Blob x;
451 fossil_force_newline();
452 prompt_for_password(zPrompt, &x, 0);
453 free(zPrompt);
454 g.urlPasswd = mprintf("%b", &x);
455 blob_reset(&x);
456 g.urlFlags |= URL_PROMPTED;
 
457 if( g.urlPasswd[0]
458 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
459 ){
460 char c;
461 prompt_user("remember password (Y/n)? ", &x);
462 c = blob_str(&x)[0];
463 blob_reset(&x);
464 if( c!='n' && c!='N' ){
465 g.urlFlags |= URL_REMEMBER_PW;
466 if( g.urlFlags & URL_REMEMBER ){
467 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
468 }
469 }
@@ -490,10 +473,9 @@
490 */
491 void url_get_password_if_needed(void){
492 if( (g.urlUser && g.urlUser[0])
493 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
494 && isatty(fileno(stdin))
495 && g.urlIsSsh==0
496 ){
497 url_prompt_for_password();
498 }
499 }
500
--- src/url.c
+++ src/url.c
@@ -100,11 +100,10 @@
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
104 g.urlFossil = "fossil";
 
105 iStart = 6;
106 }else{
107 g.urlIsHttps = 0;
108 g.urlProtocol = "http";
109 g.urlDfltPort = 80;
@@ -173,16 +172,10 @@
172 g.urlFossil = zValue;
173 dehttpize(g.urlFossil);
174 zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
175 cQuerySep = '&';
176 }
 
 
 
 
 
 
177 }
178
179 dehttpize(g.urlPath);
180 if( g.urlDfltPort==g.urlPort ){
181 g.urlCanonical = mprintf(
@@ -444,26 +437,16 @@
437 if( g.urlIsSsh || g.urlIsFile ) return;
438 if( isatty(fileno(stdin))
439 && (g.urlFlags & URL_PROMPT_PW)!=0
440 && (g.urlFlags & URL_PROMPTED)==0
441 ){
 
 
 
 
 
 
 
442 g.urlFlags |= URL_PROMPTED;
443 g.urlPasswd = prompt_for_user_password(g.urlUser);
444 if( g.urlPasswd[0]
445 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
446 ){
447 if( save_password_prompt() ){
 
 
 
 
448 g.urlFlags |= URL_REMEMBER_PW;
449 if( g.urlFlags & URL_REMEMBER ){
450 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
451 }
452 }
@@ -490,10 +473,9 @@
473 */
474 void url_get_password_if_needed(void){
475 if( (g.urlUser && g.urlUser[0])
476 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
477 && isatty(fileno(stdin))
 
478 ){
479 url_prompt_for_password();
480 }
481 }
482
+28 -1
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
3434
if( z[i]=='\r' || z[i]=='\n' ){
3535
while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
3636
z[i] = 0;
3737
break;
3838
}
39
- if( z[i]<' ' ) z[i] = ' ';
39
+ if( z[i]>0 && z[i]<' ' ) z[i] = ' ';
4040
}
4141
blob_append(pBlob, z, -1);
4242
}
4343
4444
#if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128128
break;
129129
}
130130
}
131131
blob_reset(&secondTry);
132132
}
133
+
134
+/*
135
+** Prompt to save Fossil user password
136
+*/
137
+int save_password_prompt(){
138
+ Blob x;
139
+ char c;
140
+ prompt_user("remember password (Y/n)? ", &x);
141
+ c = blob_str(&x)[0];
142
+ blob_reset(&x);
143
+ return ( c!='n' && c!='N' );
144
+}
145
+
146
+/*
147
+** Prompt for Fossil user password
148
+*/
149
+char *prompt_for_user_password(const char *zUser){
150
+ char *zPrompt = mprintf("\rpassword for %s: ", zUser);
151
+ char *zPw;
152
+ Blob x;
153
+ fossil_force_newline();
154
+ prompt_for_password(zPrompt, &x, 0);
155
+ free(zPrompt);
156
+ zPw = mprintf("%b", &x);
157
+ blob_reset(&x);
158
+ return zPw;
159
+}
133160
134161
/*
135162
** Prompt the user to enter a single line of text.
136163
*/
137164
void prompt_user(const char *zPrompt, Blob *pIn){
138165
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
34 if( z[i]=='\r' || z[i]=='\n' ){
35 while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
36 z[i] = 0;
37 break;
38 }
39 if( z[i]<' ' ) z[i] = ' ';
40 }
41 blob_append(pBlob, z, -1);
42 }
43
44 #if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128 break;
129 }
130 }
131 blob_reset(&secondTry);
132 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
134 /*
135 ** Prompt the user to enter a single line of text.
136 */
137 void prompt_user(const char *zPrompt, Blob *pIn){
138
--- src/user.c
+++ src/user.c
@@ -34,11 +34,11 @@
34 if( z[i]=='\r' || z[i]=='\n' ){
35 while( i>0 && fossil_isspace(z[i-1]) ){ i--; }
36 z[i] = 0;
37 break;
38 }
39 if( z[i]>0 && z[i]<' ' ) z[i] = ' ';
40 }
41 blob_append(pBlob, z, -1);
42 }
43
44 #if defined(_WIN32) || defined(__BIONIC__)
@@ -128,10 +128,37 @@
128 break;
129 }
130 }
131 blob_reset(&secondTry);
132 }
133
134 /*
135 ** Prompt to save Fossil user password
136 */
137 int save_password_prompt(){
138 Blob x;
139 char c;
140 prompt_user("remember password (Y/n)? ", &x);
141 c = blob_str(&x)[0];
142 blob_reset(&x);
143 return ( c!='n' && c!='N' );
144 }
145
146 /*
147 ** Prompt for Fossil user password
148 */
149 char *prompt_for_user_password(const char *zUser){
150 char *zPrompt = mprintf("\rpassword for %s: ", zUser);
151 char *zPw;
152 Blob x;
153 fossil_force_newline();
154 prompt_for_password(zPrompt, &x, 0);
155 free(zPrompt);
156 zPw = mprintf("%b", &x);
157 blob_reset(&x);
158 return zPw;
159 }
160
161 /*
162 ** Prompt the user to enter a single line of text.
163 */
164 void prompt_user(const char *zPrompt, Blob *pIn){
165
+1 -8
--- src/utf8.c
+++ src/utf8.c
@@ -23,18 +23,11 @@
2323
#include "utf8.h"
2424
#include <sqlite3.h>
2525
#ifdef _WIN32
2626
# include <windows.h>
2727
#endif
28
-#ifdef __CYGWIN__
29
-# include <sys/cygwin.h>
30
-# define CP_UTF8 65001
31
- __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int,
32
- const char *, int, const char *, int, const char *, const char *);
33
- __declspec(dllimport) extern __stdcall int MultiByteToWideChar(int, int,
34
- const char *, int, wchar_t*, int);
35
-#endif
28
+#include "cygsup.h"
3629
3730
#ifdef _WIN32
3831
/*
3932
** Translate MBCS to UTF-8. Return a pointer to the translated text.
4033
** Call fossil_mbcs_free() to deallocate any memory used to store the
4134
--- src/utf8.c
+++ src/utf8.c
@@ -23,18 +23,11 @@
23 #include "utf8.h"
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28 #ifdef __CYGWIN__
29 # include <sys/cygwin.h>
30 # define CP_UTF8 65001
31 __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int,
32 const char *, int, const char *, int, const char *, const char *);
33 __declspec(dllimport) extern __stdcall int MultiByteToWideChar(int, int,
34 const char *, int, wchar_t*, int);
35 #endif
36
37 #ifdef _WIN32
38 /*
39 ** Translate MBCS to UTF-8. Return a pointer to the translated text.
40 ** Call fossil_mbcs_free() to deallocate any memory used to store the
41
--- src/utf8.c
+++ src/utf8.c
@@ -23,18 +23,11 @@
23 #include "utf8.h"
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28 #include "cygsup.h"
 
 
 
 
 
 
 
29
30 #ifdef _WIN32
31 /*
32 ** Translate MBCS to UTF-8. Return a pointer to the translated text.
33 ** Call fossil_mbcs_free() to deallocate any memory used to store the
34
+6 -3
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
8181
if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
8282
return;
8383
}
8484
8585
db_begin_transaction();
86
- p = manifest_get(vid, CFTYPE_MANIFEST);
86
+ p = manifest_get(vid, CFTYPE_MANIFEST, 0);
8787
if( p==0 ) {
8888
db_end_transaction(1);
8989
return;
9090
}
9191
db_prepare(&ins,
@@ -846,22 +846,25 @@
846846
** pManOut, should be identical.
847847
*/
848848
void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849849
int fid;
850850
Blob file;
851
+ Blob err;
851852
Manifest *pManifest;
852853
ManifestFile *pFile;
853854
char zBuf[100];
854855
855856
blob_zero(pOut);
857
+ blob_zero(&err);
856858
if( pManOut ){
857859
blob_zero(pManOut);
858860
}
859861
db_must_be_within_tree();
860
- pManifest = manifest_get(vid, CFTYPE_MANIFEST);
862
+ pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err);
861863
if( pManifest==0 ){
862
- fossil_fatal("manifest file (%d) is malformed", vid);
864
+ fossil_fatal("manifest file (%d) is malformed:\n%s\n",
865
+ vid, blob_str(&err));
863866
}
864867
manifest_file_rewind(pManifest);
865868
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
866869
if( pFile->zUuid==0 ) continue;
867870
fid = uuid_to_rid(pFile->zUuid, 0);
868871
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
81 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
82 return;
83 }
84
85 db_begin_transaction();
86 p = manifest_get(vid, CFTYPE_MANIFEST);
87 if( p==0 ) {
88 db_end_transaction(1);
89 return;
90 }
91 db_prepare(&ins,
@@ -846,22 +846,25 @@
846 ** pManOut, should be identical.
847 */
848 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849 int fid;
850 Blob file;
 
851 Manifest *pManifest;
852 ManifestFile *pFile;
853 char zBuf[100];
854
855 blob_zero(pOut);
 
856 if( pManOut ){
857 blob_zero(pManOut);
858 }
859 db_must_be_within_tree();
860 pManifest = manifest_get(vid, CFTYPE_MANIFEST);
861 if( pManifest==0 ){
862 fossil_fatal("manifest file (%d) is malformed", vid);
 
863 }
864 manifest_file_rewind(pManifest);
865 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
866 if( pFile->zUuid==0 ) continue;
867 fid = uuid_to_rid(pFile->zUuid, 0);
868
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
81 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
82 return;
83 }
84
85 db_begin_transaction();
86 p = manifest_get(vid, CFTYPE_MANIFEST, 0);
87 if( p==0 ) {
88 db_end_transaction(1);
89 return;
90 }
91 db_prepare(&ins,
@@ -846,22 +846,25 @@
846 ** pManOut, should be identical.
847 */
848 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849 int fid;
850 Blob file;
851 Blob err;
852 Manifest *pManifest;
853 ManifestFile *pFile;
854 char zBuf[100];
855
856 blob_zero(pOut);
857 blob_zero(&err);
858 if( pManOut ){
859 blob_zero(pManOut);
860 }
861 db_must_be_within_tree();
862 pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err);
863 if( pManifest==0 ){
864 fossil_fatal("manifest file (%d) is malformed:\n%s\n",
865 vid, blob_str(&err));
866 }
867 manifest_file_rewind(pManifest);
868 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
869 if( pFile->zUuid==0 ) continue;
870 fid = uuid_to_rid(pFile->zUuid, 0);
871
+6 -3
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
8181
if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
8282
return;
8383
}
8484
8585
db_begin_transaction();
86
- p = manifest_get(vid, CFTYPE_MANIFEST);
86
+ p = manifest_get(vid, CFTYPE_MANIFEST, 0);
8787
if( p==0 ) {
8888
db_end_transaction(1);
8989
return;
9090
}
9191
db_prepare(&ins,
@@ -846,22 +846,25 @@
846846
** pManOut, should be identical.
847847
*/
848848
void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849849
int fid;
850850
Blob file;
851
+ Blob err;
851852
Manifest *pManifest;
852853
ManifestFile *pFile;
853854
char zBuf[100];
854855
855856
blob_zero(pOut);
857
+ blob_zero(&err);
856858
if( pManOut ){
857859
blob_zero(pManOut);
858860
}
859861
db_must_be_within_tree();
860
- pManifest = manifest_get(vid, CFTYPE_MANIFEST);
862
+ pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err);
861863
if( pManifest==0 ){
862
- fossil_fatal("manifest file (%d) is malformed", vid);
864
+ fossil_fatal("manifest file (%d) is malformed:\n%s\n",
865
+ vid, blob_str(&err));
863866
}
864867
manifest_file_rewind(pManifest);
865868
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
866869
if( pFile->zUuid==0 ) continue;
867870
fid = uuid_to_rid(pFile->zUuid, 0);
868871
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
81 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
82 return;
83 }
84
85 db_begin_transaction();
86 p = manifest_get(vid, CFTYPE_MANIFEST);
87 if( p==0 ) {
88 db_end_transaction(1);
89 return;
90 }
91 db_prepare(&ins,
@@ -846,22 +846,25 @@
846 ** pManOut, should be identical.
847 */
848 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849 int fid;
850 Blob file;
 
851 Manifest *pManifest;
852 ManifestFile *pFile;
853 char zBuf[100];
854
855 blob_zero(pOut);
 
856 if( pManOut ){
857 blob_zero(pManOut);
858 }
859 db_must_be_within_tree();
860 pManifest = manifest_get(vid, CFTYPE_MANIFEST);
861 if( pManifest==0 ){
862 fossil_fatal("manifest file (%d) is malformed", vid);
 
863 }
864 manifest_file_rewind(pManifest);
865 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
866 if( pFile->zUuid==0 ) continue;
867 fid = uuid_to_rid(pFile->zUuid, 0);
868
--- src/vfile.c
+++ src/vfile.c
@@ -81,11 +81,11 @@
81 if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
82 return;
83 }
84
85 db_begin_transaction();
86 p = manifest_get(vid, CFTYPE_MANIFEST, 0);
87 if( p==0 ) {
88 db_end_transaction(1);
89 return;
90 }
91 db_prepare(&ins,
@@ -846,22 +846,25 @@
846 ** pManOut, should be identical.
847 */
848 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
849 int fid;
850 Blob file;
851 Blob err;
852 Manifest *pManifest;
853 ManifestFile *pFile;
854 char zBuf[100];
855
856 blob_zero(pOut);
857 blob_zero(&err);
858 if( pManOut ){
859 blob_zero(pManOut);
860 }
861 db_must_be_within_tree();
862 pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err);
863 if( pManifest==0 ){
864 fossil_fatal("manifest file (%d) is malformed:\n%s\n",
865 vid, blob_str(&err));
866 }
867 manifest_file_rewind(pManifest);
868 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
869 if( pFile->zUuid==0 ) continue;
870 fid = uuid_to_rid(pFile->zUuid, 0);
871
+7 -7
--- src/wiki.c
+++ src/wiki.c
@@ -16,13 +16,13 @@
1616
**
1717
*******************************************************************************
1818
**
1919
** This file contains code to do formatting of wiki text.
2020
*/
21
+#include "config.h"
2122
#include <assert.h>
2223
#include <ctype.h>
23
-#include "config.h"
2424
#include "wiki.h"
2525
2626
/*
2727
** Return true if the input string is a well-formed wiki page name.
2828
**
@@ -228,11 +228,11 @@
228228
"SELECT rid FROM tagxref"
229229
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230230
" ORDER BY mtime DESC", zTag
231231
);
232232
free(zTag);
233
- pWiki = manifest_get(rid, CFTYPE_WIKI);
233
+ pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
234234
if( pWiki ){
235235
zBody = pWiki->zWiki;
236236
zMimetype = pWiki->zMimetype;
237237
}
238238
}
@@ -391,11 +391,11 @@
391391
free(zTag);
392392
if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
393393
login_needed();
394394
return;
395395
}
396
- if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
396
+ if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
397397
zBody = pWiki->zWiki;
398398
zMimetype = pWiki->zMimetype;
399399
}
400400
}
401401
if( P("submit")!=0 && zBody!=0
@@ -632,11 +632,11 @@
632632
blob_appendf(&body, db_get("sandbox",""));
633633
appendRemark(&body, zMimetype);
634634
db_set("sandbox", blob_str(&body), 0);
635635
}else{
636636
login_verify_csrf_secret();
637
- pWiki = manifest_get(rid, CFTYPE_WIKI);
637
+ pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
638638
if( pWiki ){
639639
blob_append(&body, pWiki->zWiki, -1);
640640
manifest_destroy(pWiki);
641641
}
642642
blob_zero(&wiki);
@@ -782,15 +782,15 @@
782782
" WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)"
783783
" ORDER BY event.mtime DESC LIMIT 1",
784784
zPageName, rid1
785785
);
786786
}
787
- pW1 = manifest_get(rid1, CFTYPE_WIKI);
787
+ pW1 = manifest_get(rid1, CFTYPE_WIKI, 0);
788788
if( pW1==0 ) fossil_redirect_home();
789789
blob_init(&w1, pW1->zWiki, -1);
790790
blob_zero(&w2);
791
- if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
791
+ if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI, 0))!=0 ){
792792
blob_init(&w2, pW2->zWiki, -1);
793793
}
794794
blob_zero(&d);
795795
diffFlags = construct_diff_flags(1,0);
796796
text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
@@ -1064,11 +1064,11 @@
10641064
rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
10651065
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
10661066
" ORDER BY x.mtime DESC LIMIT 1",
10671067
zPageName
10681068
);
1069
- if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
1069
+ if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
10701070
zBody = pWiki->zWiki;
10711071
}
10721072
if( zBody==0 ){
10731073
fossil_fatal("wiki page [%s] not found",zPageName);
10741074
}
10751075
--- src/wiki.c
+++ src/wiki.c
@@ -16,13 +16,13 @@
16 **
17 *******************************************************************************
18 **
19 ** This file contains code to do formatting of wiki text.
20 */
 
21 #include <assert.h>
22 #include <ctype.h>
23 #include "config.h"
24 #include "wiki.h"
25
26 /*
27 ** Return true if the input string is a well-formed wiki page name.
28 **
@@ -228,11 +228,11 @@
228 "SELECT rid FROM tagxref"
229 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230 " ORDER BY mtime DESC", zTag
231 );
232 free(zTag);
233 pWiki = manifest_get(rid, CFTYPE_WIKI);
234 if( pWiki ){
235 zBody = pWiki->zWiki;
236 zMimetype = pWiki->zMimetype;
237 }
238 }
@@ -391,11 +391,11 @@
391 free(zTag);
392 if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
393 login_needed();
394 return;
395 }
396 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
397 zBody = pWiki->zWiki;
398 zMimetype = pWiki->zMimetype;
399 }
400 }
401 if( P("submit")!=0 && zBody!=0
@@ -632,11 +632,11 @@
632 blob_appendf(&body, db_get("sandbox",""));
633 appendRemark(&body, zMimetype);
634 db_set("sandbox", blob_str(&body), 0);
635 }else{
636 login_verify_csrf_secret();
637 pWiki = manifest_get(rid, CFTYPE_WIKI);
638 if( pWiki ){
639 blob_append(&body, pWiki->zWiki, -1);
640 manifest_destroy(pWiki);
641 }
642 blob_zero(&wiki);
@@ -782,15 +782,15 @@
782 " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)"
783 " ORDER BY event.mtime DESC LIMIT 1",
784 zPageName, rid1
785 );
786 }
787 pW1 = manifest_get(rid1, CFTYPE_WIKI);
788 if( pW1==0 ) fossil_redirect_home();
789 blob_init(&w1, pW1->zWiki, -1);
790 blob_zero(&w2);
791 if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
792 blob_init(&w2, pW2->zWiki, -1);
793 }
794 blob_zero(&d);
795 diffFlags = construct_diff_flags(1,0);
796 text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
@@ -1064,11 +1064,11 @@
1064 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1065 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1066 " ORDER BY x.mtime DESC LIMIT 1",
1067 zPageName
1068 );
1069 if( (pWiki = manifest_get(rid, CFTYPE_WIKI))!=0 ){
1070 zBody = pWiki->zWiki;
1071 }
1072 if( zBody==0 ){
1073 fossil_fatal("wiki page [%s] not found",zPageName);
1074 }
1075
--- src/wiki.c
+++ src/wiki.c
@@ -16,13 +16,13 @@
16 **
17 *******************************************************************************
18 **
19 ** This file contains code to do formatting of wiki text.
20 */
21 #include "config.h"
22 #include <assert.h>
23 #include <ctype.h>
 
24 #include "wiki.h"
25
26 /*
27 ** Return true if the input string is a well-formed wiki page name.
28 **
@@ -228,11 +228,11 @@
228 "SELECT rid FROM tagxref"
229 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230 " ORDER BY mtime DESC", zTag
231 );
232 free(zTag);
233 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
234 if( pWiki ){
235 zBody = pWiki->zWiki;
236 zMimetype = pWiki->zMimetype;
237 }
238 }
@@ -391,11 +391,11 @@
391 free(zTag);
392 if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){
393 login_needed();
394 return;
395 }
396 if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
397 zBody = pWiki->zWiki;
398 zMimetype = pWiki->zMimetype;
399 }
400 }
401 if( P("submit")!=0 && zBody!=0
@@ -632,11 +632,11 @@
632 blob_appendf(&body, db_get("sandbox",""));
633 appendRemark(&body, zMimetype);
634 db_set("sandbox", blob_str(&body), 0);
635 }else{
636 login_verify_csrf_secret();
637 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
638 if( pWiki ){
639 blob_append(&body, pWiki->zWiki, -1);
640 manifest_destroy(pWiki);
641 }
642 blob_zero(&wiki);
@@ -782,15 +782,15 @@
782 " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)"
783 " ORDER BY event.mtime DESC LIMIT 1",
784 zPageName, rid1
785 );
786 }
787 pW1 = manifest_get(rid1, CFTYPE_WIKI, 0);
788 if( pW1==0 ) fossil_redirect_home();
789 blob_init(&w1, pW1->zWiki, -1);
790 blob_zero(&w2);
791 if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI, 0))!=0 ){
792 blob_init(&w2, pW2->zWiki, -1);
793 }
794 blob_zero(&d);
795 diffFlags = construct_diff_flags(1,0);
796 text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
@@ -1064,11 +1064,11 @@
1064 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1065 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1066 " ORDER BY x.mtime DESC LIMIT 1",
1067 zPageName
1068 );
1069 if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1070 zBody = pWiki->zWiki;
1071 }
1072 if( zBody==0 ){
1073 fossil_fatal("wiki page [%s] not found",zPageName);
1074 }
1075
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -15,12 +15,12 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code to do formatting of wiki text.
1919
*/
20
-#include <assert.h>
2120
#include "config.h"
21
+#include <assert.h>
2222
#include "wikiformat.h"
2323
2424
#if INTERFACE
2525
/*
2626
** Allowed wiki transformation operations
2727
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to do formatting of wiki text.
19 */
20 #include <assert.h>
21 #include "config.h"
 
22 #include "wikiformat.h"
23
24 #if INTERFACE
25 /*
26 ** Allowed wiki transformation operations
27
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -15,12 +15,12 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to do formatting of wiki text.
19 */
 
20 #include "config.h"
21 #include <assert.h>
22 #include "wikiformat.h"
23
24 #if INTERFACE
25 /*
26 ** Allowed wiki transformation operations
27
+1 -1
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -16,13 +16,13 @@
1616
*******************************************************************************
1717
**
1818
** This file contains code that generates WYSIWYG text editors on
1919
** web pages.
2020
*/
21
+#include "config.h"
2122
#include <assert.h>
2223
#include <ctype.h>
23
-#include "config.h"
2424
#include "wysiwyg.h"
2525
2626
2727
/*
2828
** Output code for a WYSIWYG editor. The caller must have already generated
2929
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -16,13 +16,13 @@
16 *******************************************************************************
17 **
18 ** This file contains code that generates WYSIWYG text editors on
19 ** web pages.
20 */
 
21 #include <assert.h>
22 #include <ctype.h>
23 #include "config.h"
24 #include "wysiwyg.h"
25
26
27 /*
28 ** Output code for a WYSIWYG editor. The caller must have already generated
29
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -16,13 +16,13 @@
16 *******************************************************************************
17 **
18 ** This file contains code that generates WYSIWYG text editors on
19 ** web pages.
20 */
21 #include "config.h"
22 #include <assert.h>
23 #include <ctype.h>
 
24 #include "wysiwyg.h"
25
26
27 /*
28 ** Output code for a WYSIWYG editor. The caller must have already generated
29
+18 -11
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
12281228
{
12291229
cgi_reset_content();
12301230
@ error bad\scommand:\s%F(blob_str(&xfer.line))
12311231
}
12321232
blobarray_reset(xfer.aToken, xfer.nToken);
1233
+ blob_reset(&xfer.line);
12331234
}
12341235
if( isPush ){
12351236
if( run_push_script()==TH_ERROR ){
12361237
cgi_reset_content();
12371238
@ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
12551256
if( xfer.syncPrivate ) send_private(&xfer);
12561257
}
12571258
if( recvConfig ){
12581259
configure_finalize_receive();
12591260
}
1261
+ db_multi_exec("DROP TABLE onremote");
12601262
manifest_crosslink_end();
12611263
12621264
/* Send the server timestamp last, in case prior processing happened
12631265
** to use up a significant fraction of our time window.
12641266
*/
@@ -1425,11 +1427,10 @@
14251427
nCardSent++;
14261428
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
14271429
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
14281430
}
14291431
manifest_crosslink_begin();
1430
- transport_global_startup();
14311432
if( syncFlags & SYNC_VERBOSE ){
14321433
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
14331434
}
14341435
14351436
while( go ){
@@ -1504,11 +1505,22 @@
15041505
*/
15051506
zRandomness = db_text(0, "SELECT hex(randomblob(20))");
15061507
blob_appendf(&send, "# %s\n", zRandomness);
15071508
free(zRandomness);
15081509
1510
+ if( syncFlags & SYNC_VERBOSE ){
1511
+ fossil_print("waiting for server...");
1512
+ }
1513
+ fflush(stdout);
15091514
/* Exchange messages with the server */
1515
+ if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1516
+ MAX_REDIRECTS) ){
1517
+ nErr++;
1518
+ break;
1519
+ }
1520
+
1521
+ /* Output current stats */
15101522
if( syncFlags & SYNC_VERBOSE ){
15111523
fossil_print(zValueFormat, "Sent:",
15121524
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
15131525
xfer.nFileSent, xfer.nDeltaSent);
15141526
}else{
@@ -1520,19 +1532,11 @@
15201532
nCardRcvd = 0;
15211533
xfer.nFileSent = 0;
15221534
xfer.nDeltaSent = 0;
15231535
xfer.nGimmeSent = 0;
15241536
xfer.nIGotSent = 0;
1525
- if( syncFlags & SYNC_VERBOSE ){
1526
- fossil_print("waiting for server...");
1527
- }
1528
- fflush(stdout);
1529
- if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1530
- MAX_REDIRECTS) ){
1531
- nErr++;
1532
- break;
1533
- }
1537
+
15341538
lastPctDone = -1;
15351539
blob_reset(&send);
15361540
rArrivalTime = db_double(0.0, "SELECT julianday('now')");
15371541
15381542
/* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
17751779
fossil_print("Error: %s\n", zMsg);
17761780
if( fossil_strcmp(zMsg, "login failed")==0 ){
17771781
if( nCycle<2 ){
17781782
g.urlPasswd = 0;
17791783
go = 1;
1780
- if( g.cgiOutput==0 ) url_prompt_for_password();
1784
+ if( g.cgiOutput==0 ){
1785
+ g.urlFlags |= URL_PROMPT_PW;
1786
+ url_prompt_for_password();
1787
+ }
17811788
}
17821789
}else{
17831790
blob_appendf(&xfer.err, "server says: %s\n", zMsg);
17841791
nErr++;
17851792
}
17861793
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
1228 {
1229 cgi_reset_content();
1230 @ error bad\scommand:\s%F(blob_str(&xfer.line))
1231 }
1232 blobarray_reset(xfer.aToken, xfer.nToken);
 
1233 }
1234 if( isPush ){
1235 if( run_push_script()==TH_ERROR ){
1236 cgi_reset_content();
1237 @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
1255 if( xfer.syncPrivate ) send_private(&xfer);
1256 }
1257 if( recvConfig ){
1258 configure_finalize_receive();
1259 }
 
1260 manifest_crosslink_end();
1261
1262 /* Send the server timestamp last, in case prior processing happened
1263 ** to use up a significant fraction of our time window.
1264 */
@@ -1425,11 +1427,10 @@
1425 nCardSent++;
1426 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1427 if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
1428 }
1429 manifest_crosslink_begin();
1430 transport_global_startup();
1431 if( syncFlags & SYNC_VERBOSE ){
1432 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1433 }
1434
1435 while( go ){
@@ -1504,11 +1505,22 @@
1504 */
1505 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
1506 blob_appendf(&send, "# %s\n", zRandomness);
1507 free(zRandomness);
1508
 
 
 
 
1509 /* Exchange messages with the server */
 
 
 
 
 
 
 
1510 if( syncFlags & SYNC_VERBOSE ){
1511 fossil_print(zValueFormat, "Sent:",
1512 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
1513 xfer.nFileSent, xfer.nDeltaSent);
1514 }else{
@@ -1520,19 +1532,11 @@
1520 nCardRcvd = 0;
1521 xfer.nFileSent = 0;
1522 xfer.nDeltaSent = 0;
1523 xfer.nGimmeSent = 0;
1524 xfer.nIGotSent = 0;
1525 if( syncFlags & SYNC_VERBOSE ){
1526 fossil_print("waiting for server...");
1527 }
1528 fflush(stdout);
1529 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1530 MAX_REDIRECTS) ){
1531 nErr++;
1532 break;
1533 }
1534 lastPctDone = -1;
1535 blob_reset(&send);
1536 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
1537
1538 /* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
1775 fossil_print("Error: %s\n", zMsg);
1776 if( fossil_strcmp(zMsg, "login failed")==0 ){
1777 if( nCycle<2 ){
1778 g.urlPasswd = 0;
1779 go = 1;
1780 if( g.cgiOutput==0 ) url_prompt_for_password();
 
 
 
1781 }
1782 }else{
1783 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1784 nErr++;
1785 }
1786
--- src/xfer.c
+++ src/xfer.c
@@ -1228,10 +1228,11 @@
1228 {
1229 cgi_reset_content();
1230 @ error bad\scommand:\s%F(blob_str(&xfer.line))
1231 }
1232 blobarray_reset(xfer.aToken, xfer.nToken);
1233 blob_reset(&xfer.line);
1234 }
1235 if( isPush ){
1236 if( run_push_script()==TH_ERROR ){
1237 cgi_reset_content();
1238 @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
@@ -1255,10 +1256,11 @@
1256 if( xfer.syncPrivate ) send_private(&xfer);
1257 }
1258 if( recvConfig ){
1259 configure_finalize_receive();
1260 }
1261 db_multi_exec("DROP TABLE onremote");
1262 manifest_crosslink_end();
1263
1264 /* Send the server timestamp last, in case prior processing happened
1265 ** to use up a significant fraction of our time window.
1266 */
@@ -1425,11 +1427,10 @@
1427 nCardSent++;
1428 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1429 if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
1430 }
1431 manifest_crosslink_begin();
 
1432 if( syncFlags & SYNC_VERBOSE ){
1433 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1434 }
1435
1436 while( go ){
@@ -1504,11 +1505,22 @@
1505 */
1506 zRandomness = db_text(0, "SELECT hex(randomblob(20))");
1507 blob_appendf(&send, "# %s\n", zRandomness);
1508 free(zRandomness);
1509
1510 if( syncFlags & SYNC_VERBOSE ){
1511 fossil_print("waiting for server...");
1512 }
1513 fflush(stdout);
1514 /* Exchange messages with the server */
1515 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1516 MAX_REDIRECTS) ){
1517 nErr++;
1518 break;
1519 }
1520
1521 /* Output current stats */
1522 if( syncFlags & SYNC_VERBOSE ){
1523 fossil_print(zValueFormat, "Sent:",
1524 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
1525 xfer.nFileSent, xfer.nDeltaSent);
1526 }else{
@@ -1520,19 +1532,11 @@
1532 nCardRcvd = 0;
1533 xfer.nFileSent = 0;
1534 xfer.nDeltaSent = 0;
1535 xfer.nGimmeSent = 0;
1536 xfer.nIGotSent = 0;
1537
 
 
 
 
 
 
 
 
1538 lastPctDone = -1;
1539 blob_reset(&send);
1540 rArrivalTime = db_double(0.0, "SELECT julianday('now')");
1541
1542 /* Send the send-private pragma if we are trying to sync private data */
@@ -1775,11 +1779,14 @@
1779 fossil_print("Error: %s\n", zMsg);
1780 if( fossil_strcmp(zMsg, "login failed")==0 ){
1781 if( nCycle<2 ){
1782 g.urlPasswd = 0;
1783 go = 1;
1784 if( g.cgiOutput==0 ){
1785 g.urlFlags |= URL_PROMPT_PW;
1786 url_prompt_for_password();
1787 }
1788 }
1789 }else{
1790 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1791 nErr++;
1792 }
1793
+2 -2
--- src/zip.c
+++ src/zip.c
@@ -15,13 +15,13 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code used to generate ZIP archives.
1919
*/
20
+#include "config.h"
2021
#include <assert.h>
2122
#include <zlib.h>
22
-#include "config.h"
2323
#include "zip.h"
2424
2525
/*
2626
** Write a 16- or 32-bit integer as little-endian into the given buffer.
2727
*/
@@ -337,11 +337,11 @@
337337
if( zDir && zDir[0] ){
338338
blob_appendf(&filename, "%s/", zDir);
339339
}
340340
nPrefix = blob_size(&filename);
341341
342
- pManifest = manifest_get(rid, CFTYPE_MANIFEST);
342
+ pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
343343
if( pManifest ){
344344
char *zName;
345345
zip_set_timedate(pManifest->rDate);
346346
if( db_get_boolean("manifest", 0) ){
347347
blob_append(&filename, "manifest", -1);
348348
--- src/zip.c
+++ src/zip.c
@@ -15,13 +15,13 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to generate ZIP archives.
19 */
 
20 #include <assert.h>
21 #include <zlib.h>
22 #include "config.h"
23 #include "zip.h"
24
25 /*
26 ** Write a 16- or 32-bit integer as little-endian into the given buffer.
27 */
@@ -337,11 +337,11 @@
337 if( zDir && zDir[0] ){
338 blob_appendf(&filename, "%s/", zDir);
339 }
340 nPrefix = blob_size(&filename);
341
342 pManifest = manifest_get(rid, CFTYPE_MANIFEST);
343 if( pManifest ){
344 char *zName;
345 zip_set_timedate(pManifest->rDate);
346 if( db_get_boolean("manifest", 0) ){
347 blob_append(&filename, "manifest", -1);
348
--- src/zip.c
+++ src/zip.c
@@ -15,13 +15,13 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code used to generate ZIP archives.
19 */
20 #include "config.h"
21 #include <assert.h>
22 #include <zlib.h>
 
23 #include "zip.h"
24
25 /*
26 ** Write a 16- or 32-bit integer as little-endian into the given buffer.
27 */
@@ -337,11 +337,11 @@
337 if( zDir && zDir[0] ){
338 blob_appendf(&filename, "%s/", zDir);
339 }
340 nPrefix = blob_size(&filename);
341
342 pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
343 if( pManifest ){
344 char *zName;
345 zip_set_timedate(pManifest->rDate);
346 if( db_get_boolean("manifest", 0) ){
347 blob_append(&filename, "manifest", -1);
348
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -163,12 +163,12 @@
163163
endif
164164
endif
165165
166166
# With MinGW command line handling workaround
167167
ifdef MINGW_IS_32BIT_ONLY
168
-TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
169
-RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
168
+TCC += -DBROKEN_MINGW_CMDLINE=1
169
+RCC += -DBROKEN_MINGW_CMDLINE=1
170170
endif
171171
172172
# With HTTPS support
173173
ifdef FOSSIL_ENABLE_SSL
174174
TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
16851685
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
16861686
16871687
$(OBJDIR)/zip.h: $(OBJDIR)/headers
16881688
16891689
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690
- $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1690
+ $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -D_HAVE_SQLITE_CONFIG_H -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
16911691
16921692
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
16931693
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
16941694
16951695
$(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
16961696
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -163,12 +163,12 @@
163 endif
164 endif
165
166 # With MinGW command line handling workaround
167 ifdef MINGW_IS_32BIT_ONLY
168 TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
169 RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
170 endif
171
172 # With HTTPS support
173 ifdef FOSSIL_ENABLE_SSL
174 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
1685 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1686
1687 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1688
1689 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1691
1692 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1693 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1694
1695 $(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
1696
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -163,12 +163,12 @@
163 endif
164 endif
165
166 # With MinGW command line handling workaround
167 ifdef MINGW_IS_32BIT_ONLY
168 TCC += -DBROKEN_MINGW_CMDLINE=1
169 RCC += -DBROKEN_MINGW_CMDLINE=1
170 endif
171
172 # With HTTPS support
173 ifdef FOSSIL_ENABLE_SSL
174 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
1685 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1686
1687 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1688
1689 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -D_HAVE_SQLITE_CONFIG_H -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1691
1692 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1693 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1694
1695 $(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
1696
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -163,12 +163,12 @@
163163
endif
164164
endif
165165
166166
# With MinGW command line handling workaround
167167
ifdef MINGW_IS_32BIT_ONLY
168
-TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
169
-RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
168
+TCC += -DBROKEN_MINGW_CMDLINE=1
169
+RCC += -DBROKEN_MINGW_CMDLINE=1
170170
endif
171171
172172
# With HTTPS support
173173
ifdef FOSSIL_ENABLE_SSL
174174
TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
16851685
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
16861686
16871687
$(OBJDIR)/zip.h: $(OBJDIR)/headers
16881688
16891689
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690
- $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1690
+ $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -D_HAVE_SQLITE_CONFIG_H -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
16911691
16921692
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
16931693
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
16941694
16951695
$(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
16961696
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -163,12 +163,12 @@
163 endif
164 endif
165
166 # With MinGW command line handling workaround
167 ifdef MINGW_IS_32BIT_ONLY
168 TCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
169 RCC += -DBROKEN_MINGW_CMDLINE=1 -D_USE_32BIT_TIME_T
170 endif
171
172 # With HTTPS support
173 ifdef FOSSIL_ENABLE_SSL
174 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
1685 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1686
1687 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1688
1689 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1691
1692 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1693 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1694
1695 $(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
1696
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -163,12 +163,12 @@
163 endif
164 endif
165
166 # With MinGW command line handling workaround
167 ifdef MINGW_IS_32BIT_ONLY
168 TCC += -DBROKEN_MINGW_CMDLINE=1
169 RCC += -DBROKEN_MINGW_CMDLINE=1
170 endif
171
172 # With HTTPS support
173 ifdef FOSSIL_ENABLE_SSL
174 TCC += -DFOSSIL_ENABLE_SSL=1
@@ -1685,11 +1685,11 @@
1685 $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
1686
1687 $(OBJDIR)/zip.h: $(OBJDIR)/headers
1688
1689 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c
1690 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_WIN32_NO_ANSI -D_HAVE_SQLITE_CONFIG_H -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1691
1692 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1693 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1694
1695 $(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
1696
+38 -28
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -11,10 +11,13 @@
1111
SRCDIR = $B\src
1212
OBJDIR = .
1313
OX = .
1414
O = .obj
1515
E = .exe
16
+
17
+# Uncomment to enable debug symbols
18
+# DEBUG = 1
1619
1720
# Uncomment to enable JSON API
1821
# FOSSIL_ENABLE_JSON = 1
1922
2023
# Uncomment to enable SSL support
@@ -25,37 +28,44 @@
2528
SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
2629
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
2730
!endif
2831
2932
# zlib options
30
-ZINCDIR = $(B)\compat\zlib
31
-ZLIBDIR = $(B)\compat\zlib
32
-ZLIB = zlib.lib
33
-
34
-INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
35
-
36
-!ifdef FOSSIL_ENABLE_SSL
37
-INCL = $(INCL) -I$(SSLINCDIR)
38
-!endif
39
-
40
-CFLAGS = -nologo -MT -O2
41
-BCC = $(CC) $(CFLAGS)
42
-TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
43
-RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
44
-LIBS = $(ZLIB) ws2_32.lib advapi32.lib
45
-LIBDIR = -LIBPATH:$(ZLIBDIR)
46
-
47
-!ifdef FOSSIL_ENABLE_JSON
48
-TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
49
-RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
50
-!endif
51
-
52
-!ifdef FOSSIL_ENABLE_SSL
53
-TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
54
-RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
55
-LIBS = $(LIBS) $(SSLLIB)
56
-LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
33
+ZINCDIR = $(B)\compat\zlib
34
+ZLIBDIR = $(B)\compat\zlib
35
+ZLIB = zlib.lib
36
+
37
+INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
38
+
39
+!ifdef FOSSIL_ENABLE_SSL
40
+INCL = $(INCL) -I$(SSLINCDIR)
41
+!endif
42
+
43
+CFLAGS = -nologo -MT -O2
44
+LDFLAGS = /NODEFAULTLIB:msvcrt
45
+
46
+!ifdef DEBUG
47
+CFLAGS = $(CFLAGS) -Zi
48
+LDFLAGS = $(LDFLAGS) /DEBUG
49
+!endif
50
+
51
+BCC = $(CC) $(CFLAGS)
52
+TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
53
+RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
54
+LIBS = $(ZLIB) ws2_32.lib advapi32.lib
55
+LIBDIR = -LIBPATH:$(ZLIBDIR)
56
+
57
+!ifdef FOSSIL_ENABLE_JSON
58
+TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
59
+RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
60
+!endif
61
+
62
+!ifdef FOSSIL_ENABLE_SSL
63
+TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
64
+RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
65
+LIBS = $(LIBS) $(SSLLIB)
66
+LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
5767
!endif
5868
5969
SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
6070
/DSQLITE_THREADSAFE=0 \
6171
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
@@ -294,11 +304,11 @@
294304
@echo Building zlib from "$(ZLIBDIR)"...
295305
@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
296306
297307
$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
298308
cd $(OX)
299
- link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
309
+ link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
300310
301311
$(OX)\linkopts: $B\win\Makefile.msc
302312
echo $(OX)\add.obj > $@
303313
echo $(OX)\allrepo.obj >> $@
304314
echo $(OX)\attach.obj >> $@
305315
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -11,10 +11,13 @@
11 SRCDIR = $B\src
12 OBJDIR = .
13 OX = .
14 O = .obj
15 E = .exe
 
 
 
16
17 # Uncomment to enable JSON API
18 # FOSSIL_ENABLE_JSON = 1
19
20 # Uncomment to enable SSL support
@@ -25,37 +28,44 @@
25 SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
26 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
27 !endif
28
29 # zlib options
30 ZINCDIR = $(B)\compat\zlib
31 ZLIBDIR = $(B)\compat\zlib
32 ZLIB = zlib.lib
33
34 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
35
36 !ifdef FOSSIL_ENABLE_SSL
37 INCL = $(INCL) -I$(SSLINCDIR)
38 !endif
39
40 CFLAGS = -nologo -MT -O2
41 BCC = $(CC) $(CFLAGS)
42 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
43 RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
44 LIBS = $(ZLIB) ws2_32.lib advapi32.lib
45 LIBDIR = -LIBPATH:$(ZLIBDIR)
46
47 !ifdef FOSSIL_ENABLE_JSON
48 TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
49 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
50 !endif
51
52 !ifdef FOSSIL_ENABLE_SSL
53 TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
54 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
55 LIBS = $(LIBS) $(SSLLIB)
56 LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
 
 
 
 
 
 
 
57 !endif
58
59 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
60 /DSQLITE_THREADSAFE=0 \
61 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
@@ -294,11 +304,11 @@
294 @echo Building zlib from "$(ZLIBDIR)"...
295 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
296
297 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
298 cd $(OX)
299 link /NODEFAULTLIB:msvcrt -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
300
301 $(OX)\linkopts: $B\win\Makefile.msc
302 echo $(OX)\add.obj > $@
303 echo $(OX)\allrepo.obj >> $@
304 echo $(OX)\attach.obj >> $@
305
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -11,10 +11,13 @@
11 SRCDIR = $B\src
12 OBJDIR = .
13 OX = .
14 O = .obj
15 E = .exe
16
17 # Uncomment to enable debug symbols
18 # DEBUG = 1
19
20 # Uncomment to enable JSON API
21 # FOSSIL_ENABLE_JSON = 1
22
23 # Uncomment to enable SSL support
@@ -25,37 +28,44 @@
28 SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32
29 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
30 !endif
31
32 # zlib options
33 ZINCDIR = $(B)\compat\zlib
34 ZLIBDIR = $(B)\compat\zlib
35 ZLIB = zlib.lib
36
37 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR)
38
39 !ifdef FOSSIL_ENABLE_SSL
40 INCL = $(INCL) -I$(SSLINCDIR)
41 !endif
42
43 CFLAGS = -nologo -MT -O2
44 LDFLAGS = /NODEFAULTLIB:msvcrt
45
46 !ifdef DEBUG
47 CFLAGS = $(CFLAGS) -Zi
48 LDFLAGS = $(LDFLAGS) /DEBUG
49 !endif
50
51 BCC = $(CC) $(CFLAGS)
52 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL)
53 RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL)
54 LIBS = $(ZLIB) ws2_32.lib advapi32.lib
55 LIBDIR = -LIBPATH:$(ZLIBDIR)
56
57 !ifdef FOSSIL_ENABLE_JSON
58 TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1
59 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1
60 !endif
61
62 !ifdef FOSSIL_ENABLE_SSL
63 TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1
64 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1
65 LIBS = $(LIBS) $(SSLLIB)
66 LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR)
67 !endif
68
69 SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \
70 /DSQLITE_THREADSAFE=0 \
71 /DSQLITE_DEFAULT_FILE_FORMAT=4 \
@@ -294,11 +304,11 @@
304 @echo Building zlib from "$(ZLIBDIR)"...
305 @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd
306
307 $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
308 cd $(OX)
309 link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
310
311 $(OX)\linkopts: $B\win\Makefile.msc
312 echo $(OX)\add.obj > $@
313 echo $(OX)\allrepo.obj >> $@
314 echo $(OX)\attach.obj >> $@
315
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
1010
Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
1111
that are required for any new code that will be accepted into the Fossil core.
1212
But, of course, if you are writing an extension just for yourself, you can
1313
use any programming style you want.
1414
15
-The source code for Fossil is not feed directly into the C compiler, however.
15
+The source code for Fossil is not sent directly into the C compiler.
1616
There are three separate code [./makefile.wiki#preprocessing|preprocessors]
1717
that run over the code first.
1818
1919
1. The <b>mkindex</b> preprocessor scans all regular source files looking
2020
for special comments that contain "help" text and which identify routines
2121
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
10 Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
11 that are required for any new code that will be accepted into the Fossil core.
12 But, of course, if you are writing an extension just for yourself, you can
13 use any programming style you want.
14
15 The source code for Fossil is not feed directly into the C compiler, however.
16 There are three separate code [./makefile.wiki#preprocessing|preprocessors]
17 that run over the code first.
18
19 1. The <b>mkindex</b> preprocessor scans all regular source files looking
20 for special comments that contain "help" text and which identify routines
21
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -10,11 +10,11 @@
10 Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
11 that are required for any new code that will be accepted into the Fossil core.
12 But, of course, if you are writing an extension just for yourself, you can
13 use any programming style you want.
14
15 The source code for Fossil is not sent directly into the C compiler.
16 There are three separate code [./makefile.wiki#preprocessing|preprocessors]
17 that run over the code first.
18
19 1. The <b>mkindex</b> preprocessor scans all regular source files looking
20 for special comments that contain "help" text and which identify routines
21
+2 -1
--- www/build.wiki
+++ www/build.wiki
@@ -136,7 +136,8 @@
136136
generated by configure to add the following lines:
137137
<blockquote><pre>
138138
TCC += -DSQLITE_WITHOUT_ZONEMALLOC
139139
TCC += -DWITHOUT_ICONV
140140
TCC += -Dsocketlen_t=int
141
- </pre></blockquote>
141
+ TCC += -DSQLITE_MAX_MMAP_SIZE=0
142
+</pre></blockquote>
142143
</ul>
143144
--- www/build.wiki
+++ www/build.wiki
@@ -136,7 +136,8 @@
136 generated by configure to add the following lines:
137 <blockquote><pre>
138 TCC += -DSQLITE_WITHOUT_ZONEMALLOC
139 TCC += -DWITHOUT_ICONV
140 TCC += -Dsocketlen_t=int
141 </pre></blockquote>
 
142 </ul>
143
--- www/build.wiki
+++ www/build.wiki
@@ -136,7 +136,8 @@
136 generated by configure to add the following lines:
137 <blockquote><pre>
138 TCC += -DSQLITE_WITHOUT_ZONEMALLOC
139 TCC += -DWITHOUT_ICONV
140 TCC += -Dsocketlen_t=int
141 TCC += -DSQLITE_MAX_MMAP_SIZE=0
142 </pre></blockquote>
143 </ul>
144
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,34 @@
11
<title>Change Log</title>
2
+
3
+<h2>Changes For Version 1.28 (as yet unreleased)</h2>
4
+ * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
5
+ * When cloning a repository, the user name passed via the URL (if any)
6
+ is now used as the default local admin user's name.
7
+ * Enhance the SSH transport mechanism so that it runs a single instance of
8
+ the "fossil" executable on the remote side, obviating the need for a shell
9
+ on the remote side. Some users may need to add the "?fossil=/path/to/fossil"
10
+ query parameter to "ssh:" URIs if their fossil binary is not in a standard
11
+ place.
12
+ * Add the "[/help?cmd=blame | fossil blame]" command that works just like
13
+ "fossil annotate" but uses a different output format that includes the
14
+ user who made each changes and omits line numbers.
15
+ * Add the "Tarball and ZIP-archive Prefix" configuration parameter under
16
+ Admin/Configuration.
17
+ * Fix CGI processing so that it works on web servers that do not
18
+ supply REQUEST_URI.
19
+ * Add options --dirsonly, --emptydirs, and --allckouts to the
20
+ "[/help?cmd=clean | fossil clean]" command.
21
+ * Ten-fold performance improvement in large "fossil blame" or
22
+ "fossil annotate" commands.
23
+ * Add option -W|--width to the "[/help?cmd=timeline | fossil timeline]"
24
+ and "[/help?cmd=finfo | fossil finfo]" commands.
25
+ * Option -n|--limit of "[/help?cmd=timeline | fossil timeline]" now
26
+ specifies the number of entries, just like all other commands which
27
+ have the -n|--limit option. The various timeline-related functions
28
+ now output "=== ?? limit (??) reached ===" at the end whenever
29
+ appropriate. Use "-n 0" if no limit is desired.
230
331
<h2>Changes For Version 1.27 (2013-09-11)</h2>
432
* Enhance the [/help?cmd=changes | fossil changes],
533
[/help?cmd=clean | fossil clean], [/help?cmd=extras | fossil extras],
634
[/help?cmd=ls | fossil ls] and [/help?cmd=status | fossil status] commands
735
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,34 @@
1 <title>Change Log</title>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
3 <h2>Changes For Version 1.27 (2013-09-11)</h2>
4 * Enhance the [/help?cmd=changes | fossil changes],
5 [/help?cmd=clean | fossil clean], [/help?cmd=extras | fossil extras],
6 [/help?cmd=ls | fossil ls] and [/help?cmd=status | fossil status] commands
7
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,34 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.28 (as yet unreleased)</h2>
4 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
5 * When cloning a repository, the user name passed via the URL (if any)
6 is now used as the default local admin user's name.
7 * Enhance the SSH transport mechanism so that it runs a single instance of
8 the "fossil" executable on the remote side, obviating the need for a shell
9 on the remote side. Some users may need to add the "?fossil=/path/to/fossil"
10 query parameter to "ssh:" URIs if their fossil binary is not in a standard
11 place.
12 * Add the "[/help?cmd=blame | fossil blame]" command that works just like
13 "fossil annotate" but uses a different output format that includes the
14 user who made each changes and omits line numbers.
15 * Add the "Tarball and ZIP-archive Prefix" configuration parameter under
16 Admin/Configuration.
17 * Fix CGI processing so that it works on web servers that do not
18 supply REQUEST_URI.
19 * Add options --dirsonly, --emptydirs, and --allckouts to the
20 "[/help?cmd=clean | fossil clean]" command.
21 * Ten-fold performance improvement in large "fossil blame" or
22 "fossil annotate" commands.
23 * Add option -W|--width to the "[/help?cmd=timeline | fossil timeline]"
24 and "[/help?cmd=finfo | fossil finfo]" commands.
25 * Option -n|--limit of "[/help?cmd=timeline | fossil timeline]" now
26 specifies the number of entries, just like all other commands which
27 have the -n|--limit option. The various timeline-related functions
28 now output "=== ?? limit (??) reached ===" at the end whenever
29 appropriate. Use "-n 0" if no limit is desired.
30
31 <h2>Changes For Version 1.27 (2013-09-11)</h2>
32 * Enhance the [/help?cmd=changes | fossil changes],
33 [/help?cmd=clean | fossil clean], [/help?cmd=extras | fossil extras],
34 [/help?cmd=ls | fossil ls] and [/help?cmd=status | fossil status] commands
35
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -79,11 +79,11 @@
7979
8080
<h3>2.1 Identification Of Artifacts</h3>
8181
8282
A particular version of a particular file is called an "artifact".
8383
Each artifact has a universally unique name which is the
84
-<a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content
84
+<a href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> hash of the content
8585
of that file expressed as 40 characters of lower-case hexadecimal. Such
8686
a hash is referred to as the Artifact Identifier or Artifact ID
8787
for the artifact. The SHA1 algorithm is created with the purpose of
8888
providing a highly forgery-resistant identifier for a file. Given any
8989
file it is simple to find the artifact ID for that file. But given a
9090
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -79,11 +79,11 @@
79
80 <h3>2.1 Identification Of Artifacts</h3>
81
82 A particular version of a particular file is called an "artifact".
83 Each artifact has a universally unique name which is the
84 <a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content
85 of that file expressed as 40 characters of lower-case hexadecimal. Such
86 a hash is referred to as the Artifact Identifier or Artifact ID
87 for the artifact. The SHA1 algorithm is created with the purpose of
88 providing a highly forgery-resistant identifier for a file. Given any
89 file it is simple to find the artifact ID for that file. But given a
90
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -79,11 +79,11 @@
79
80 <h3>2.1 Identification Of Artifacts</h3>
81
82 A particular version of a particular file is called an "artifact".
83 Each artifact has a universally unique name which is the
84 <a href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> hash of the content
85 of that file expressed as 40 characters of lower-case hexadecimal. Such
86 a hash is referred to as the Artifact Identifier or Artifact ID
87 for the artifact. The SHA1 algorithm is created with the purpose of
88 providing a highly forgery-resistant identifier for a file. Given any
89 file it is simple to find the artifact ID for that file. But given a
90
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -55,11 +55,11 @@
5555
<b>fossil clone</b> <i>URL repository-filename</i>
5656
</blockquote>
5757
5858
<p>The <i>URL</i> above is the http URL for the fossil repository
5959
you want to clone, and it may include a "user:password" part, e.g.
60
- <tt>http://drh:[email protected]/fossil</tt>. You can
60
+ <tt>http://user:[email protected]/fossil</tt>. You can
6161
call the new repository anything you want - there are no naming
6262
restrictions. As an example, you can clone the fossil repository
6363
this way:</p>
6464
6565
<blockquote>
@@ -220,11 +220,11 @@
220220
date/time stamp. ([./checkin_names.wiki | more info])
221221
If you omit
222222
the <i>VERSION</i>, then fossil moves you to the
223223
latest version of the branch your are currently on.</p>
224224
225
- <p>The default behaviors is for [./concepts.wiki#workflow|autosync] to
225
+ <p>The default behavior is for [./concepts.wiki#workflow|autosync] to
226226
be turned on. That means that a [/help/pull|pull] automatically occurs
227227
when you run [/help/update|update] and a [/help/push|push] happens
228228
automatically after you [/help/commit|commit]. So in normal practice,
229229
the push, pull, and sync commands are rarely used. But it is important
230230
to know about them, all the same.</p>
231231
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -55,11 +55,11 @@
55 <b>fossil clone</b> <i>URL repository-filename</i>
56 </blockquote>
57
58 <p>The <i>URL</i> above is the http URL for the fossil repository
59 you want to clone, and it may include a "user:password" part, e.g.
60 <tt>http://drh:[email protected]/fossil</tt>. You can
61 call the new repository anything you want - there are no naming
62 restrictions. As an example, you can clone the fossil repository
63 this way:</p>
64
65 <blockquote>
@@ -220,11 +220,11 @@
220 date/time stamp. ([./checkin_names.wiki | more info])
221 If you omit
222 the <i>VERSION</i>, then fossil moves you to the
223 latest version of the branch your are currently on.</p>
224
225 <p>The default behaviors is for [./concepts.wiki#workflow|autosync] to
226 be turned on. That means that a [/help/pull|pull] automatically occurs
227 when you run [/help/update|update] and a [/help/push|push] happens
228 automatically after you [/help/commit|commit]. So in normal practice,
229 the push, pull, and sync commands are rarely used. But it is important
230 to know about them, all the same.</p>
231
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -55,11 +55,11 @@
55 <b>fossil clone</b> <i>URL repository-filename</i>
56 </blockquote>
57
58 <p>The <i>URL</i> above is the http URL for the fossil repository
59 you want to clone, and it may include a "user:password" part, e.g.
60 <tt>http://user:[email protected]/fossil</tt>. You can
61 call the new repository anything you want - there are no naming
62 restrictions. As an example, you can clone the fossil repository
63 this way:</p>
64
65 <blockquote>
@@ -220,11 +220,11 @@
220 date/time stamp. ([./checkin_names.wiki | more info])
221 If you omit
222 the <i>VERSION</i>, then fossil moves you to the
223 latest version of the branch your are currently on.</p>
224
225 <p>The default behavior is for [./concepts.wiki#workflow|autosync] to
226 be turned on. That means that a [/help/pull|pull] automatically occurs
227 when you run [/help/update|update] and a [/help/push|push] happens
228 automatically after you [/help/commit|commit]. So in normal practice,
229 the push, pull, and sync commands are rarely used. But it is important
230 to know about them, all the same.</p>
231
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
3838
Server (3) runs as a CGI script on a shared hosting account at
3939
<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
4040
This server demonstrates the ability of
4141
Fossil to run on an economical shared-host web account with no
4242
privileges beyond port 80 HTTP access and CGI. It is not necessary
43
-to have a dedicated computer with administrator to run Fossil.
43
+to have a dedicated computer with administrator privileges to run Fossil.
4444
As far as we are aware,
4545
Fossil is the only full-featured configuration management system
4646
that can run in
4747
such a restricted environment. The CGI script that runs on the
4848
Hurricane Electric server is the same as the CGI script shown above,
4949
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -38,11 +38,11 @@
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator privileges to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49
+15 -3
--- www/server.wiki
+++ www/server.wiki
@@ -102,11 +102,23 @@
102102
[http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that
103103
accepts and decodes SSL-encrypted connections. Fossil can be run directly from
104104
stunnel in a mannar similar to inetd and xinetd. This can be used to provide
105105
a secure link to a Fossil project. The configuration needed to get stunnel4
106106
to invoke Fossil is very similar to the inetd and xinetd examples shown above.
107
-See the stunnel4 documentation for details.
107
+The relevant parts of an stunnel configuration might look something
108
+like the following:
109
+<blockquote><pre><nowiki>
110
+[https]
111
+accept = www.ubercool-project.org:443
112
+TIMEOUTclose = 0
113
+exec = /usr/bin/fossil
114
+execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
115
+</nowiki></pre></blockquote>
116
+See the stunnel4 documentation for further details bout the /etc/stunnel/stunnel.conf
117
+configuration file. Note that the [/help/http|fossil http] command should include
118
+the --https option to let Fossil know to use "https" instead of "http" as the scheme
119
+on generated hyperlinks.
108120
<p>
109121
Using inetd or xinetd or stunnel is a more complex setup
110122
than the "standalone" server, but it has the
111123
advantage of only using system resources when an actual connection is
112124
attempted. If no-one ever connects to that port, a Fossil server will
@@ -158,11 +170,11 @@
158170
<b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
159171
accessible under "cgi-bin", which would be a typical deployment on Apache
160172
for instance).
161173
</p>
162174
<p>
163
-To server multiple repositories from a directory using CGI, use the "directory:"
175
+To serve multiple repositories from a directory using CGI, use the "directory:"
164176
tag in the CGI script rather than "repository:". You might also want to add
165177
a "notfound:" tag to tell where to redirect if the particular repository requested
166178
by the URL is not found:
167179
<blockquote><pre>
168180
#!/usr/bin/fossil
@@ -170,11 +182,11 @@
170182
notfound: http://url-to-go-to-if-repo-not-found/
171183
</pre></blockquote>
172184
</p>
173185
<p>
174186
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
175
-will serve up the repository "/home/fossil/repos/XYX.fossil" (if it exists).
187
+will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
176188
</p>
177189
</blockquote>
178190
179191
<a name="scgi"></a>
180192
<h2>Fossil as SCGI</h2><blockquote>
181193
--- www/server.wiki
+++ www/server.wiki
@@ -102,11 +102,23 @@
102 [http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that
103 accepts and decodes SSL-encrypted connections. Fossil can be run directly from
104 stunnel in a mannar similar to inetd and xinetd. This can be used to provide
105 a secure link to a Fossil project. The configuration needed to get stunnel4
106 to invoke Fossil is very similar to the inetd and xinetd examples shown above.
107 See the stunnel4 documentation for details.
 
 
 
 
 
 
 
 
 
 
 
 
108 <p>
109 Using inetd or xinetd or stunnel is a more complex setup
110 than the "standalone" server, but it has the
111 advantage of only using system resources when an actual connection is
112 attempted. If no-one ever connects to that port, a Fossil server will
@@ -158,11 +170,11 @@
158 <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
159 accessible under "cgi-bin", which would be a typical deployment on Apache
160 for instance).
161 </p>
162 <p>
163 To server multiple repositories from a directory using CGI, use the "directory:"
164 tag in the CGI script rather than "repository:". You might also want to add
165 a "notfound:" tag to tell where to redirect if the particular repository requested
166 by the URL is not found:
167 <blockquote><pre>
168 #!/usr/bin/fossil
@@ -170,11 +182,11 @@
170 notfound: http://url-to-go-to-if-repo-not-found/
171 </pre></blockquote>
172 </p>
173 <p>
174 Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
175 will serve up the repository "/home/fossil/repos/XYX.fossil" (if it exists).
176 </p>
177 </blockquote>
178
179 <a name="scgi"></a>
180 <h2>Fossil as SCGI</h2><blockquote>
181
--- www/server.wiki
+++ www/server.wiki
@@ -102,11 +102,23 @@
102 [http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that
103 accepts and decodes SSL-encrypted connections. Fossil can be run directly from
104 stunnel in a mannar similar to inetd and xinetd. This can be used to provide
105 a secure link to a Fossil project. The configuration needed to get stunnel4
106 to invoke Fossil is very similar to the inetd and xinetd examples shown above.
107 The relevant parts of an stunnel configuration might look something
108 like the following:
109 <blockquote><pre><nowiki>
110 [https]
111 accept = www.ubercool-project.org:443
112 TIMEOUTclose = 0
113 exec = /usr/bin/fossil
114 execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
115 </nowiki></pre></blockquote>
116 See the stunnel4 documentation for further details bout the /etc/stunnel/stunnel.conf
117 configuration file. Note that the [/help/http|fossil http] command should include
118 the --https option to let Fossil know to use "https" instead of "http" as the scheme
119 on generated hyperlinks.
120 <p>
121 Using inetd or xinetd or stunnel is a more complex setup
122 than the "standalone" server, but it has the
123 advantage of only using system resources when an actual connection is
124 attempted. If no-one ever connects to that port, a Fossil server will
@@ -158,11 +170,11 @@
170 <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
171 accessible under "cgi-bin", which would be a typical deployment on Apache
172 for instance).
173 </p>
174 <p>
175 To serve multiple repositories from a directory using CGI, use the "directory:"
176 tag in the CGI script rather than "repository:". You might also want to add
177 a "notfound:" tag to tell where to redirect if the particular repository requested
178 by the URL is not found:
179 <blockquote><pre>
180 #!/usr/bin/fossil
@@ -170,11 +182,11 @@
182 notfound: http://url-to-go-to-if-repo-not-found/
183 </pre></blockquote>
184 </p>
185 <p>
186 Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
187 will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
188 </p>
189 </blockquote>
190
191 <a name="scgi"></a>
192 <h2>Fossil as SCGI</h2><blockquote>
193

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button