Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | merge trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | cleanX |
Files: | files | file ages | folders |
SHA1: |
a354949a62a958d253bdcc09ba81d533 |
User & Date: | jan.nijtmans 2013-10-30 10:50:54.579 |
Context
2014-02-21
| ||
14:46 | merge trunk ... (check-in: f93b4b4d user: jan.nijtmans tags: cleanX) | |
2013-10-30
| ||
10:53 | merge cleanX branch changes (which all come from trunk) ... (check-in: 6934dd3c user: jan.nijtmans tags: cleanX-no-clean-glob) | |
10:50 | merge trunk ... (check-in: a354949a user: jan.nijtmans tags: cleanX) | |
09:11 | Make "fossil add", "fossil addremove", "fossil update" and "fossil co --latest" work when the repository doesn't contain any commit yet. This is not a fatal situation at all. ... (check-in: b725c1cf user: jan.nijtmans tags: trunk) | |
2013-10-01
| ||
23:01 | Merge updates from trunk. ... (check-in: 8d2f9ab1 user: mistachkin tags: cleanX) | |
Changes
Changes to VERSION.
|
| | | 1 | 1.28 |
Changes to autosetup/jimsh0.c.
︙ | ︙ | |||
183 184 185 186 187 188 189 | # define strtoull strtoul # endif #endif #define UCHAR(c) ((unsigned char)(c)) | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | # define strtoull strtoul # endif #endif #define UCHAR(c) ((unsigned char)(c)) #define JIM_VERSION 74 #define JIM_OK 0 #define JIM_ERR 1 #define JIM_RETURN 2 #define JIM_BREAK 3 #define JIM_CONTINUE 4 #define JIM_SIGNAL 5 |
︙ | ︙ | |||
319 320 321 322 323 324 325 | #define Jim_GetHashEntryVal(he) ((he)->val) #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) #define Jim_GetHashTableSize(ht) ((ht)->size) #define Jim_GetHashTableUsed(ht) ((ht)->used) typedef struct Jim_Obj { | < < > > | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | #define Jim_GetHashEntryVal(he) ((he)->val) #define Jim_GetHashTableCollisions(ht) ((ht)->collisions) #define Jim_GetHashTableSize(ht) ((ht)->size) #define Jim_GetHashTableUsed(ht) ((ht)->used) typedef struct Jim_Obj { char *bytes; const struct Jim_ObjType *typePtr; int refCount; int length; union { jim_wide wideValue; int intValue; |
︙ | ︙ | |||
663 664 665 666 667 668 669 | JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry (Jim_HashTableIterator *iter); JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); | < < | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry (Jim_HashTableIterator *iter); JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, Jim_Obj *objPtr); JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, int *lenPtr); JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr); JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); |
︙ | ︙ | |||
875 876 877 878 879 880 881 882 883 884 885 886 887 888 | JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); JIM_EXPORT void Jim_HistoryAdd(const char *line); JIM_EXPORT void Jim_HistoryShow(void); JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); | > > | 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); JIM_EXPORT void Jim_HistoryAdd(const char *line); JIM_EXPORT void Jim_HistoryShow(void); JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); JIM_EXPORT int Jim_CheckSignal(Jim_Interp *interp); #define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); |
︙ | ︙ | |||
5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 | #ifdef JIM_MAINTAINER #define JIM_DEBUG_COMMAND #define JIM_DEBUG_PANIC #endif const char *jim_tt_name(int type); #ifdef JIM_DEBUG_PANIC static void JimPanicDump(int panic_condition, const char *fmt, ...); #define JimPanic(X) JimPanicDump X #else #define JimPanic(X) #endif static char JimEmptyStringRep[] = ""; static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, int flags); static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, const char *prefix, const char *const *tablePtr, const char *name); static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); static int JimSign(jim_wide w); static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); | > > > > | 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 | #ifdef JIM_MAINTAINER #define JIM_DEBUG_COMMAND #define JIM_DEBUG_PANIC #endif #define JIM_INTEGER_SPACE 24 const char *jim_tt_name(int type); #ifdef JIM_DEBUG_PANIC static void JimPanicDump(int panic_condition, const char *fmt, ...); #define JimPanic(X) JimPanicDump X #else #define JimPanic(X) #endif static char JimEmptyStringRep[] = ""; static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, int flags); static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len); static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, const char *prefix, const char *const *tablePtr, const char *name); static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); static int JimSign(jim_wide w); static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); |
︙ | ︙ | |||
5932 5933 5934 5935 5936 5937 5938 | if (n > 0) { n = utf8_strlen(s2, n); } return n; } #endif | | > | > > | > > > > > > > > > > > > > > > > > > > > > > > > | | 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 | if (n > 0) { n = utf8_strlen(s2, n); } return n; } #endif static int JimWideToString(char *buf, jim_wide wideValue) { int pos = 0; if (wideValue == 0) { buf[pos++] = '0'; } else { char tmp[JIM_INTEGER_SPACE]; int num = 0; int i; if (wideValue < 0) { buf[pos++] = '-'; i = wideValue % 10; tmp[num++] = (i > 0) ? (10 - i) : -i; wideValue /= -10; } while (wideValue) { tmp[num++] = wideValue % 10; wideValue /= 10; } for (i = 0; i < num; i++) { buf[pos++] = '0' + tmp[num - i - 1]; } } buf[pos] = 0; return pos; } static int JimCheckConversion(const char *str, const char *endptr) { if (str[0] == '\0' || str == endptr) { return JIM_ERR; } |
︙ | ︙ | |||
6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 | ht->table = NULL; ht->size = 0; ht->sizemask = 0; ht->used = 0; ht->collisions = 0; } int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) { JimResetHashTable(ht); ht->type = type; ht->privdata = privDataPtr; return JIM_OK; | > > > > > > > > | 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 | ht->table = NULL; ht->size = 0; ht->sizemask = 0; ht->used = 0; ht->collisions = 0; } static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) { iter->ht = ht; iter->index = -1; iter->entry = NULL; iter->nextEntry = NULL; } int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) { JimResetHashTable(ht); ht->type = type; ht->privdata = privDataPtr; return JIM_OK; |
︙ | ︙ | |||
6406 6407 6408 6409 6410 6411 6412 | } return NULL; } Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) { Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); | | < < < < | 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 | } return NULL; } Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) { Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); JimInitHashTableIterator(ht, iter); return iter; } Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) { while (1) { if (iter->entry == NULL) { |
︙ | ︙ | |||
10498 10499 10500 10501 10502 10503 10504 | } int Jim_GetExitCode(Jim_Interp *interp) { return interp->exitCode; } | < < | | | 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 10564 10565 10566 10567 10568 10569 10570 10571 10572 | } int Jim_GetExitCode(Jim_Interp *interp) { return interp->exitCode; } static void UpdateStringOfInt(struct Jim_Obj *objPtr); static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); static const Jim_ObjType intObjType = { "int", NULL, NULL, UpdateStringOfInt, JIM_TYPE_NONE, }; static const Jim_ObjType coercedDoubleObjType = { "coerced-double", NULL, NULL, UpdateStringOfInt, JIM_TYPE_NONE, }; static void UpdateStringOfInt(struct Jim_Obj *objPtr) { int len; char buf[JIM_INTEGER_SPACE + 1]; len = JimWideToString(buf, JimWideValue(objPtr)); objPtr->bytes = Jim_Alloc(len + 1); memcpy(objPtr->bytes, buf, len + 1); objPtr->length = len; } int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) { |
︙ | ︙ | |||
10753 10754 10755 10756 10757 10758 10759 | } dupPtr->typePtr = &listObjType; } #define JIM_ELESTR_SIMPLE 0 #define JIM_ELESTR_BRACE 1 #define JIM_ELESTR_QUOTE 2 | | | 10786 10787 10788 10789 10790 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 | } dupPtr->typePtr = &listObjType; } #define JIM_ELESTR_SIMPLE 0 #define JIM_ELESTR_BRACE 1 #define JIM_ELESTR_QUOTE 2 static unsigned char ListElementQuotingType(const char *s, int len) { int i, level, blevel, trySimple = 1; if (len == 0) return JIM_ELESTR_BRACE; if (s[0] == '"' || s[0] == '{') { |
︙ | ︙ | |||
10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 | *p = '\0'; return p - q; } static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc) { int i, bufLen, realLength; const char *strRep; char *p; | > | > | > > > > | 10934 10935 10936 10937 10938 10939 10940 10941 10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959 10960 | *p = '\0'; return p - q; } static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc) { #define STATIC_QUOTING_LEN 32 int i, bufLen, realLength; const char *strRep; char *p; unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; if (objc > STATIC_QUOTING_LEN) { quotingType = Jim_Alloc(objc); } else { quotingType = staticQuoting; } bufLen = 0; for (i = 0; i < objc; i++) { int len; strRep = Jim_GetString(objv[i], &len); quotingType[i] = ListElementQuotingType(strRep, len); switch (quotingType[i]) { |
︙ | ︙ | |||
10973 10974 10975 10976 10977 10978 10979 | if (i + 1 != objc) { *p++ = ' '; realLength++; } } *p = '\0'; objPtr->length = realLength; | > > | > | 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 | if (i + 1 != objc) { *p++ = ' '; realLength++; } } *p = '\0'; objPtr->length = realLength; if (quotingType != staticQuoting) { Jim_Free(quotingType); } } static void UpdateStringOfList(struct Jim_Obj *objPtr) { JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len); } |
︙ | ︙ | |||
10998 10999 11000 11001 11002 11003 11004 | } if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) { Jim_Obj **listObjPtrPtr; int len; int i; | | | 11040 11041 11042 11043 11044 11045 11046 11047 11048 11049 11050 11051 11052 11053 11054 | } if (Jim_IsDict(objPtr) && !Jim_IsShared(objPtr)) { Jim_Obj **listObjPtrPtr; int len; int i; listObjPtrPtr = JimDictPairs(objPtr, &len); for (i = 0; i < len; i++) { Jim_IncrRefCount(listObjPtrPtr[i]); } Jim_FreeIntRep(interp, objPtr); objPtr->typePtr = &listObjType; |
︙ | ︙ | |||
11223 11224 11225 11226 11227 11228 11229 | { int currentLen = listPtr->internalRep.listValue.len; int requiredLen = currentLen + elemc; int i; Jim_Obj **point; if (requiredLen > listPtr->internalRep.listValue.maxLen) { | > > > > > | | > > > | | 11265 11266 11267 11268 11269 11270 11271 11272 11273 11274 11275 11276 11277 11278 11279 11280 11281 11282 11283 11284 11285 11286 11287 11288 11289 11290 | { int currentLen = listPtr->internalRep.listValue.len; int requiredLen = currentLen + elemc; int i; Jim_Obj **point; if (requiredLen > listPtr->internalRep.listValue.maxLen) { if (requiredLen < 2) { requiredLen = 4; } else { requiredLen *= 2; } listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * requiredLen); listPtr->internalRep.listValue.maxLen = requiredLen; } if (idx < 0) { idx = currentLen; } point = listPtr->internalRep.listValue.ele + idx; memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *)); for (i = 0; i < elemc; ++i) { |
︙ | ︙ | |||
11521 11522 11523 11524 11525 11526 11527 | Jim_FreeHashTable(objPtr->internalRep.ptr); Jim_Free(objPtr->internalRep.ptr); } void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { Jim_HashTable *ht, *dupHt; | | | | < | | | < | 11571 11572 11573 11574 11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 11586 11587 11588 11589 11590 11591 11592 11593 11594 11595 11596 11597 11598 11599 11600 11601 11602 11603 11604 11605 11606 11607 11608 11609 11610 11611 11612 11613 11614 11615 11616 11617 11618 11619 11620 11621 11622 11623 11624 11625 11626 11627 | Jim_FreeHashTable(objPtr->internalRep.ptr); Jim_Free(objPtr->internalRep.ptr); } void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { Jim_HashTable *ht, *dupHt; Jim_HashTableIterator htiter; Jim_HashEntry *he; ht = srcPtr->internalRep.ptr; dupHt = Jim_Alloc(sizeof(*dupHt)); Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); if (ht->size != 0) Jim_ExpandHashTable(dupHt, ht->size); JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { const Jim_Obj *keyObjPtr = he->key; Jim_Obj *valObjPtr = he->u.val; Jim_IncrRefCount((Jim_Obj *)keyObjPtr); Jim_IncrRefCount(valObjPtr); Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); } dupPtr->internalRep.ptr = dupHt; dupPtr->typePtr = &dictObjType; } static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len) { Jim_HashTable *ht; Jim_HashTableIterator htiter; Jim_HashEntry *he; Jim_Obj **objv; int i; ht = dictPtr->internalRep.ptr; objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); JimInitHashTableIterator(ht, &htiter); i = 0; while ((he = Jim_NextHashEntry(&htiter)) != NULL) { objv[i++] = (Jim_Obj *)he->key; objv[i++] = he->u.val; } *len = i; return objv; } static void UpdateStringOfDict(struct Jim_Obj *objPtr) { int len; |
︙ | ︙ | |||
12087 12088 12089 12090 12091 12092 12093 | int skip; }; typedef struct Jim_ExprOperator { const char *name; | > | | < | > | 12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153 | int skip; }; typedef struct Jim_ExprOperator { const char *name; int (*funcop) (Jim_Interp *interp, struct JimExprState * e); unsigned char precedence; unsigned char arity; unsigned char lazy; unsigned char namelen; } Jim_ExprOperator; static void ExprPush(struct JimExprState *e, Jim_Obj *obj) { Jim_IncrRefCount(obj); e->stack[e->stacklen++] = obj; } |
︙ | ︙ | |||
12772 12773 12774 12775 12776 12777 12778 12779 | { LAZY_NONE, LAZY_OP, LAZY_LEFT, LAZY_RIGHT }; static const struct Jim_ExprOperator Jim_ExprOperators[] = { | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 12821 12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876 12877 12878 12879 12880 12881 12882 12883 12884 12885 12886 12887 12888 12889 12890 12891 12892 12893 12894 12895 12896 12897 12898 12899 12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 | { LAZY_NONE, LAZY_OP, LAZY_LEFT, LAZY_RIGHT }; #define OPRINIT(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} static const struct Jim_ExprOperator Jim_ExprOperators[] = { OPRINIT("*", 110, 2, JimExprOpBin, LAZY_NONE), OPRINIT("/", 110, 2, JimExprOpBin, LAZY_NONE), OPRINIT("%", 110, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("-", 100, 2, JimExprOpBin, LAZY_NONE), OPRINIT("+", 100, 2, JimExprOpBin, LAZY_NONE), OPRINIT("<<", 90, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT(">>", 90, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("<<<", 90, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT(">>>", 90, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("<", 80, 2, JimExprOpBin, LAZY_NONE), OPRINIT(">", 80, 2, JimExprOpBin, LAZY_NONE), OPRINIT("<=", 80, 2, JimExprOpBin, LAZY_NONE), OPRINIT(">=", 80, 2, JimExprOpBin, LAZY_NONE), OPRINIT("==", 70, 2, JimExprOpBin, LAZY_NONE), OPRINIT("!=", 70, 2, JimExprOpBin, LAZY_NONE), OPRINIT("&", 50, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("^", 49, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("|", 48, 2, JimExprOpIntBin, LAZY_NONE), OPRINIT("&&", 10, 2, NULL, LAZY_OP), OPRINIT(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), OPRINIT(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), OPRINIT("||", 9, 2, NULL, LAZY_OP), OPRINIT(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), OPRINIT(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), OPRINIT("?", 5, 2, JimExprOpNull, LAZY_OP), OPRINIT(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), OPRINIT(":", 5, 2, JimExprOpNull, LAZY_OP), OPRINIT(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), OPRINIT(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), OPRINIT("**", 250, 2, JimExprOpBin, LAZY_NONE), OPRINIT("eq", 60, 2, JimExprOpStrBin, LAZY_NONE), OPRINIT("ne", 60, 2, JimExprOpStrBin, LAZY_NONE), OPRINIT("in", 55, 2, JimExprOpStrBin, LAZY_NONE), OPRINIT("ni", 55, 2, JimExprOpStrBin, LAZY_NONE), OPRINIT("!", 150, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("~", 150, 1, JimExprOpIntUnary, LAZY_NONE), OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT(NULL, 150, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("int", 200, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("abs", 200, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("double", 200, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("round", 200, 1, JimExprOpNumUnary, LAZY_NONE), OPRINIT("rand", 200, 0, JimExprOpNone, LAZY_NONE), OPRINIT("srand", 200, 1, JimExprOpIntUnary, LAZY_NONE), #ifdef JIM_MATH_FUNCTIONS OPRINIT("sin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("cos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("tan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("asin", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("acos", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("atan", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("floor", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("exp", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("log", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("log10", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary, LAZY_NONE), OPRINIT("pow", 200, 2, JimExprOpBin, LAZY_NONE), #endif }; #undef OPRINIT #define JIM_EXPR_OPERATORS_NUM \ (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) static int JimParseExpression(struct JimParserCtx *pc) { |
︙ | ︙ | |||
13024 13025 13026 13027 13028 13029 13030 | static int JimParseExprOperator(struct JimParserCtx *pc) { int i; int bestIdx = -1, bestLen = 0; for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { | | | < | < | | 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 | static int JimParseExprOperator(struct JimParserCtx *pc) { int i; int bestIdx = -1, bestLen = 0; for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { const char * const opname = Jim_ExprOperators[i].name; const int oplen = Jim_ExprOperators[i].namelen; if (opname == NULL || opname[0] != pc->p[0]) { continue; } if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { bestIdx = i + JIM_TT_EXPR_OP; bestLen = oplen; } } if (bestIdx == -1) { return JIM_ERR; } |
︙ | ︙ | |||
13109 13110 13111 13112 13113 13114 13115 | NULL, JIM_TYPE_REFERENCES, }; typedef struct ExprByteCode { | < > | 13159 13160 13161 13162 13163 13164 13165 13166 13167 13168 13169 13170 13171 13172 13173 13174 | NULL, JIM_TYPE_REFERENCES, }; typedef struct ExprByteCode { ScriptToken *token; int len; int inUse; } ExprByteCode; static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) { int i; |
︙ | ︙ | |||
13853 13854 13855 13856 13857 13858 13859 | } typedef struct ScanFmtPartDescr { | | | | | | 13903 13904 13905 13906 13907 13908 13909 13910 13911 13912 13913 13914 13915 13916 13917 13918 13919 13920 13921 13922 | } typedef struct ScanFmtPartDescr { char *arg; char *prefix; size_t width; int pos; char type; char modifier; } ScanFmtPartDescr; typedef struct ScanFmtStringObj { jim_wide size; char *stringRep; |
︙ | ︙ | |||
14869 14870 14871 14872 14873 14874 14875 | argc += len - 1; } } if (retcode == JIM_OK && argc) { retcode = JimInvokeCommand(interp, argc, argv); | < | > | 14919 14920 14921 14922 14923 14924 14925 14926 14927 14928 14929 14930 14931 14932 14933 14934 | argc += len - 1; } } if (retcode == JIM_OK && argc) { retcode = JimInvokeCommand(interp, argc, argv); if (Jim_CheckSignal(interp)) { retcode = JIM_SIGNAL; } } while (j-- > 0) { Jim_DecrRefCount(interp, argv[j]); |
︙ | ︙ | |||
15444 15445 15446 15447 15448 15449 15450 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); if (he) { callback(interp, listObjPtr, he, type); } } else { | | > | < | 15494 15495 15496 15497 15498 15499 15500 15501 15502 15503 15504 15505 15506 15507 15508 15509 15510 15511 15512 15513 15514 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); if (he) { callback(interp, listObjPtr, he, type); } } else { Jim_HashTableIterator htiter; JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) { callback(interp, listObjPtr, he, type); } } } return listObjPtr; } #define JIM_CMDLIST_COMMANDS 0 #define JIM_CMDLIST_PROCS 1 |
︙ | ︙ | |||
17793 17794 17795 17796 17797 17798 17799 | argv += i; if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { sig++; } interp->signal_level += sig; | | | 17843 17844 17845 17846 17847 17848 17849 17850 17851 17852 17853 17854 17855 17856 17857 | argv += i; if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { sig++; } interp->signal_level += sig; if (Jim_CheckSignal(interp)) { exitCode = JIM_SIGNAL; } else { exitCode = Jim_EvalObj(interp, argv[0]); } interp->signal_level -= sig; |
︙ | ︙ | |||
17949 17950 17951 17952 17953 17954 17955 | return JIM_OK; } static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listObjPtr; | | | | < | 17999 18000 18001 18002 18003 18004 18005 18006 18007 18008 18009 18010 18011 18012 18013 18014 18015 18016 18017 18018 18019 18020 18021 18022 18023 18024 18025 18026 | return JIM_OK; } static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Obj *listObjPtr; Jim_HashTableIterator htiter; Jim_HashEntry *he; listObjPtr = Jim_NewListObj(interp, NULL, 0); JimInitHashTableIterator(&interp->references, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { char buf[JIM_REFERENCE_SPACE + 1]; Jim_Reference *refPtr = he->u.val; const unsigned long *refId = he->key; JimFormatReference(buf, refPtr, *refId); Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); } Jim_SetResult(interp, listObjPtr); return JIM_OK; } #endif static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
︙ | ︙ | |||
18003 18004 18005 18006 18007 18008 18009 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, JimDictMatchCallbackType *callback, int type) { Jim_HashEntry *he; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); | | > | < | 18052 18053 18054 18055 18056 18057 18058 18059 18060 18061 18062 18063 18064 18065 18066 18067 18068 18069 18070 18071 18072 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, JimDictMatchCallbackType *callback, int type) { Jim_HashEntry *he; Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); Jim_HashTableIterator htiter; JimInitHashTableIterator(ht, &htiter); while ((he = Jim_NextHashEntry(&htiter)) != NULL) { if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { callback(interp, listObjPtr, he, type); } } return listObjPtr; } int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) { |
︙ | ︙ |
Changes to src/add.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** This file contains code used to check-out versions of the project ** from the local repository. */ #include "config.h" #include "add.h" #include <assert.h> #include <dirent.h> | | < < < < < | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** This file contains code used to check-out versions of the project ** from the local repository. */ #include "config.h" #include "add.h" #include <assert.h> #include <dirent.h> #include "cygsup.h" /* ** This routine returns the names of files in a working checkout that ** are created by Fossil itself, and hence should not be added, deleted, ** or merge, and should be omitted from "clean" and "extra" lists. ** ** Return the N-th name. The first name has N==0. When all names have |
︙ | ︙ | |||
261 262 263 264 265 266 267 | if( zCleanFlag==0 ){ zCleanFlag = db_get("clean-glob", 0); } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } vid = db_lget_int("checkout",0); | < < < | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | if( zCleanFlag==0 ){ zCleanFlag = db_get("clean-glob", 0); } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } vid = db_lget_int("checkout",0); db_begin_transaction(); db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)", filename_collation()); pClean = glob_create(zCleanFlag); pIgnore = glob_create(zIgnoreFlag); nRoot = strlen(g.zLocalRoot); |
︙ | ︙ | |||
503 504 505 506 507 508 509 | if( zCleanFlag==0 ){ zCleanFlag = db_get("clean-glob", 0); } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } vid = db_lget_int("checkout",0); | < < < | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | if( zCleanFlag==0 ){ zCleanFlag = db_get("clean-glob", 0); } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } vid = db_lget_int("checkout",0); db_begin_transaction(); /* step 1: ** Populate the temp table "sfile" with the names of all unmanaged ** files currently in the check-out, except for files that match the ** --ignore or ignore-glob patterns and dot-files. Then add all of ** the files in the sfile temp table to the set of managed files. |
︙ | ︙ |
Changes to src/allrepo.c.
︙ | ︙ | |||
56 57 58 59 60 61 62 | if( find_option(zArg, zShort, 0)!=0 ){ blob_appendf(pExtra, " --%s", zArg); } } static void collect_argument_value(Blob *pExtra, const char *zArg){ const char *zValue = find_option(zArg, 0, 1); if( zValue ){ | > | > > > | | > > > > > > > > > > > > > > | | | | | | < | > | > | > > > | > | | | > > > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | if( find_option(zArg, zShort, 0)!=0 ){ blob_appendf(pExtra, " --%s", zArg); } } static void collect_argument_value(Blob *pExtra, const char *zArg){ const char *zValue = find_option(zArg, 0, 1); if( zValue ){ if( zValue[0] ){ blob_appendf(pExtra, " --%s %s", zArg, zValue); }else{ blob_appendf(pExtra, " --%s \"\"", zArg); } } } /* ** COMMAND: all ** ** Usage: %fossil all (changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync) ** ** The ~/.fossil file records the location of all repositories for a ** user. This command performs certain operations on all repositories ** that can be useful before or after a period of disconnected operation. ** ** On Win32 systems, the file is named "_fossil" and is located in ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%. ** ** Available operations are: ** ** changes Shows all local checkouts that have uncommitted changes. ** This operation has no additional options. ** ** clean Delete all "extra" files in all local checkouts. Extreme ** caution should be exercised with this command because its ** effects cannot be undone. Use of the --dry-run option to ** carefully review the local checkouts to be operated upon ** and the --whatif option to carefully review the files to ** be deleted beforehand is highly recommended. The command ** line options supported by the clean command itself, if any ** are present, are passed along verbatim. ** ** extra Shows extra files from all local checkouts. The command ** line options supported by the extra command itself, if any ** are present, are passed along verbatim. ** ** ignore Arguments are repositories that should be ignored by ** subsequent clean, extra, list, pull, push, rebuild, and ** sync operations. The -c|--ckout option causes the listed ** local checkouts to be ignored instead. ** ** list | ls Display the location of all repositories. The -c|--ckout ** option causes all local checkouts to be listed instead. ** ** pull Run a "pull" operation on all repositories. Only the ** --verbose option is supported. ** ** push Run a "push" on all repositories. Only the --verbose ** option is supported. ** ** rebuild Rebuild on all repositories. The command line options ** supported by the rebuild command itself, if any are ** present, are passed along verbatim. The --force and ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** option is supported. ** ** Repositories are automatically added to the set of known repositories ** when one of the following commands are run against the repository: ** clone, info, pull, push, or sync. Even previously ignored repositories ** are added back to the list of repositories by these commands. ** ** Options: ** --dontstop Continue with other repositories even after an error. ** --dry-run If given, display instead of run actions. */ void all_cmd(void){ int n; Stmt q; const char *zCmd; char *zSyscmd; char *zFossil; |
︙ | ︙ | |||
120 121 122 123 124 125 126 | dryRunFlag = find_option("dry-run","n",0)!=0; if( !dryRunFlag ){ dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ } if( g.argc<3 ){ | | > > > > > > > > > > > > > > > > > > > > > > > > > | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | dryRunFlag = find_option("dry-run","n",0)!=0; if( !dryRunFlag ){ dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ } if( g.argc<3 ){ usage("changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync"); } n = strlen(g.argv[2]); db_open_config(1); blob_zero(&extra); zCmd = g.argv[2]; if( g.zLogin ) blob_appendf(&extra, " -U %s", g.zLogin); if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){ zCmd = "list"; useCheckouts = find_option("ckout","c",0)!=0; }else if( strncmp(zCmd, "clean", n)==0 ){ zCmd = "clean --chdir"; collect_argument(&extra, "allckouts",0); collect_argument_value(&extra, "case-sensitive"); collect_argument_value(&extra, "clean"); collect_argument(&extra, "dirsonly",0); collect_argument(&extra, "dotfiles",0); collect_argument(&extra, "emptydirs",0); collect_argument(&extra, "force","f"); collect_argument_value(&extra, "ignore"); collect_argument_value(&extra, "keep"); collect_argument(&extra, "temp",0); collect_argument(&extra, "verbose","v"); collect_argument(&extra, "whatif",0); useCheckouts = 1; }else if( strncmp(zCmd, "extra", n)==0 ){ zCmd = "extra --chdir"; collect_argument(&extra, "abs-paths",0); collect_argument_value(&extra, "case-sensitive"); collect_argument(&extra, "dotfiles",0); collect_argument_value(&extra, "ignore"); collect_argument(&extra, "rel-paths",0); useCheckouts = 1; stopOnError = 0; quiet = 1; }else if( strncmp(zCmd, "push", n)==0 ){ zCmd = "push -autourl -R"; collect_argument(&extra, "verbose","v"); }else if( strncmp(zCmd, "pull", n)==0 ){ zCmd = "pull -autourl -R"; collect_argument(&extra, "verbose","v"); }else if( strncmp(zCmd, "rebuild", n)==0 ){ |
︙ | ︙ | |||
183 184 185 186 187 188 189 | } fossil_free(zSql); } db_end_transaction(0); return; }else{ fossil_fatal("\"all\" subcommand should be one of: " | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | } fossil_free(zSql); } db_end_transaction(0); return; }else{ fossil_fatal("\"all\" subcommand should be one of: " "changes clean extra ignore list ls push pull rebuild sync"); } verify_all_options(); zFossil = quoteFilename(g.nameOfExe); if( useCheckouts ){ db_prepare(&q, "SELECT substr(name, 7) COLLATE nocase, max(rowid)" " FROM global_config" |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
382 383 384 385 386 387 388 | g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } #endif | | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } #endif pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0); if( pAttach==0 ) fossil_redirect_home(); zTarget = pAttach->zAttachTarget; zSrc = pAttach->zAttachSrc; ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%s'", zSrc); zName = pAttach->zAttachName; zDesc = pAttach->zComment; if( validate16(zTarget, strlen(zTarget)) |
︙ | ︙ |
Changes to src/branch.c.
︙ | ︙ | |||
71 72 73 74 75 76 77 | user_select(); db_begin_transaction(); rootid = name_to_typed_rid(g.argv[4], "ci"); if( rootid==0 ){ fossil_fatal("unable to locate check-in off of which to branch"); } | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | user_select(); db_begin_transaction(); rootid = name_to_typed_rid(g.argv[4], "ci"); if( rootid==0 ){ fossil_fatal("unable to locate check-in off of which to branch"); } pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0); if( pParent==0 ){ fossil_fatal("%s is not a valid check-in", g.argv[4]); } /* Create a manifest for the new branch */ blob_zero(&branch); if( pParent->zBaseline ){ |
︙ | ︙ |
Changes to src/browse.c.
︙ | ︙ | |||
329 330 331 332 333 334 335 | " fid INTEGER," " mid INTEGER," " mtime DATETIME," " pathname TEXT" ");" "CREATE INDEX fileage_fid ON fileage(fid);" ); | | | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | " fid INTEGER," " mid INTEGER," " mtime DATETIME," " pathname TEXT" ");" "CREATE INDEX fileage_fid ON fileage(fid);" ); pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); if( pManifest==0 ) return 1; manifest_file_rewind(pManifest); db_prepare(&ins, "INSERT INTO temp.fileage(fid, pathname)" " SELECT rid, :path FROM blob WHERE uuid=:uuid" ); while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ |
︙ | ︙ |
Changes to src/captcha.c.
︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ******************************************************************************* ** ** This file contains code to a simple text-based CAPTCHA. Though easily ** defeated by a sophisticated attacker, this CAPTCHA does at least make ** scripting attacks more difficult. */ | < > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** ******************************************************************************* ** ** This file contains code to a simple text-based CAPTCHA. Though easily ** defeated by a sophisticated attacker, this CAPTCHA does at least make ** scripting attacks more difficult. */ #include "config.h" #include <assert.h> #include "captcha.h" #if INTERFACE #define CAPTCHA 3 /* Which captcha rendering to use */ #endif /* |
︙ | ︙ |
Changes to src/cgi.c.
︙ | ︙ | |||
38 39 40 41 42 43 44 | typedef int socklen_t; #endif #include <time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "cgi.h" | | < < < < > > > > > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | typedef int socklen_t; #endif #include <time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "cgi.h" #include "cygsup.h" #if INTERFACE /* ** Shortcuts for cgi_parameter. P("x") returns the value of query parameter ** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y") ** does the same except "y" is returned in place of NULL if there is not match. */ #define P(x) cgi_parameter((x),0) #define PD(x,y) cgi_parameter((x),(y)) #define PT(x) cgi_parameter_trimmed((x),0) #define PDT(x,y) cgi_parameter_trimmed((x),(y)) /* ** Destinations for output text. */ #define CGI_HEADER 0 #define CGI_BODY 1 /* ** Flags for SSH HTTP clients */ #define CGI_SSH_CLIENT 0x0001 /* Client is SSH */ #define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */ #define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */ #endif /* INTERFACE */ /* ** The HTTP reply is generated in two pieces: the header and the body. ** These pieces are generated separately because they are not necessary ** produced in order. Parts of the header might be built after all or ** part of the body. The header and body are accumulated in separate |
︙ | ︙ | |||
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | /* Forward declaration */ static NORETURN void malformed_request(const char *zMsg); /* ** Initialize the query parameter database. Information is pulled from ** the QUERY_STRING environment variable (if it exists), from standard ** input if there is POST data, and from HTTP_COOKIE. */ void cgi_init(void){ char *z; const char *zType; int len; const char *zRequestUri = cgi_parameter("REQUEST_URI",0); const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); #ifdef FOSSIL_ENABLE_JSON json_main_bootstrap(); #endif g.isHTTP = 1; cgi_destination(CGI_BODY); | > > > > > > > > > > > > > > > > > | > > | > > > | > > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | /* Forward declaration */ static NORETURN void malformed_request(const char *zMsg); /* ** Initialize the query parameter database. Information is pulled from ** the QUERY_STRING environment variable (if it exists), from standard ** input if there is POST data, and from HTTP_COOKIE. ** ** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows: ** ** REQUEST_URI == SCRIPT_NAME + PATH_INFO ** ** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If ** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is ** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided ** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and ** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then ** assume that PATH_INFO is an empty string and set REQUEST_URI equal ** to PATH_INFO. ** ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and ** PATH_INFO when it is empty. */ void cgi_init(void){ char *z; const char *zType; int len; const char *zRequestUri = cgi_parameter("REQUEST_URI",0); const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); const char *zPathInfo = cgi_parameter("PATH_INFO",""); #ifdef FOSSIL_ENABLE_JSON json_main_bootstrap(); #endif g.isHTTP = 1; cgi_destination(CGI_BODY); if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME"); if( zRequestUri==0 ){ const char *z = zPathInfo; if( zPathInfo==0 ){ malformed_request("missing PATH_INFO and/or REQUEST_URI"); } if( z[0]=='/' ) z++; zRequestUri = mprintf("%s/%s", zScriptName, z); cgi_set_parameter("REQUEST_URI", zRequestUri); } if( zPathInfo==0 ){ int i, j; for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){} for(j=i; zRequestUri[j] && zRequestUri[j]!='?'; j++){} cgi_set_parameter("PATH_INFO", mprintf("%.*s", j-i, zRequestUri+i)); } z = (char*)P("HTTP_COOKIE"); |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); } } } cgi_init(); cgi_trace(0); } /* ** This routine handles a single SCGI request which is coming in on ** g.httpIn and which replies on g.httpOut ** ** The SCGI request is read from g.httpIn and is used to initialize ** entries in the cgi_parameter() hash, as if those entries were | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 | cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr); } } } cgi_init(); cgi_trace(0); } /* ** This routine handles a single HTTP request from an SSH client which is ** coming in on g.httpIn and which replies on g.httpOut ** ** Once all the setup is finished, this procedure returns ** and subsequent code handles the actual generation of the webpage. ** ** It is called in a loop so some variables will need to be replaced */ void cgi_handle_ssh_http_request(const char *zIpAddr){ static int nCycles = 0; static char *zCmd = 0; char *z, *zToken; const char *zType = 0; int i, content_length = 0; char zLine[2000]; /* A single line of input. */ if( zIpAddr ){ if( nCycles==0 ){ cgi_setenv("REMOTE_ADDR", zIpAddr); g.zIpAddr = mprintf("%s", zIpAddr); } }else{ fossil_panic("missing SSH IP address"); } if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request("missing HTTP header"); } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken==0 ){ malformed_request("malformed HTTP header"); } if( fossil_strcmp(zToken, "echo")==0 ){ /* start looking for probes to complete transport_open */ zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken); if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request("missing HTTP header"); } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken==0 ){ malformed_request("malformed HTTP header"); } }else if( zToken && strlen(zToken)==0 && zCmd ){ /* transport_flip request and continued transport_open */ cgi_handle_ssh_transport(zCmd); if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request("missing HTTP header"); } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken==0 ){ malformed_request("malformed HTTP header"); } } if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0 && fossil_strcmp(zToken,"HEAD")!=0 ){ malformed_request("unsupported HTTP method"); } if( nCycles==0 ){ cgi_setenv("GATEWAY_INTERFACE","CGI/1.0"); cgi_setenv("REQUEST_METHOD",zToken); } zToken = extract_token(z, &z); if( zToken==0 ){ malformed_request("malformed URL in HTTP header"); } if( nCycles==0 ){ cgi_setenv("REQUEST_URI", zToken); cgi_setenv("SCRIPT_NAME", ""); } for(i=0; zToken[i] && zToken[i]!='?'; i++){} if( zToken[i] ) zToken[i++] = 0; if( nCycles==0 ){ cgi_setenv("PATH_INFO", zToken); }else{ cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken)); } /* Get all the optional fields that follow the first line. */ while( fgets(zLine,sizeof(zLine),g.httpIn) ){ char *zFieldName; char *zVal; cgi_trace(zLine); zFieldName = extract_token(zLine,&zVal); if( zFieldName==0 || *zFieldName==0 ) break; while( fossil_isspace(*zVal) ){ zVal++; } i = strlen(zVal); while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; } zVal[i] = 0; for(i=0; zFieldName[i]; i++){ zFieldName[i] = fossil_tolower(zFieldName[i]); } if( fossil_strcmp(zFieldName,"content-length:")==0 ){ content_length = atoi(zVal); }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){ g.zContentType = zType = mprintf("%s", zVal); }else if( fossil_strcmp(zFieldName,"host:")==0 ){ if( nCycles==0 ){ cgi_setenv("HTTP_HOST", zVal); } }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){ if( nCycles==0 ){ cgi_setenv("HTTP_USER_AGENT", zVal); } }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){ if( fossil_strnicmp(zVal, "ssh", 3)==0 ){ if( nCycles==0 ){ g.fSshClient |= CGI_SSH_FOSSIL; g.fullHttpReply = 0; } } } } if( nCycles==0 ){ if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){ /* did not find new fossil ssh transport */ g.fSshClient &= ~CGI_SSH_CLIENT; g.fullHttpReply = 1; cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1"); } } cgi_reset_content(); cgi_destination(CGI_BODY); if( content_length>0 && zType ){ blob_zero(&g.cgiIn); if( fossil_strcmp(zType, "application/x-fossil")==0 ){ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length); blob_uncompress(&g.cgiIn, &g.cgiIn); }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length); }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){ blob_read_from_channel(&g.cgiIn, g.httpIn, content_length); } } cgi_trace(0); nCycles++; } /* ** This routine handles the old fossil SSH probes */ char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){ /* Start looking for probes */ while( fossil_strcmp(zToken, "echo")==0 ){ zToken = extract_token(z, &z); if( zToken==0 ){ malformed_request("malformed probe"); } if( fossil_strncmp(zToken, "test", 4)==0 || fossil_strncmp(zToken, "probe-", 6)==0 ){ fprintf(g.httpOut, "%s\n", zToken); fflush(g.httpOut); }else{ malformed_request("malformed probe"); } if( fgets(zLine, zSize, g.httpIn)==0 ){ malformed_request("malformed probe"); } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken==0 ){ malformed_request("malformed probe"); } } /* Got all probes now first transport_open is completed ** so return the command that was requested */ g.fSshClient |= CGI_SSH_COMPAT; return mprintf("%s", zToken); } /* ** This routine handles the old fossil SSH transport_flip ** and transport_open communications if detected. */ void cgi_handle_ssh_transport(const char *zCmd){ char *z, *zToken; char zLine[2000]; /* A single line of input. */ /* look for second newline of transport_flip */ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request("incorrect transport_flip"); } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken && strlen(zToken)==0 ){ /* look for path to fossil */ if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ if ( zCmd==0 ){ malformed_request("missing fossil command"); }else{ /* no new command so exit */ fossil_exit(0); } } cgi_trace(zLine); zToken = extract_token(zLine, &z); if( zToken==0 ){ malformed_request("malformed fossil command"); } /* see if we've seen the command */ if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){ return; }else{ malformed_request("transport_open failed"); } }else{ malformed_request("transport_flip failed"); } } /* ** This routine handles a single SCGI request which is coming in on ** g.httpIn and which replies on g.httpOut ** ** The SCGI request is read from g.httpIn and is used to initialize ** entries in the cgi_parameter() hash, as if those entries were |
︙ | ︙ | |||
1443 1444 1445 1446 1447 1448 1449 | if( zBrowser ){ zBrowser = mprintf(zBrowser, iPort); #if defined(__CYGWIN__) /* On Cygwin, we can do better than "echo" */ if( memcmp(zBrowser, "echo ", 5)==0 ){ wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5); wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */ | | | 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 | if( zBrowser ){ zBrowser = mprintf(zBrowser, iPort); #if defined(__CYGWIN__) /* On Cygwin, we can do better than "echo" */ if( memcmp(zBrowser, "echo ", 5)==0 ){ wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5); wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */ if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){ fossil_warning("cannot start browser\n"); } }else #endif if( system(zBrowser)<0 ){ fossil_warning("cannot start browser: %s\n", zBrowser); } |
︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 | if( zIf==0 ) return; if( objectTime > cgi_rfc822_parsedate(zIf) ) return; cgi_set_status(304,"Not Modified"); cgi_reset_content(); cgi_reply(); fossil_exit(0); } | > > > > > > > > > > > > > > > > > > | 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 | if( zIf==0 ) return; if( objectTime > cgi_rfc822_parsedate(zIf) ) return; cgi_set_status(304,"Not Modified"); cgi_reset_content(); cgi_reply(); fossil_exit(0); } /* ** Check to see if the remote client is SSH and return ** its IP or return default */ const char *cgi_ssh_remote_addr(const char *zDefault){ char *zIndex; const char *zSshConn = fossil_getenv("SSH_CONNECTION"); if( zSshConn && zSshConn[0] ){ char *zSshClient = mprintf("%s",zSshConn); if( (zIndex = strchr(zSshClient,' '))!=0 ){ zSshClient[zIndex-zSshClient] = '\0'; return zSshClient; } } return zDefault; } |
Changes to src/checkin.c.
︙ | ︙ | |||
840 841 842 843 844 845 846 | blob_append(&prompt, zInit, -1); } #else blob_init(&prompt, zInit, -1); #endif blob_append(&prompt, "\n" | | | 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | blob_append(&prompt, zInit, -1); } #else blob_init(&prompt, zInit, -1); #endif blob_append(&prompt, "\n" "# Enter commit message for this check-in. Lines beginning with # are ignored.\n" "#\n", -1 ); blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : g.zLogin); if( p->zBranch && p->zBranch[0] ){ blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch); }else{ char *zTags = info_tags_of_checkin(parent_rid, 1); |
︙ | ︙ | |||
1017 1018 1019 1020 1021 1022 1023 | const char *zBaselineUuid, /* UUID of baseline, or zero */ Manifest *pBaseline, /* Make it a delta manifest if not zero */ int vid, /* BLOB.id for the parent check-in */ CheckinInfo *p, /* Information about the check-in */ int *pnFBcard /* OUT: Number of generated B- and F-cards */ ){ char *zDate; /* Date of the check-in */ | | > | > > > > > > > | 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | const char *zBaselineUuid, /* UUID of baseline, or zero */ Manifest *pBaseline, /* Make it a delta manifest if not zero */ int vid, /* BLOB.id for the parent check-in */ CheckinInfo *p, /* Information about the check-in */ int *pnFBcard /* OUT: Number of generated B- and F-cards */ ){ char *zDate; /* Date of the check-in */ char *zParentUuid = 0; /* UUID of parent check-in */ Blob filename; /* A single filename */ int nBasename; /* Size of base filename */ Stmt q; /* Various queries */ Blob mcksum; /* Manifest checksum */ ManifestFile *pFile; /* File from the baseline */ int nFBcard = 0; /* Number of B-cards and F-cards */ int i; /* Loop counter */ const char *zColor; /* Modified value of p->zColor */ assert( pBaseline==0 || pBaseline->zBaseline==0 ); assert( pBaseline==0 || zBaselineUuid!=0 ); blob_zero(pOut); if( vid ){ zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND " "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)", vid, vid); if( !zParentUuid ){ fossil_fatal("Could not find a valid check-in for RID %d. " "Possible checkout/repo mismatch.", vid); } } if( pBaseline ){ blob_appendf(pOut, "B %s\n", zBaselineUuid); manifest_file_rewind(pBaseline); pFile = manifest_file_next(pBaseline, 0); nFBcard++; }else{ pFile = 0; |
︙ | ︙ | |||
1125 1126 1127 1128 1129 1130 1131 | blob_appendf(pOut, "F %F\n", pFile->zName); pFile = manifest_file_next(pBaseline, 0); nFBcard++; } if( p->zMimetype && p->zMimetype[0] ){ blob_appendf(pOut, "N %F\n", p->zMimetype); } | > | | | | | | | | | | | | | | | | < | > > | 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | blob_appendf(pOut, "F %F\n", pFile->zName); pFile = manifest_file_next(pBaseline, 0); nFBcard++; } if( p->zMimetype && p->zMimetype[0] ){ blob_appendf(pOut, "N %F\n", p->zMimetype); } if( vid ){ blob_appendf(pOut, "P %s", zParentUuid); if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate); free(zParentUuid); db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2"); while( db_step(&q)==SQLITE_ROW ){ char *zMergeUuid; int mid = db_column_int(&q, 0); if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue; zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); if( zMergeUuid ){ blob_appendf(pOut, " %s", zMergeUuid); if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate); free(zMergeUuid); } } db_finalize(&q); blob_appendf(pOut, "\n"); } free(zDate); db_prepare(&q, "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge" " FROM vmerge, blob" " WHERE (vmerge.id=-1 OR vmerge.id=-2)" " AND blob.rid=vmerge.merge" " ORDER BY 1"); |
︙ | ︙ | |||
1642 1643 1644 1645 1646 1647 1648 1649 | fossil_fatal("none of the selected files have changed; use " "--allow-empty to override."); } /* ** Do not allow a commit that will cause a fork unless the --allow-fork ** or --force flags is used, or unless this is a private check-in. */ | > > > > > | | 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 | fossil_fatal("none of the selected files have changed; use " "--allow-empty to override."); } /* ** Do not allow a commit that will cause a fork unless the --allow-fork ** or --force flags is used, or unless this is a private check-in. ** The initial commit MUST have tags "trunk" and "sym-trunk". */ if( !vid ){ if( sCiInfo.zBranch==0 ){ sCiInfo.zBranch = db_get("main-branch", "trunk"); } }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ fossil_fatal("would fork. \"update\" first or use --allow-fork."); } /* ** Do not allow a commit against a closed leaf |
︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | } /* See if a delta-manifest would be more appropriate */ if( !forceBaseline ){ const char *zBaselineUuid; Manifest *pParent; Manifest *pBaseline; | | | 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 | } /* See if a delta-manifest would be more appropriate */ if( !forceBaseline ){ const char *zBaselineUuid; Manifest *pParent; Manifest *pBaseline; pParent = manifest_get(vid, CFTYPE_MANIFEST, 0); if( pParent && pParent->zBaseline ){ zBaselineUuid = pParent->zBaseline; pBaseline = manifest_get_by_name(zBaselineUuid, 0); }else{ zBaselineUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); pBaseline = pParent; } |
︙ | ︙ |
Changes to src/checkout.c.
︙ | ︙ | |||
101 102 103 104 105 106 107 | Blob filename; int baseLen; Manifest *pManifest; ManifestFile *pFile; /* Check the EXE permission status of all files */ | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | Blob filename; int baseLen; Manifest *pManifest; ManifestFile *pFile; /* Check the EXE permission status of all files */ pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); if( pManifest==0 ) return; blob_zero(&filename); blob_appendf(&filename, "%s", g.zLocalRoot); baseLen = blob_size(&filename); manifest_file_rewind(pManifest); while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ int isExe; |
︙ | ︙ | |||
218 219 220 221 222 223 224 | " ORDER BY event.mtime DESC"); if( zVers==0 ){ zVers = db_text(0, "SELECT uuid FROM event, blob" " WHERE event.objid=blob.rid AND event.type='ci'" " ORDER BY event.mtime DESC"); } if( zVers==0 ){ | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | " ORDER BY event.mtime DESC"); if( zVers==0 ){ zVers = db_text(0, "SELECT uuid FROM event, blob" " WHERE event.objid=blob.rid AND event.type='ci'" " ORDER BY event.mtime DESC"); } if( zVers==0 ){ return; } }else{ zVers = g.argv[2]; } vid = load_vfile(zVers); if( prior==vid ){ return; |
︙ | ︙ |
Changes to src/clone.c.
︙ | ︙ | |||
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | ** admin user. This can be overridden using the -A|--admin-user ** parameter. ** ** Options: ** --admin-user|-A USERNAME Make USERNAME the administrator ** --private Also clone private branches ** --ssl-identity=filename Use the SSL identity if requested by the server ** ** See also: init */ void clone_cmd(void){ char *zPassword; const char *zDefaultUser; /* Optional name of the default user */ int nErr = 0; int bPrivate = 0; /* Also clone private branches */ if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; url_proxy_options(); if( g.argc < 4 ){ usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); } db_open_config(0); if( file_size(g.argv[3])>0 ){ fossil_fatal("file already exists: %s", g.argv[3]); } zDefaultUser = find_option("admin-user","A",1); url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW); if( g.urlIsFile ){ file_copy(g.urlName, g.argv[3]); db_close(1); db_open_repository(g.argv[3]); db_record_repository_filename(g.argv[3]); url_remember(); if( !bPrivate ) delete_private_content(); | > > > | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ** admin user. This can be overridden using the -A|--admin-user ** parameter. ** ** Options: ** --admin-user|-A USERNAME Make USERNAME the administrator ** --private Also clone private branches ** --ssl-identity=filename Use the SSL identity if requested by the server ** --ssh-command|-c 'command' Use this SSH command ** ** See also: init */ void clone_cmd(void){ char *zPassword; const char *zDefaultUser; /* Optional name of the default user */ int nErr = 0; int bPrivate = 0; /* Also clone private branches */ if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; clone_ssh_find_options(); url_proxy_options(); if( g.argc < 4 ){ usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); } db_open_config(0); if( file_size(g.argv[3])>0 ){ fossil_fatal("file already exists: %s", g.argv[3]); } zDefaultUser = find_option("admin-user","A",1); url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW); if( zDefaultUser==0 && g.urlUser!=0 ) zDefaultUser = g.urlUser; if( g.urlIsFile ){ file_copy(g.urlName, g.argv[3]); db_close(1); db_open_repository(g.argv[3]); db_record_repository_filename(g.argv[3]); url_remember(); if( !bPrivate ) delete_private_content(); |
︙ | ︙ | |||
165 166 167 168 169 170 171 172 173 174 175 176 177 178 | blob_reset(&fn); } db_multi_exec( "REPLACE INTO config(name,value,mtime)" " VALUES('server-code', lower(hex(randomblob(20))), now());" ); url_enable_proxy(0); url_get_password_if_needed(); g.xlinkClusterOnly = 1; nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); g.xlinkClusterOnly = 0; verify_cancel(); db_end_transaction(0); db_close(1); | > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | blob_reset(&fn); } db_multi_exec( "REPLACE INTO config(name,value,mtime)" " VALUES('server-code', lower(hex(randomblob(20))), now());" ); url_enable_proxy(0); clone_ssh_db_set_options(); url_get_password_if_needed(); g.xlinkClusterOnly = 1; nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); g.xlinkClusterOnly = 0; verify_cancel(); db_end_transaction(0); db_close(1); |
︙ | ︙ | |||
186 187 188 189 190 191 192 | fossil_print("Rebuilding repository meta-data...\n"); rebuild_db(0, 1, 0); fossil_print("project-id: %s\n", db_get("project-code", 0)); zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); db_end_transaction(0); } | > > > > > > > > > > > > > > > > > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | fossil_print("Rebuilding repository meta-data...\n"); rebuild_db(0, 1, 0); fossil_print("project-id: %s\n", db_get("project-code", 0)); zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); db_end_transaction(0); } /* ** Look for SSH clone command line options and setup in globals. */ void clone_ssh_find_options(void){ const char *zSshCmd; /* SSH command string */ zSshCmd = find_option("ssh-command","c",1); if( zSshCmd && zSshCmd[0] ){ g.zSshCmd = mprintf("%s", zSshCmd); } } /* ** Set SSH options discovered in global variables (set from command line ** options). */ void clone_ssh_db_set_options(void){ if( g.zSshCmd && g.zSshCmd[0] ){ db_set("ssh-command", g.zSshCmd, 0); } } |
Changes to src/comformat.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | /* ** Given a comment string zText, format that string for printing ** on a TTY. Assume that the output cursors is indent spaces from ** the left margin and that a single line can contain no more than ** lineLength characters. Indent all subsequent lines by indent. ** | < < > | > > > > > > > > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | /* ** Given a comment string zText, format that string for printing ** on a TTY. Assume that the output cursors is indent spaces from ** the left margin and that a single line can contain no more than ** lineLength characters. Indent all subsequent lines by indent. ** ** Return the number of newlines that are output. */ int comment_print(const char *zText, int indent, int lineLength){ int tlen = lineLength - indent; int si, sk, i, k; int doIndent = 0; char *zBuf; char zBuffer[400]; int lineCnt = 0; if( tlen<=0 ){ tlen = strlen(zText); } if( tlen >= (sizeof(zBuffer)) ){ zBuf = fossil_malloc(tlen+1); }else{ zBuf = zBuffer; } for(;;){ while( fossil_isspace(zText[0]) ){ zText++; } if( zText[0]==0 ){ if( doIndent==0 ){ fossil_print("\n"); lineCnt = 1; } if( zBuf!=zBuffer) fossil_free(zBuf); return lineCnt; } for(sk=si=i=k=0; zText[i] && k<tlen; i++){ char c = zText[i]; if( fossil_isspace(c) ){ si = i; sk = k; |
︙ | ︙ | |||
67 68 69 70 71 72 73 | } if( doIndent ){ fossil_print("%*s", indent, ""); } doIndent = 1; if( sk>0 && zText[i] ){ zText += si; | < < < < > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | } if( doIndent ){ fossil_print("%*s", indent, ""); } doIndent = 1; if( sk>0 && zText[i] ){ zText += si; zBuf[sk] = 0; }else{ zText += i; zBuf[k] = 0; } fossil_print("%s\n", zBuf); lineCnt++; } } /* ** Test the comment printing ** |
︙ | ︙ |
Changes to src/config.h.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** some linux distributions, and possibly other unixes as well. */ #define _LARGE_FILE 1 #ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 #endif #define _LARGEFILE_SOURCE 1 #ifdef HAVE_AUTOCONFIG_H #include "autoconfig.h" #endif #ifndef _RC_COMPILE_ | > > > > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** some linux distributions, and possibly other unixes as well. */ #define _LARGE_FILE 1 #ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 #endif #define _LARGEFILE_SOURCE 1 /* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */ #if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T) # define _USE_32BIT_TIME_T #endif #ifdef HAVE_AUTOCONFIG_H #include "autoconfig.h" #endif #ifndef _RC_COMPILE_ |
︙ | ︙ | |||
80 81 82 83 84 85 86 | # elif defined(__GNUC__) # define COMPILER_NAME "gcc-" __VERSION__ # else # define COMPILER_NAME "unknown" # endif #endif | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | # elif defined(__GNUC__) # define COMPILER_NAME "gcc-" __VERSION__ # else # define COMPILER_NAME "unknown" # endif #endif #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) #include "sqlite3.h" /* ** On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257. */ #if HAVE_GETPASSPHRASE |
︙ | ︙ |
Changes to src/configure.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #define CONFIGSET_XFER 0x000080 /* Transfer configuration */ #define CONFIGSET_ALL 0x0000ff /* Everything */ #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */ #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */ #endif /* INTERFACE */ /* ** Names of the configuration sets */ static struct { const char *zName; /* Name of the configuration set */ | > > > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #define CONFIGSET_XFER 0x000080 /* Transfer configuration */ #define CONFIGSET_ALL 0x0000ff /* Everything */ #define CONFIGSET_OVERWRITE 0x100000 /* Causes overwrite instead of merge */ #define CONFIGSET_OLDFORMAT 0x200000 /* Use the legacy format */ /* ** This mask is used for the common TH1 configuration settings (i.e. those ** that are not specific to one particular subsystem, such as the transfer ** subsystem). */ #define CONFIGSET_TH1 (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER) #endif /* INTERFACE */ /* ** Names of the configuration sets */ static struct { const char *zName; /* Name of the configuration set */ |
︙ | ︙ | |||
88 89 90 91 92 93 94 | { "index-page", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, { "timeline-plaintext", CONFIGSET_SKIN }, { "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, | | | | > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | { "index-page", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, { "timeline-plaintext", CONFIGSET_SKIN }, { "adunit", CONFIGSET_SKIN }, { "adunit-omit-if-admin", CONFIGSET_SKIN }, { "adunit-omit-if-user", CONFIGSET_SKIN }, { "th1-setup", CONFIGSET_TH1 }, #ifdef FOSSIL_ENABLE_TCL { "tcl", CONFIGSET_TH1 }, { "tcl-setup", CONFIGSET_TH1 }, #endif { "project-name", CONFIGSET_PROJ }, { "short-project-name", CONFIGSET_PROJ }, { "project-description", CONFIGSET_PROJ }, { "manifest", CONFIGSET_PROJ }, { "binary-glob", CONFIGSET_PROJ }, { "clean-glob", CONFIGSET_PROJ }, { "ignore-glob", CONFIGSET_PROJ }, { "keep-glob", CONFIGSET_PROJ }, { "crnl-glob", CONFIGSET_PROJ }, |
︙ | ︙ |
Added src/cygsup.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | /* ** Copyright (c) 2007 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains preprocessor directives used to help integrate with the ** Cygwin runtime and build environment. The intent of this file is to keep ** the Cygwin-specific preprocessor directives together. */ #if defined(__CYGWIN__) && !defined(CYGSUP_H) #define CYGSUP_H /* ******************************************************************************* ** Include any Cygwin-specific headers here. ** ******************************************************************************* */ #include <wchar.h> #include <sys/cygwin.h> /* ******************************************************************************* ** Define any Cygwin-specific preprocessor macros here. All macros defined in ** this section should be wrapped with #ifndef, in order to allow them to be ** externally overridden. ******************************************************************************* */ #ifndef CP_UTF8 # define CP_UTF8 65001 #endif #ifndef WINBASEAPI # define WINBASEAPI __declspec(dllimport) #endif #ifndef WINADVAPI # define WINADVAPI __declspec(dllimport) #endif #ifndef SHSTDAPI # define SHSTDAPI __declspec(dllimport) #endif #ifndef STDAPI # define STDAPI __stdcall #endif #ifndef WINAPI # define WINAPI __stdcall #endif /* ******************************************************************************* ** Declare any Cygwin-specific Win32 or other APIs here. Functions declared in ** this section should use the built-in ANSI C types in order to make sure this ** header file continues to work as a self-contained unit. ** ** On Cygwin64, "long" is 64-bit but in Win64 it's 32-bit. That's why in the ** signatures below "long" should not be used. They now use "int" instead. ******************************************************************************* */ WINADVAPI extern WINAPI int RegOpenKeyExW( void *, /* HKEY */ const wchar_t *, /* LPCWSTR */ unsigned int, /* DWORD */ unsigned int, /* REGSAM */ void * /* PHKEY */ ); WINADVAPI extern WINAPI int RegQueryValueExW( void *, /* HKEY */ const wchar_t *, /* LPCWSTR */ unsigned int *, /* LPDWORD */ unsigned int *, /* LPDWORD */ unsigned char *, /* LPBYTE */ unsigned int * /* LPDWORD */ ); SHSTDAPI extern STDAPI void *ShellExecuteW( void *, /* HWND */ const wchar_t *, /* LPCWSTR */ const wchar_t *, /* LPCWSTR */ const wchar_t *, /* LPCWSTR */ const wchar_t *, /* LPCWSTR */ int /* INT */ ); WINBASEAPI extern WINAPI int WideCharToMultiByte( unsigned int, /* UINT */ unsigned int, /* DWORD */ const wchar_t *, /* LPCWSTR */ int, /* int */ char *, /* LPSTR */ int, /* int */ const char *, /* LPCSTR */ int * /* LPBOOL */ ); WINBASEAPI extern WINAPI int MultiByteToWideChar( unsigned int, /* UINT */ unsigned int, /* DWORD */ const char *, /* LPCSTR */ int, /* int */ wchar_t *, /* LPWSTR */ int /* int */ ); #endif /* defined(__CYGWIN__) && !defined(CYGSUP_H) */ |
Changes to src/delta.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ** This module implements the delta compress algorithm. ** ** Though developed specifically for fossil, the code in this file ** is generally applicable and is thus easily separated from the ** fossil source code base. Nothing in this file depends on anything ** else in fossil. */ #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include "delta.h" /* | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** This module implements the delta compress algorithm. ** ** Though developed specifically for fossil, the code in this file ** is generally applicable and is thus easily separated from the ** fossil source code base. Nothing in this file depends on anything ** else in fossil. */ #include "config.h" #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include "delta.h" /* |
︙ | ︙ |
Changes to src/descendants.c.
︙ | ︙ | |||
327 328 329 330 331 332 333 | compute_leaves(base, 0); db_prepare(&q, "%s" " AND event.objid IN (SELECT rid FROM leaves)" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | compute_leaves(base, 0); db_prepare(&q, "%s" " AND event.objid IN (SELECT rid FROM leaves)" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); print_timeline(&q, -20, 79, 0); db_finalize(&q); } /* ** COMMAND: leaves* ** ** Usage: %fossil leaves ?OPTIONS? |
︙ | ︙ |
Changes to src/diff.c.
︙ | ︙ | |||
1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 | int nVers; /* Number of versions analyzed */ int bLimit; /* True if the iLimit was reached */ struct AnnVers { const char *zFUuid; /* File being analyzed */ const char *zMUuid; /* Check-in containing the file */ const char *zDate; /* Date of the check-in */ const char *zBgColor; /* Suggested background color */ unsigned cnt; /* Number of lines contributed by this check-in */ } *aVers; /* For each check-in analyzed */ char **azVers; /* Names of versions analyzed */ }; /* ** Initialize the annotation process by specifying the file that is | > | 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 | int nVers; /* Number of versions analyzed */ int bLimit; /* True if the iLimit was reached */ struct AnnVers { const char *zFUuid; /* File being analyzed */ const char *zMUuid; /* Check-in containing the file */ const char *zDate; /* Date of the check-in */ const char *zBgColor; /* Suggested background color */ const char *zUser; /* Name of user who did the check-in */ unsigned cnt; /* Number of lines contributed by this check-in */ } *aVers; /* For each check-in analyzed */ char **azVers; /* Names of versions analyzed */ }; /* ** Initialize the annotation process by specifying the file that is |
︙ | ︙ | |||
2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | ); db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)"); db_prepare(&q, "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid)," " (SELECT uuid FROM blob WHERE rid=mlink.mid)," " date(event.mtime)," " mlink.pid" " FROM mlink, event" " WHERE mlink.fid=:rid" " AND event.objid=mlink.mid" " AND mlink.pid NOT IN vseen" " ORDER BY %s event.mtime", (annFlags & ANN_FILE_ANCEST)!=0 ? "(mlink.mid IN (SELECT rid FROM ancestor)) DESC,":"" ); db_bind_int(&q, ":rid", rid); if( iLimit==0 ) iLimit = 1000000000; while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){ | > | > | 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 | ); db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)"); db_prepare(&q, "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid)," " (SELECT uuid FROM blob WHERE rid=mlink.mid)," " date(event.mtime)," " coalesce(event.euser,event.user)," " mlink.pid" " FROM mlink, event" " WHERE mlink.fid=:rid" " AND event.objid=mlink.mid" " AND mlink.pid NOT IN vseen" " ORDER BY %s event.mtime", (annFlags & ANN_FILE_ANCEST)!=0 ? "(mlink.mid IN (SELECT rid FROM ancestor)) DESC,":"" ); db_bind_int(&q, ":rid", rid); if( iLimit==0 ) iLimit = 1000000000; while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){ int prevId = db_column_int(&q, 4); p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0])); p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0)); p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); if( p->nVers ){ content_get(rid, &step); annotation_step(p, &step, p->nVers-1); blob_reset(&step); } p->nVers++; db_bind_int(&ins, ":rid", rid); |
︙ | ︙ | |||
2266 2267 2268 2269 2270 2271 2272 2273 | } @ </pre> style_footer(); } /* ** COMMAND: annotate ** | > | | > > | 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 | } @ </pre> style_footer(); } /* ** COMMAND: annotate ** COMMAND: blame ** ** %fossil (annotate|blame) ?OPTIONS? FILENAME ** ** Output the text of a file with markings to show when each line of ** the file was last modified. The "annotate" command shows line numbers ** and omits the username. The "blame" command shows the user who made each ** checkin and omits the line number. ** ** Options: ** --filevers Show file version numbers rather than check-in versions ** -l|--log List all versions analyzed ** -n|--limit N Only look backwards in time by N versions ** ** See also: info, finfo, timeline |
︙ | ︙ | |||
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 | Annotator ann; /* The annotation of the file */ int i; /* Loop counter */ const char *zLimit; /* The value to the -n|--limit option */ int iLimit; /* How far back in time to look */ int showLog; /* True to show the log */ int fileVers; /* Show file version instead of check-in versions */ int annFlags = 0; /* Flags to control annotation properties */ zLimit = find_option("limit","n",1); if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; iLimit = atoi(zLimit); showLog = find_option("log","l",0)!=0; fileVers = find_option("filevers",0,0)!=0; db_must_be_within_tree(); if( g.argc<3 ) { | > > | 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 | Annotator ann; /* The annotation of the file */ int i; /* Loop counter */ const char *zLimit; /* The value to the -n|--limit option */ int iLimit; /* How far back in time to look */ int showLog; /* True to show the log */ int fileVers; /* Show file version instead of check-in versions */ int annFlags = 0; /* Flags to control annotation properties */ int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ bBlame = g.argv[1][0]=='b'; zLimit = find_option("limit","n",1); if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; iLimit = atoi(zLimit); showLog = find_option("log","l",0)!=0; fileVers = find_option("filevers",0,0)!=0; db_must_be_within_tree(); if( g.argc<3 ) { |
︙ | ︙ | |||
2340 2341 2342 2343 2344 2345 2346 | } fossil_print("---------------------------------------------------\n"); } for(i=0; i<ann.nOrig; i++){ int iVers = ann.aOrig[i].iVers; char *z = (char*)ann.aOrig[i].z; int n = ann.aOrig[i].n; | | < > > | < | | | | | > > > > > | > | | > > | 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 | } fossil_print("---------------------------------------------------\n"); } for(i=0; i<ann.nOrig; i++){ int iVers = ann.aOrig[i].iVers; char *z = (char*)ann.aOrig[i].z; int n = ann.aOrig[i].n; struct AnnVers *p; if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; p = ann.aVers + iVers; if( bBlame ){ if( iVers>=0 ){ fossil_print("%.10s %s %13.13s: %.*s\n", fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z); }else{ fossil_print("%35s %.*s\n", "", n, z); } }else{ if( iVers>=0 ){ fossil_print("%.10s %s %5d: %.*s\n", fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z); }else{ fossil_print("%21s %5d: %.*s\n", "", i+1, n, z); } } } } |
Changes to src/diffcmd.c.
︙ | ︙ | |||
913 914 915 916 917 918 919 | ** (1) Write the Tcl/Tk script used for rendering into a temp file. ** (2) Invoke "wish" on the temp file using fossil_system(). ** (3) Delete the temp file. */ void diff_tk(const char *zSubCmd, int firstArg){ int i; Blob script; | | > > > > > > > > > > > > | | | | | > > | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 | ** (1) Write the Tcl/Tk script used for rendering into a temp file. ** (2) Invoke "wish" on the temp file using fossil_system(). ** (3) Delete the temp file. */ void diff_tk(const char *zSubCmd, int firstArg){ int i; Blob script; char *zTempFile = 0; char *zCmd; blob_zero(&script); blob_appendf(&script, "set fossilcmd {| \"%/\" %s --html -y -i -v", g.nameOfExe, zSubCmd); for(i=firstArg; i<g.argc; i++){ const char *z = g.argv[i]; if( z[0]=='-' ){ if( strglob("*-html",z) ) continue; if( strglob("*-y",z) ) continue; if( strglob("*-i",z) ) continue; /* The undocumented --script FILENAME option causes the Tk script to ** be written into the FILENAME instead of being run. This is used ** for testing and debugging. */ if( strglob("*-script",z) && i<g.argc-1 ){ i++; zTempFile = g.argv[i]; continue; } } blob_append(&script, " ", 1); shell_escape(&script, z); } blob_appendf(&script, "}\n%s", zDiffScript); if( zTempFile ){ blob_write_to_file(&script, zTempFile); fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile); }else{ zTempFile = write_blob_to_temp_file(&script); zCmd = mprintf("tclsh \"%s\"", zTempFile); fossil_system(zCmd); file_delete(zTempFile); fossil_free(zCmd); } blob_reset(&script); } /* ** Returns non-zero if files that may be binary should be used with external ** diff programs. */ int diff_include_binary_files(void){ |
︙ | ︙ |
Changes to src/doc.c.
︙ | ︙ | |||
447 448 449 450 451 452 453 | Manifest *pM; ManifestFile *pFile; /* Add the vid baseline to the cache */ if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){ db_multi_exec("DELETE FROM vcache"); } | | | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | Manifest *pM; ManifestFile *pFile; /* Add the vid baseline to the cache */ if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){ db_multi_exec("DELETE FROM vcache"); } pM = manifest_get(vid, CFTYPE_MANIFEST, 0); if( pM==0 ){ goto doc_not_found; } db_prepare(&s, "INSERT INTO vcache(vid,fname,rid)" " SELECT %d, :fname, rid FROM blob" " WHERE uuid=:uuid", |
︙ | ︙ |
Changes to src/event.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 | ** ** Milestones ** Blog posts ** New articles ** Process checkpoints ** Announcements */ #include <assert.h> #include <ctype.h> | > < | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** ** Milestones ** Blog posts ** New articles ** Process checkpoints ** Announcements */ #include "config.h" #include <assert.h> #include <ctype.h> #include "event.h" /* ** Output a hyperlink to an event given its tagid. */ void hyperlink_to_event_tagid(int tagid){ char *zEventId; |
︙ | ︙ | |||
111 112 113 114 115 116 117 | if( !zVerbose ){ zVerbose = P("detail"); /* deprecated */ } verboseFlag = (zVerbose!=0) && !is_false(zVerbose); /* Extract the event content. */ | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | if( !zVerbose ){ zVerbose = P("detail"); /* deprecated */ } verboseFlag = (zVerbose!=0) && !is_false(zVerbose); /* Extract the event content. */ pEvent = manifest_get(rid, CFTYPE_EVENT, 0); if( pEvent==0 ){ fossil_fatal("Object #%d is not an event", rid); } blob_init(&fullbody, pEvent->zWiki, -1); if( wiki_find_title(&fullbody, &title, &tail) ){ style_header(blob_str(&title)); }else{ |
︙ | ︙ | |||
255 256 257 258 259 260 261 | /* If editing an existing event, extract the key fields to use as ** a starting point for the edit. */ if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){ Manifest *pEvent; | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | /* If editing an existing event, extract the key fields to use as ** a starting point for the edit. */ if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){ Manifest *pEvent; pEvent = manifest_get(rid, CFTYPE_EVENT, 0); if( pEvent && pEvent->type==CFTYPE_EVENT ){ if( zBody==0 ) zBody = pEvent->zWiki; if( zETime==0 ){ zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); } if( zComment==0 ) zComment = pEvent->zComment; } |
︙ | ︙ |
Changes to src/finfo.c.
︙ | ︙ | |||
41 42 43 44 45 46 47 | ** to stdout. The -p mode is another form of the "cat" command. ** ** Options: ** -b|--brief display a brief (one line / revision) summary ** --case-sensitive B Enable or disable case-sensitive filenames. B is a ** boolean: "yes", "no", "true", "false", etc. ** -l|--log select log mode (the default) | | > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | ** to stdout. The -p mode is another form of the "cat" command. ** ** Options: ** -b|--brief display a brief (one line / revision) summary ** --case-sensitive B Enable or disable case-sensitive filenames. B is a ** boolean: "yes", "no", "true", "false", etc. ** -l|--log select log mode (the default) ** -n|--limit N display the first N changes. N=0 means no limit. ** --offset P skip P changes ** -p|--print select print mode ** -r|--revision R print the given revision (or ckout, if none is given) ** to stdout (only in print mode) ** -s|--status select status mode (print a status indicator for FILE) ** -W|--width <num> With of lines (default 79). Must be >22 or 0. ** ** See also: artifact, cat, descendants, info, leaves */ void finfo_cmd(void){ capture_case_sensitive_option(); db_must_be_within_tree(); if( find_option("status","s",0) ){ |
︙ | ︙ | |||
132 133 134 135 136 137 138 139 | }else{ Blob line; Stmt q; Blob fname; int rid; const char *zFilename; const char *zLimit; const char *zOffset; | > | > > > > > | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | }else{ Blob line; Stmt q; Blob fname; int rid; const char *zFilename; const char *zLimit; const char *zWidth; const char *zOffset; int iLimit, iOffset, iBrief, iWidth; if( find_option("log","l",0) ){ /* this is the default, no-op */ } zLimit = find_option("limit","n",1); zWidth = find_option("width","W",1); iLimit = zLimit ? atoi(zLimit) : -1; iWidth = zWidth ? atoi(zWidth) : 79; zOffset = find_option("offset",0,1); iOffset = zOffset ? atoi(zOffset) : 0; iBrief = (find_option("brief","b",0) == 0); if( (iWidth!=0) && (iWidth<=22) ){ fossil_fatal("--width|-W value must be >22 or 0"); } if( g.argc!=3 ){ usage("?-l|--log? ?-b|--brief? FILENAME"); } file_tree_name(g.argv[2], &fname, 1); rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s", &fname, filename_collation()); if( rid==0 ){ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | char *zOut; if( zBr==0 ) zBr = "trunk"; if( iBrief ){ fossil_print("%s ", zDate); zOut = sqlite3_mprintf( "[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)", zCiUuid, zCom, zUser, zFileUuid, zBr); | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | char *zOut; if( zBr==0 ) zBr = "trunk"; if( iBrief ){ fossil_print("%s ", zDate); zOut = sqlite3_mprintf( "[%.10s] %s (user: %s, artifact: [%.10s], branch: %s)", zCiUuid, zCom, zUser, zFileUuid, zBr); comment_print(zOut, 11, iWidth); sqlite3_free(zOut); }else{ blob_reset(&line); blob_appendf(&line, "%.10s ", zCiUuid); blob_appendf(&line, "%.10s ", zDate); blob_appendf(&line, "%8.8s ", zUser); blob_appendf(&line, "%8.8s ", zBr); |
︙ | ︙ |
Changes to src/gzip.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 | ** ** This file contains code used to incrementally generate a GZIP compressed ** file. The GZIP format is described in RFC-1952. ** ** State information is stored in static variables, so this implementation ** can only be building up a single GZIP file at a time. */ #include <assert.h> #include <zlib.h> | > < | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** ** This file contains code used to incrementally generate a GZIP compressed ** file. The GZIP format is described in RFC-1952. ** ** State information is stored in static variables, so this implementation ** can only be building up a single GZIP file at a time. */ #include "config.h" #include <assert.h> #include <zlib.h> #include "gzip.h" /* ** State information for the GZIP file under construction. */ struct gzip_state { int eState; /* 0: idle 1: header 2: compressing */ |
︙ | ︙ |
Changes to src/http.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 117 118 119 120 121 122 123 | blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded); fossil_free(zEncoded); fossil_free(zCredentials); } blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); } blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload)); } | > | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded); fossil_free(zEncoded); fossil_free(zCredentials); } blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); } blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload)); } |
︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | goto write_err; } if( iHttpVersion==0 ){ closeConnection = 1; }else{ closeConnection = 0; } }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ for(i=15; fossil_isspace(zLine[i]); i++){} iLength = atoi(&zLine[i]); }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){ char c; for(i=11; fossil_isspace(zLine[i]); i++){} c = zLine[i]; | > > > > > > > > > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | goto write_err; } if( iHttpVersion==0 ){ closeConnection = 1; }else{ closeConnection = 0; } }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; if( rc!=200 && rc!=302 ){ int ii; for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} while( zLine[ii]==' ' ) ii++; fossil_warning("server says: %s", &zLine[ii]); goto write_err; } closeConnection = 0; }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ for(i=15; fossil_isspace(zLine[i]); i++){} iLength = atoi(&zLine[i]); }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){ char c; for(i=11; fossil_isspace(zLine[i]); i++){} c = zLine[i]; |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 | /* ** Close the connection to the server if appropriate. ** ** FIXME: There is some bug in the lower layers that prevents the ** connection from remaining open. The easiest fix for now is to ** simply close and restart the connection for each round-trip. */ | > > | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | /* ** Close the connection to the server if appropriate. ** ** FIXME: There is some bug in the lower layers that prevents the ** connection from remaining open. The easiest fix for now is to ** simply close and restart the connection for each round-trip. ** ** For SSH we will leave the connection open. */ if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */ if( closeConnection ){ transport_close(); }else{ transport_rewind(); } return 0; |
︙ | ︙ |
Changes to src/http_socket.c.
︙ | ︙ | |||
207 208 209 210 211 212 213 | if( got<=0 ) break; total += (size_t)got; N -= (size_t)got; pContent = (void*)&((char*)pContent)[got]; } return total; } | > > > > > > > > > > > > > > > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | if( got<=0 ) break; total += (size_t)got; N -= (size_t)got; pContent = (void*)&((char*)pContent)[got]; } return total; } /* ** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets ** populated. For hostnames with more than one IP (or if overridden in ** ~/.ssh/config) the rcvfrom may not match the host to which we connect. */ void socket_ssh_resolve_addr(void){ struct hostent *pHost; /* Used to make best effort for rcvfrom */ struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); pHost = gethostbyname(g.urlName); if( pHost!=0 ){ memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length); g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr)); } } |
Changes to src/http_transport.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | if( pnRcvd ) *pnRcvd = transport.nRcvd; if( resetFlag ){ transport.nSent = 0; transport.nRcvd = 0; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | | | | | | | > | | | | | | > > | | < < < < < < < < < < < < < < < < < < < | | | | | | > > > | | < < < < < < < < < < < | < | > > | | | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | if( pnRcvd ) *pnRcvd = transport.nRcvd; if( resetFlag ){ transport.nSent = 0; transport.nRcvd = 0; } } /* ** Default SSH command */ #ifdef __MINGW32__ static char zDefaultSshCmd[] = "ssh -T"; #else static char zDefaultSshCmd[] = "ssh -e none -T"; #endif /* ** SSH initialization of the transport layer */ int transport_ssh_open(void){ /* For SSH we need to create and run SSH fossil http ** to talk to the remote machine. */ const char *zSsh; /* The base SSH command */ Blob zCmd; /* The SSH command */ char *zHost; /* The host name to contact */ int n; /* Size of prefix string */ socket_ssh_resolve_addr(); zSsh = db_get("ssh-command", zDefaultSshCmd); blob_init(&zCmd, zSsh, -1); if( g.urlPort!=g.urlDfltPort && g.urlPort ){ #ifdef __MINGW32__ blob_appendf(&zCmd, " -P %d", g.urlPort); #else blob_appendf(&zCmd, " -p %d", g.urlPort); #endif } if( g.fSshTrace ){ fossil_force_newline(); fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */ } if( g.urlUser && g.urlUser[0] ){ zHost = mprintf("%s@%s", g.urlUser, g.urlName); }else{ zHost = mprintf("%s", g.urlName); } n = blob_size(&zCmd); blob_append(&zCmd, " ", 1); shell_escape(&zCmd, zHost); blob_append(&zCmd, " ", 1); shell_escape(&zCmd, mprintf("%s", g.urlFossil)); blob_append(&zCmd, " test-http", 10); if( g.urlPath && g.urlPath[0] ){ blob_append(&zCmd, " ", 1); shell_escape(&zCmd, mprintf("%s", g.urlPath)); } if( g.fSshTrace ){ fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */ } free(zHost); popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); if( sshPid==0 ){ socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd); } blob_reset(&zCmd); return sshPid==0; } /* ** Open a connection to the server. The server is defined by the following ** global variables: ** ** g.urlName Name of the server. Ex: www.fossil-scm.org ** g.urlPort TCP/IP port. Ex: 80 ** g.urlIsHttps Use TLS for the connection ** ** Return the number of errors. */ int transport_open(void){ int rc = 0; if( transport.isOpen==0 ){ if( g.urlIsSsh ){ rc = transport_ssh_open(); if( rc==0 ) transport.isOpen = 1; }else if( g.urlIsHttps ){ #ifdef FOSSIL_ENABLE_SSL rc = ssl_open(); if( rc==0 ) transport.isOpen = 1; #else socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); rc = 1; |
︙ | ︙ | |||
338 339 340 341 342 343 344 | transport.nUsed = 0; transport.iCursor = 0; if( transport.pLog ){ fclose(transport.pLog); transport.pLog = 0; } if( g.urlIsSsh ){ | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | transport.nUsed = 0; transport.iCursor = 0; if( transport.pLog ){ fclose(transport.pLog); transport.pLog = 0; } if( g.urlIsSsh ){ transport_ssh_close(); }else if( g.urlIsHttps ){ #ifdef FOSSIL_ENABLE_SSL ssl_close(); #endif }else if( g.urlIsFile ){ if( transport.pFile ){ fclose(transport.pFile); |
︙ | ︙ | |||
397 398 399 400 401 402 403 | } /* ** This routine is called when the outbound message is complete and ** it is time to being receiving a reply. */ void transport_flip(void){ | | < < | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | } /* ** This routine is called when the outbound message is complete and ** it is time to being receiving a reply. */ void transport_flip(void){ if( g.urlIsFile ){ char *zCmd; fclose(transport.pFile); zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth", g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile ); fossil_system(zCmd); free(zCmd); |
︙ | ︙ | |||
579 580 581 582 583 584 585 586 | } i++; } if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]); return &transport.pBuf[iStart]; } void transport_global_shutdown(void){ | > > > | < < | < > > > > > > > > > > > > | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | } i++; } if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]); return &transport.pBuf[iStart]; } /* ** Global transport shutdown */ void transport_global_shutdown(void){ if( g.urlIsSsh ){ transport_ssh_close(); } if( g.urlIsHttps ){ #ifdef FOSSIL_ENABLE_SSL ssl_global_shutdown(); #endif }else{ socket_global_shutdown(); } } /* ** Close SSH transport. */ void transport_ssh_close(void){ if( sshPid ){ /*printf("Closing SSH tunnel: ");*/ fflush(stdout); pclose2(sshIn, sshOut, sshPid); sshPid = 0; } } |
Changes to src/import.c.
︙ | ︙ | |||
417 418 419 420 421 422 423 | ){ gg.zFrom = gg.zPrevCheckin; gg.zPrevCheckin = 0; } if( gg.zFrom==0 ) return; rid = fast_uuid_to_rid(gg.zFrom); if( rid==0 ) return; | | | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | ){ gg.zFrom = gg.zPrevCheckin; gg.zPrevCheckin = 0; } if( gg.zFrom==0 ) return; rid = fast_uuid_to_rid(gg.zFrom); if( rid==0 ) return; p = manifest_get(rid, CFTYPE_MANIFEST, 0); if( p==0 ) return; manifest_file_rewind(p); while( (pOld = manifest_file_next(p, 0))!=0 ){ pNew = import_add_file(); pNew->zName = fossil_strdup(pOld->zName); pNew->isExe = pOld->zPerm && strstr(pOld->zPerm, "x")!=0; pNew->isLink = pOld->zPerm && strstr(pOld->zPerm, "l")!=0; |
︙ | ︙ |
Changes to src/info.c.
︙ | ︙ | |||
577 578 579 580 581 582 583 | if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; @ <tr><th>Received From:</th> @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> } db_finalize(&q2); } if( g.perm.Hyperlink ){ | > > > | > > > > > > > > > | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; @ <tr><th>Received From:</th> @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> } db_finalize(&q2); } if( g.perm.Hyperlink ){ char *zPJ = db_get("short-project-name", 0); Blob projName; int jj; if( zPJ==0 ) zPJ = db_get("project-name", "unnamed"); blob_zero(&projName); blob_append(&projName, zPJ, -1); blob_trim(&projName); zPJ = blob_str(&projName); for(jj=0; zPJ[jj]; jj++){ if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){ zPJ[jj] = '_'; } } @ <tr><th>Timelines:</th><td> @ %z(href("%R/timeline?f=%S",zUuid))family</a> if( zParent ){ @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> } if( !isLeaf ){ @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a> |
︙ | ︙ | |||
603 604 605 606 607 608 609 | } db_finalize(&q2); /* The Download: line */ if( g.perm.Zip ){ char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s", | | | > | 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | } db_finalize(&q2); /* The Download: line */ if( g.perm.Zip ){ char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s", zPJ, zUuid, zUuid); @ </td></tr> @ <tr><th>Downloads:</th><td> @ %z(href("%s",zUrl))Tarball</a> @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid)) @ ZIP archive</a> fossil_free(zUrl); } @ </td></tr> @ <tr><th>Other Links:</th> @ <td> @ %z(href("%R/dir?ci=%S",zUuid))files</a> @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a> @ | %z(href("%R/artifact/%S",zUuid))manifest</a> if( g.perm.Write ){ @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> } @ </td> @ </tr> blob_reset(&projName); } @ </table> }else{ style_header("Check-in Information"); login_anonymous_available(); } db_finalize(&q1); |
︙ | ︙ | |||
721 722 723 724 725 726 727 | Blob wiki; int modPending; const char *zModAction; login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(); return; } rid = name_to_rid_www("name"); | | | 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 | Blob wiki; int modPending; const char *zModAction; login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(); return; } rid = name_to_rid_www("name"); if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){ style_header("Wiki Page Information Error"); @ No such object: %h(P("name")) style_footer(); return; } if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){ if( strcmp(zModAction,"delete")==0 ){ |
︙ | ︙ | |||
832 833 834 835 836 837 838 | } return 0; } if( !is_a_version(rid) ){ webpage_error("Artifact %s is not a checkin.", P(zParam)); return 0; } | | | 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | } return 0; } if( !is_a_version(rid) ){ webpage_error("Artifact %s is not a checkin.", P(zParam)); return 0; } return manifest_get(rid, CFTYPE_MANIFEST, 0); } /* ** Output a description of a check-in */ static void checkin_description(int rid){ Stmt q; |
︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 | ManifestFile *pFile; zCI = P("ci"); if( zCI==0 ) return 0; zFilename = P("filename"); if( zFilename==0 ) return 0; cirid = name_to_rid_www("ci"); | | | 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 | ManifestFile *pFile; zCI = P("ci"); if( zCI==0 ) return 0; zFilename = P("filename"); if( zFilename==0 ) return 0; cirid = name_to_rid_www("ci"); pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0); if( pManifest==0 ) return 0; manifest_file_rewind(pManifest); while( (pFile = manifest_file_next(pManifest,0))!=0 ){ if( fossil_strcmp(zFilename, pFile->zName)==0 ){ int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid); manifest_destroy(pManifest); return rid; |
︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 | style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun", g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } | | | 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 | style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun", g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } pTktChng = manifest_get(rid, CFTYPE_TICKET, 0); if( pTktChng==0 ) fossil_redirect_home(); zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1); if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){ if( strcmp(zModAction,"delete")==0 ){ moderation_disapprove(rid); cgi_redirectf("%R/tktview/%s", zTktName); |
︙ | ︙ |
Changes to src/json_artifact.c.
︙ | ︙ | |||
190 191 192 193 194 195 196 | return NULL; } if(!eventTypeLabel){ eventTypeLabel = json_new_string("ticket"); json_gc_add("$EVENT_TYPE_LABEL(ticket)", eventTypeLabel); } | | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | return NULL; } if(!eventTypeLabel){ eventTypeLabel = json_new_string("ticket"); json_gc_add("$EVENT_TYPE_LABEL(ticket)", eventTypeLabel); } pTktChng = manifest_get(rid, CFTYPE_TICKET, 0); if( pTktChng==0 ){ g.json.resultCode = FSL_JSON_E_MANIFEST_READ_FAILED; return NULL; } pay = cson_new_object(); cson_object_set(pay, "eventType", eventTypeLabel ); cson_object_set(pay, "uuid", json_new_string(pTktChng->zTicketUuid)); |
︙ | ︙ |
Changes to src/json_branch.c.
︙ | ︙ | |||
216 217 218 219 220 221 222 | db_begin_transaction(); rootid = name_to_typed_rid(zBasis, "ci"); if( rootid==0 ){ zOpt->rcErrMsg = "Basis branch not found."; return FSL_JSON_E_RESOURCE_NOT_FOUND; } | | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | db_begin_transaction(); rootid = name_to_typed_rid(zBasis, "ci"); if( rootid==0 ){ zOpt->rcErrMsg = "Basis branch not found."; return FSL_JSON_E_RESOURCE_NOT_FOUND; } pParent = manifest_get(rootid, CFTYPE_MANIFEST, 0); if( pParent==0 ){ zOpt->rcErrMsg = "Could not read parent manifest."; return FSL_JSON_E_UNKNOWN; } /* Create a manifest for the new branch */ blob_zero(&branch); |
︙ | ︙ |
Changes to src/json_timeline.c.
︙ | ︙ | |||
630 631 632 633 634 635 636 | /* convert each row into a JSON object...*/ int rc; int const rid = db_column_int(&q,0); Manifest * pMan = NULL; cson_value * rowV; cson_object * row; /*printf("rid=%d\n",rid);*/ | | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | /* convert each row into a JSON object...*/ int rc; int const rid = db_column_int(&q,0); Manifest * pMan = NULL; cson_value * rowV; cson_object * row; /*printf("rid=%d\n",rid);*/ pMan = manifest_get(rid, CFTYPE_TICKET, 0); if(!pMan){ /* this might be an attachment? I'm seeing this with rid 15380, uuid [1292fef05f2472108]. /json/artifact/1292fef05f2472108 returns not-found, probably because we haven't added artifact/ticket yet(?). |
︙ | ︙ |
Changes to src/json_wiki.c.
︙ | ︙ | |||
80 81 82 83 84 85 86 | ** the page. ** ** The returned value, if not NULL, is-a JSON Object owned by the ** caller. If it returns NULL then it may set g.json's error state. */ cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ Manifest * pWiki = NULL; | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | ** the page. ** ** The returned value, if not NULL, is-a JSON Object owned by the ** caller. If it returns NULL then it may set g.json's error state. */ cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ Manifest * pWiki = NULL; if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){ json_set_err( FSL_JSON_E_UNKNOWN, "Error reading wiki page from manifest (rid=%d).", rid ); return NULL; }else{ unsigned int len = 0; cson_object * pay = cson_new_object(); |
︙ | ︙ | |||
526 527 528 529 530 531 532 | if(r2<0){ goto ambiguous; }else if(0==r2){ goto invalid; } zErrTag = zV1; | | | | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | if(r2<0){ goto ambiguous; }else if(0==r2){ goto invalid; } zErrTag = zV1; pW1 = manifest_get(r1, CFTYPE_WIKI, 0); if( pW1==0 ) { goto manifest; } zErrTag = zV2; pW2 = manifest_get(r2, CFTYPE_WIKI, 0); if( pW2==0 ) { goto manifest; } blob_init(&w1, pW1->zWiki, -1); blob_zero(&w2); blob_init(&w2, pW2->zWiki, -1); |
︙ | ︙ |
Changes to src/login.c.
︙ | ︙ | |||
791 792 793 794 795 796 797 | ** local login is disabled and if we are using HTTP and not HTTPS, ** then there is no need to check user credentials. ** ** This feature allows the "fossil ui" command to give the user ** full access rights without having to log in. */ zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil")); | | > | 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 | ** local login is disabled and if we are using HTTP and not HTTPS, ** then there is no need to check user credentials. ** ** This feature allows the "fossil ui" command to give the user ** full access rights without having to log in. */ zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil")); if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 || g.fSshClient & CGI_SSH_CLIENT ) && g.useLocalauth && db_get_int("localauth",0)==0 && P("HTTPS")==0 ){ uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'"); g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid); zCap = "sx"; |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
136 137 138 139 140 141 142 143 144 145 146 147 148 149 | int fSqlTrace; /* True if --sqltrace flag is present */ int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if -sqlprint flag is present */ int fQuiet; /* True if -quiet flag is present */ int fHttpTrace; /* Trace outbound HTTP requests */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fNoSync; /* Do not do an autosync ever. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ | > > | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | int fSqlTrace; /* True if --sqltrace flag is present */ int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if -sqlprint flag is present */ int fQuiet; /* True if -quiet flag is present */ int fHttpTrace; /* Trace outbound HTTP requests */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ char *zSshCmd; /* SSH command string */ int fNoSync; /* Do not do an autosync ever. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ |
︙ | ︙ | |||
177 178 179 180 181 182 183 | int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ char *urlFossil; /* The fossil query parameter on ssh: */ | < | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ char *urlFossil; /* The fossil query parameter on ssh: */ unsigned urlFlags; /* Boolean flags controlling URL processing */ const char *zLogin; /* Login name. "" if not logged in. */ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of ** SSL client identity */ int useLocalauth; /* No login required if from 127.0.0.1 */ int noPswd; /* Logged in without password (on 127.0.0.1) */ |
︙ | ︙ | |||
601 602 603 604 605 606 607 608 609 610 611 612 613 614 | const char *zChdir = find_option("chdir",0,1); g.isHTTP = 0; g.fQuiet = find_option("quiet", 0, 0)!=0; g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; g.fSqlStats = find_option("sqlstats", 0, 0)!=0; g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; g.fSshTrace = find_option("sshtrace", 0, 0)!=0; if( g.fSqlTrace ) g.fSqlStats = 1; g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; g.fHttpTrace = find_option("httptrace", 0, 0)!=0; g.zLogin = find_option("user", "U", 1); g.zSSLIdentity = find_option("ssl-identity", 0, 1); g.zErrlog = find_option("errorlog", 0, 1); if( find_option("utc",0,0) ) g.fTimeFormat = 1; | > > | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | const char *zChdir = find_option("chdir",0,1); g.isHTTP = 0; g.fQuiet = find_option("quiet", 0, 0)!=0; g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; g.fSqlStats = find_option("sqlstats", 0, 0)!=0; g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; g.fSshTrace = find_option("sshtrace", 0, 0)!=0; g.fSshClient = 0; g.zSshCmd = 0; if( g.fSqlTrace ) g.fSqlStats = 1; g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; g.fHttpTrace = find_option("httptrace", 0, 0)!=0; g.zLogin = find_option("user", "U", 1); g.zSSLIdentity = find_option("ssl-identity", 0, 1); g.zErrlog = find_option("errorlog", 0, 1); if( find_option("utc",0,0) ) g.fTimeFormat = 1; |
︙ | ︙ | |||
1312 1313 1314 1315 1316 1317 1318 | zRepo, zPathInfo, zNewScript); } } /* Find the page that the user has requested, construct and deliver that ** page. */ | > | | 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | zRepo, zPathInfo, zNewScript); } } /* Find the page that the user has requested, construct and deliver that ** page. */ if( g.zContentType && strncmp(g.zContentType, "application/x-fossil", 20)==0 ){ zPathInfo = "/xfer"; } set_base_url(0); if( zPathInfo==0 || zPathInfo[0]==0 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){ #ifdef FOSSIL_ENABLE_JSON if(g.json.isJsonMode){ |
︙ | ︙ | |||
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 | g.httpIn = fossil_fopen(g.argv[3], "rb"); g.httpOut = fossil_fopen(g.argv[4], "wb"); zIpAddr = g.argv[5]; }else{ g.httpIn = stdin; g.httpOut = stdout; zIpAddr = 0; } find_server_repository(0); g.zRepositoryName = enter_chroot_jail(g.zRepositoryName); if( useSCGI ){ cgi_handle_scgi_request(); }else{ cgi_handle_http_request(zIpAddr); } process_one_web_page(zNotFound, glob_create(zFileGlob)); } /* ** Note that the following command is used by ssh:// processing. ** ** COMMAND: test-http ** Works like the http command but gives setup permission to all users. */ void cmd_test_http(void){ Th_InitTraceLog(); login_set_capabilities("sx", 0); g.useLocalauth = 1; | > > > > > > > > > > > > > > > > > > > > > > > < > > > > > > | | > | 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 | g.httpIn = fossil_fopen(g.argv[3], "rb"); g.httpOut = fossil_fopen(g.argv[4], "wb"); zIpAddr = g.argv[5]; }else{ g.httpIn = stdin; g.httpOut = stdout; zIpAddr = 0; } if( zIpAddr==0 ){ zIpAddr = cgi_ssh_remote_addr(0); if( zIpAddr && zIpAddr[0] ){ g.fSshClient |= CGI_SSH_CLIENT; } } find_server_repository(0); g.zRepositoryName = enter_chroot_jail(g.zRepositoryName); if( useSCGI ){ cgi_handle_scgi_request(); }else if( g.fSshClient & CGI_SSH_CLIENT ){ ssh_request_loop(zIpAddr, glob_create(zFileGlob)); }else{ cgi_handle_http_request(zIpAddr); } process_one_web_page(zNotFound, glob_create(zFileGlob)); } /* ** Process all requests in a single SSH connection if possible. */ void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){ do{ cgi_handle_ssh_http_request(zIpAddr); process_one_web_page(0, FileGlob); blob_reset(&g.cgiIn); } while ( g.fSshClient & CGI_SSH_FOSSIL || g.fSshClient & CGI_SSH_COMPAT ); } /* ** Note that the following command is used by ssh:// processing. ** ** COMMAND: test-http ** Works like the http command but gives setup permission to all users. ** */ void cmd_test_http(void){ const char *zIpAddr; /* IP address of remote client */ Th_InitTraceLog(); login_set_capabilities("sx", 0); g.useLocalauth = 1; g.httpIn = stdin; g.httpOut = stdout; find_server_repository(0); g.cgiOutput = 1; g.fullHttpReply = 1; zIpAddr = cgi_ssh_remote_addr(0); if( zIpAddr && zIpAddr[0] ){ g.fSshClient |= CGI_SSH_CLIENT; ssh_request_loop(zIpAddr, 0); }else{ cgi_set_parameter("REMOTE_ADDR", "127.0.0.1"); cgi_handle_http_request(0); process_one_web_page(0, 0); } } #if !defined(_WIN32) #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__) /* ** Search for an executable on the PATH environment variable. ** Return true (1) if found and false (0) if not found. |
︙ | ︙ |
Changes to src/makemake.tcl.
︙ | ︙ | |||
500 501 502 503 504 505 506 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY | | | | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -DFOSSIL_ENABLE_SSL=1 RCC += -DFOSSIL_ENABLE_SSL=1 endif |
︙ | ︙ | |||
769 770 771 772 773 774 775 776 777 778 779 780 781 782 | writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n" writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n" } writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c" set opt $SQLITE_OPTIONS writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" set opt {} writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c" writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n" writeln "\$(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\n" | > | 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 | writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n" writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n" } writeln "\$(OBJDIR)/sqlite3.o:\t\$(SRCDIR)/sqlite3.c" set opt $SQLITE_OPTIONS append opt " -D_HAVE_SQLITE_CONFIG_H" writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" set opt {} writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c" writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n" writeln "\$(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\n" |
︙ | ︙ | |||
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 | # B = .. SRCDIR = $B\src OBJDIR = . OX = . O = .obj E = .exe # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable SSL support # FOSSIL_ENABLE_SSL = 1 !ifdef FOSSIL_ENABLE_SSL SSLINCDIR = $(B)\compat\openssl-1.0.1e\include SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !endif # zlib options | > > > | | | | | | > > > > > > > | | | | | | | | | | | | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 | # B = .. SRCDIR = $B\src OBJDIR = . OX = . O = .obj E = .exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable SSL support # FOSSIL_ENABLE_SSL = 1 !ifdef FOSSIL_ENABLE_SSL SSLINCDIR = $(B)\compat\openssl-1.0.1e\include SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !endif # zlib options ZINCDIR = $(B)\compat\zlib ZLIBDIR = $(B)\compat\zlib ZLIB = zlib.lib INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR) !ifdef FOSSIL_ENABLE_SSL INCL = $(INCL) -I$(SSLINCDIR) !endif CFLAGS = -nologo -MT -O2 LDFLAGS = /NODEFAULTLIB:msvcrt !ifdef DEBUG CFLAGS = $(CFLAGS) -Zi LDFLAGS = $(LDFLAGS) /DEBUG !endif BCC = $(CC) $(CFLAGS) TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL) RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL) LIBS = $(ZLIB) ws2_32.lib advapi32.lib LIBDIR = -LIBPATH:$(ZLIBDIR) !ifdef FOSSIL_ENABLE_JSON TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1 !endif !ifdef FOSSIL_ENABLE_SSL TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1 LIBS = $(LIBS) $(SSLLIB) LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR) !endif } regsub -all {[-]D} $SQLITE_OPTIONS {/D} MSC_SQLITE_OPTIONS set j " \\\n " writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n" writeln -nonewline "SRC = " set i 0 |
︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 | zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib cd $(OX) | | | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib cd $(OX) link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts $(OX)\linkopts: $B\win\Makefile.msc} set redir {>} foreach s [lsort [concat $src $AdditionalObj]] { writeln "\techo \$(OX)\\$s.obj $redir \$@" set redir {>>} } |
︙ | ︙ |
Changes to src/manifest.c.
︙ | ︙ | |||
953 954 955 956 957 958 959 | return 0; } /* ** Get a manifest given the rid for the control artifact. Return ** a pointer to the manifest on success or NULL if there is a failure. */ | | | | | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | return 0; } /* ** Get a manifest given the rid for the control artifact. Return ** a pointer to the manifest on success or NULL if there is a failure. */ Manifest *manifest_get(int rid, int cfType, Blob *pErr){ Blob content; Manifest *p; if( !rid ) return 0; p = manifest_cache_find(rid); if( p ){ if( cfType!=CFTYPE_ANY && cfType!=p->type ){ manifest_cache_insert(p); p = 0; } return p; } content_get(rid, &content); p = manifest_parse(&content, rid, pErr); if( p && cfType!=CFTYPE_ANY && cfType!=p->type ){ manifest_destroy(p); p = 0; } return p; } /* ** Given a checkin name, load and parse the manifest for that checkin. ** Throw a fatal error if anything goes wrong. */ Manifest *manifest_get_by_name(const char *zName, int *pRid){ int rid; Manifest *p; rid = name_to_typed_rid(zName, "ci"); if( !is_a_version(rid) ){ fossil_fatal("no such checkin: %s", zName); } if( pRid ) *pRid = rid; p = manifest_get(rid, CFTYPE_MANIFEST, 0); if( p==0 ){ fossil_fatal("cannot parse manifest for checkin: %s", zName); } return p; } /* |
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 | ** throw an error. If the baseline is a manifest, throw an ** error if throwError is true, or record that p is an orphan ** and return 1 if throwError is false. */ static int fetch_baseline(Manifest *p, int throwError){ if( p->zBaseline!=0 && p->pBaseline==0 ){ int rid = uuid_to_rid(p->zBaseline, 1); | | | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | ** throw an error. If the baseline is a manifest, throw an ** error if throwError is true, or record that p is an orphan ** and return 1 if throwError is false. */ static int fetch_baseline(Manifest *p, int throwError){ if( p->zBaseline!=0 && p->pBaseline==0 ){ int rid = uuid_to_rid(p->zBaseline, 1); p->pBaseline = manifest_get(rid, CFTYPE_MANIFEST, 0); if( p->pBaseline==0 ){ if( !throwError ){ db_multi_exec( "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)", p->rid, rid ); return 1; |
︙ | ︙ | |||
1897 1898 1899 1900 1901 1902 1903 | ); if( strlen(p->zAttachTarget)!=UUID_SIZE || !validate16(p->zAttachTarget, UUID_SIZE) ){ char *zComment; if( p->zAttachSrc && p->zAttachSrc[0] ){ zComment = mprintf( | | | | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 | ); if( strlen(p->zAttachTarget)!=UUID_SIZE || !validate16(p->zAttachTarget, UUID_SIZE) ){ char *zComment; if( p->zAttachSrc && p->zAttachSrc[0] ){ zComment = mprintf( "Add attachment [/artifact/%S|%h] to wiki page [%h]", p->zAttachSrc, p->zAttachName, p->zAttachTarget); }else{ zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]", p->zAttachName, p->zAttachTarget); } db_multi_exec( "REPLACE INTO event(type,mtime,objid,user,comment)" "VALUES('w',%.17g,%d,%Q,%Q)", p->rDate, rid, p->zUser, zComment ); free(zComment); }else{ char *zComment; if( p->zAttachSrc && p->zAttachSrc[0] ){ zComment = mprintf( "Add attachment [/artifact/%S|%h] to ticket [%S]", p->zAttachSrc, p->zAttachName, p->zAttachTarget); }else{ zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]", p->zAttachName, p->zAttachTarget); } db_multi_exec( "REPLACE INTO event(type,mtime,objid,user,comment)" |
︙ | ︙ |
Changes to src/md5.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" /* * If compiled on a machine that doesn't have a 32-bit integer, | > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include "config.h" #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" /* * If compiled on a machine that doesn't have a 32-bit integer, |
︙ | ︙ |
Changes to src/popen.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <fcntl.h> /* ** Print a fatal error and quit. */ static void win32_fatal_error(const char *zMsg){ fossil_fatal("%s", zMsg); } #endif /* ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. | > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #include <fcntl.h> /* ** Print a fatal error and quit. */ static void win32_fatal_error(const char *zMsg){ fossil_fatal("%s", zMsg); } #else #include <signal.h> #include <sys/wait.h> #endif /* ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. |
︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 | close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); *pChildPid = 0; return 1; } if( *pChildPid==0 ){ int fd; int nErr = 0; /* This is the child process */ close(0); fd = dup(pout[0]); if( fd!=0 ) nErr++; | > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); *pChildPid = 0; return 1; } signal(SIGPIPE,SIG_IGN); if( *pChildPid==0 ){ int fd; int nErr = 0; /* This is the child process */ close(0); fd = dup(pout[0]); if( fd!=0 ) nErr++; |
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 | /* Not implemented, yet */ close(fdIn); fclose(pOut); #else close(fdIn); fclose(pOut); kill(childPid, SIGINT); #endif } | > | 213 214 215 216 217 218 219 220 221 222 | /* Not implemented, yet */ close(fdIn); fclose(pOut); #else close(fdIn); fclose(pOut); kill(childPid, SIGINT); while( waitpid(0, 0, WNOHANG)>0 ) {} #endif } |
Changes to src/rebuild.c.
︙ | ︙ | |||
347 348 349 350 351 352 353 354 355 356 357 358 359 360 | zTable = db_text(0, "SELECT name FROM sqlite_master /*scan*/" " WHERE type='table'" " AND name NOT IN ('blob','delta','rcvfrom','user'," "'config','shun','private','reportfmt'," "'concealed','accesslog','modreq')" " AND name NOT GLOB 'sqlite_*'" ); if( zTable==0 ) break; db_multi_exec("DROP TABLE %Q", zTable); free(zTable); } db_multi_exec(zRepositorySchema2); ticket_create_table(0); | > | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | zTable = db_text(0, "SELECT name FROM sqlite_master /*scan*/" " WHERE type='table'" " AND name NOT IN ('blob','delta','rcvfrom','user'," "'config','shun','private','reportfmt'," "'concealed','accesslog','modreq')" " AND name NOT GLOB 'sqlite_*'" " AND name NOT GLOB 'fx_*'" ); if( zTable==0 ) break; db_multi_exec("DROP TABLE %Q", zTable); free(zTable); } db_multi_exec(zRepositorySchema2); ticket_create_table(0); |
︙ | ︙ | |||
719 720 721 722 723 724 725 | db_finalize(&q); while( bag_count(&pending)>0 ){ Manifest *p; int rid = bag_first(&pending); int i; bag_remove(&pending, rid); | | | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 | db_finalize(&q); while( bag_count(&pending)>0 ){ Manifest *p; int rid = bag_first(&pending); int i; bag_remove(&pending, rid); p = manifest_get(rid, CFTYPE_CLUSTER, 0); if( p==0 ){ fossil_fatal("bad cluster: rid=%d", rid); } for(i=0; i<p->nCChild; i++){ const char *zUuid = p->azCChild[i]; int crid = name_to_rid(zUuid); if( crid==0 ){ |
︙ | ︙ |
Changes to src/search.c.
︙ | ︙ | |||
187 188 189 190 191 192 193 | Blob sql = empty_blob; Stmt q; int iBest; char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop off the end of the results. */ char const * zLimit = find_option("limit","n",1); | | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | Blob sql = empty_blob; Stmt q; int iBest; char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop off the end of the results. */ char const * zLimit = find_option("limit","n",1); int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching lines/entries to list */ db_must_be_within_tree(); if( g.argc<2 ) return; blob_init(&pattern, g.argv[2], -1); for(i=3; i<g.argc; i++){ blob_appendf(&pattern, " %s", g.argv[i]); } |
︙ | ︙ | |||
218 219 220 221 222 223 224 | blob_append(&sql, "SELECT rid, uuid, date, comment, 0, 0 FROM srch " "WHERE 1 ", -1); if(!fAll){ blob_appendf(&sql,"AND x>%d ", iBest/3); } blob_append(&sql, "ORDER BY x DESC, date DESC ", -1); | < < < | | 218 219 220 221 222 223 224 225 226 227 228 229 | blob_append(&sql, "SELECT rid, uuid, date, comment, 0, 0 FROM srch " "WHERE 1 ", -1); if(!fAll){ blob_appendf(&sql,"AND x>%d ", iBest/3); } blob_append(&sql, "ORDER BY x DESC, date DESC ", -1); db_prepare(&q, blob_str(&sql)); blob_reset(&sql); print_timeline(&q, nLimit, 79, 0); db_finalize(&q); } |
Changes to src/setup.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Implementation of the Setup page */ | < > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Implementation of the Setup page */ #include "config.h" #include <assert.h> #include "setup.h" /* ** The table of web pages supported by this application is generated ** automatically by the "mkindex" program and written into a file ** named "page_index.h". We include that file here to get access ** to the table. |
︙ | ︙ | |||
725 726 727 728 729 730 731 | @ <li><p> @ No login is required for user <span class="usertype">nobody</span>. The @ capabilities of the <span class="usertype">nobody</span> user are @ inherited by all users, regardless of whether or not they are logged in. @ To disable universal access to the repository, make sure no user named @ <span class="usertype">nobody</span> exists or that the @ <span class="usertype">nobody</span> user has no capabilities | | | 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | @ <li><p> @ No login is required for user <span class="usertype">nobody</span>. The @ capabilities of the <span class="usertype">nobody</span> user are @ inherited by all users, regardless of whether or not they are logged in. @ To disable universal access to the repository, make sure no user named @ <span class="usertype">nobody</span> exists or that the @ <span class="usertype">nobody</span> user has no capabilities @ enabled. The password for <span class="usertype">nobody</span> is ignored. @ To avoid problems with spiders overloading the server, it is recommended @ that the <span class="capability">h</span> (Hyperlinks) capability be @ turned off for the <span class="usertype">nobody</span> user. @ </p></li> @ @ <li><p> @ Login is required for user <span class="usertype">anonymous</span> but the |
︙ | ︙ | |||
847 848 849 850 851 852 853 854 855 856 857 858 859 860 | } @ cols="%d(cols)">%h(z)</textarea> if( zLabel && *zLabel ){ @ <span class="textareaLabel">%s(zLabel)</span> } } } /* ** WEBPAGE: setup_access */ void setup_access(void){ login_check_credentials(); | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | } @ cols="%d(cols)">%h(z)</textarea> if( zLabel && *zLabel ){ @ <span class="textareaLabel">%s(zLabel)</span> } } } /* ** Generate a text box for an attribute. */ static void multiple_choice_attribute( const char *zLabel, /* The text label on the menu */ const char *zVar, /* The corresponding row in the VAR table */ const char *zQP, /* The query parameter */ const char *zDflt, /* Default value if VAR table entry does not exist */ int nChoice, /* Number of choices */ const char **azChoice /* Choices. 2 per choice: (VAR value, Display) */ ){ const char *z = db_get(zVar, (char*)zDflt); const char *zQ = P(zQP); int i; if( zQ && fossil_strcmp(zQ,z)!=0){ login_verify_csrf_secret(); db_set(zVar, zQ, 0); z = zQ; } @ <select size="1" name="%s(zQP)" id="id%s(zQP)"> for(i=0; i<nChoice*2; i+=2){ const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : ""; @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option> } @ </select> } /* ** WEBPAGE: setup_access */ void setup_access(void){ login_check_credentials(); |
︙ | ︙ | |||
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | /* ** WEBPAGE: setup_timeline */ void setup_timeline(void){ double tmDiff; char zTmDiff[20]; login_check_credentials(); if( !g.perm.Setup ){ login_needed(); } style_header("Timeline Display Preferences"); db_begin_transaction(); | > > > > > > | 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 | /* ** WEBPAGE: setup_timeline */ void setup_timeline(void){ double tmDiff; char zTmDiff[20]; static const char *azTimeFormats[] = { "0", "HH:MM", "1", "HH:MM:SS", "2", "YYYY-MM-DD HH:MM", "3", "YYMMDD HH:MM" }; login_check_credentials(); if( !g.perm.Setup ){ login_needed(); } style_header("Timeline Display Preferences"); db_begin_transaction(); |
︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 | }else if( tmDiff<0.0 ){ sqlite3_snprintf(sizeof(zTmDiff), zTmDiff, "%.1f", -tmDiff); @ %s(zTmDiff) hours behind UTC.</p> }else{ @ %s(zTmDiff) hours ahead of UTC.</p> } @ <hr /> onoff_attribute("Show version differences by default", "show-version-diffs", "vdiff", 0, 0); @ <p>On the version-information pages linked from the timeline can either @ show complete diffs of all file changes, or can just list the names of @ the files that have changed. Users can get to either page by @ clicking. This setting selects the default.</p> | > > > > > > > > | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | }else if( tmDiff<0.0 ){ sqlite3_snprintf(sizeof(zTmDiff), zTmDiff, "%.1f", -tmDiff); @ %s(zTmDiff) hours behind UTC.</p> }else{ @ %s(zTmDiff) hours ahead of UTC.</p> } @ <hr /> multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", "tdf", "0", 4, azTimeFormats); @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown @ in a separate box (using CSS class "timelineDate") whenever the date changes. @ With the "YYYY-MM-DD HH:MM" and "YYMMDD ..." formats, the complete date @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p> @ <hr /> onoff_attribute("Show version differences by default", "show-version-diffs", "vdiff", 0, 0); @ <p>On the version-information pages linked from the timeline can either @ show complete diffs of all file changes, or can just list the names of @ the files that have changed. Users can get to either page by @ clicking. This setting selects the default.</p> |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | style_header("WWW Configuration"); db_begin_transaction(); @ <form action="%s(g.zTop)/setup_config" method="post"><div> login_insert_csrf_secret(); @ <hr /> entry_attribute("Project Name", 60, "project-name", "pn", "", 0); @ <p>Give your project a name so visitors know what this site is about. | | > > > > > > > > | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 | style_header("WWW Configuration"); db_begin_transaction(); @ <form action="%s(g.zTop)/setup_config" method="post"><div> login_insert_csrf_secret(); @ <hr /> entry_attribute("Project Name", 60, "project-name", "pn", "", 0); @ <p>Give your project a name so visitors know what this site is about. @ The project name will also be used as the RSS feed title. @ </p> @ <hr /> textarea_attribute("Project Description", 3, 80, "project-description", "pd", "", 0); @ <p>Describe your project. This will be used in page headers for search @ engines as well as a short RSS description.</p> @ <hr /> entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name", "spn", "", 0); @ <p>This is used as a prefix on the names of generated tarballs and ZIP archive. @ For best results, keep this prefix brief and avoid special characters such @ as "/" and "\". @ If no tarball prefix is specified, then the full Project Name above is used. @ </p> @ <hr /> onoff_attribute("Enable WYSIWYG Wiki Editing", "wysiwyg-wiki", "wysiwyg-wiki", 0, 0); @ <p>Enable what-you-see-is-what-you-get (WYSIWYG) editing of wiki pages. @ The WYSIWYG editor generates HTML instead of markup, which makes @ subsequent manual editing more difficult.</p> @ <hr /> |
︙ | ︙ | |||
1486 1487 1488 1489 1490 1491 1492 | onoff_attribute("Moderate ticket changes", "modreq-tkt", "modreq-tkt", 0, 0); @ <p>When enabled, any change to tickets is subject to the approval @ a ticket moderator - a user with the "q" or Mod-Tkt privilege. @ Ticket changes enter the system and are shown locally, but are not @ synced until they are approved. The moderator has the option to @ delete the change rather than approve it. Ticket changes made by | | | 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | onoff_attribute("Moderate ticket changes", "modreq-tkt", "modreq-tkt", 0, 0); @ <p>When enabled, any change to tickets is subject to the approval @ a ticket moderator - a user with the "q" or Mod-Tkt privilege. @ Ticket changes enter the system and are shown locally, but are not @ synced until they are approved. The moderator has the option to @ delete the change rather than approve it. Ticket changes made by @ a user who has the Mod-Tkt privilege are never subject to @ moderation. @ @ <hr /> onoff_attribute("Moderate wiki changes", "modreq-wiki", "modreq-wiki", 0, 0); @ <p>When enabled, any change to wiki is subject to the approval @ a ticket moderator - a user with the "l" or Mod-Wiki privilege. |
︙ | ︙ |
Changes to src/sha1.c.
1 2 3 | /* ** This implementation of SHA1. */ | < > | 1 2 3 4 5 6 7 8 9 10 11 12 | /* ** This implementation of SHA1. */ #include "config.h" #include <sys/types.h> #include "sha1.h" /* ** The SHA1 implementation below is adapted from: ** ** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $ |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
970 971 972 973 974 975 976 | int rc; int nResult; int i; const char *z; rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); | | | 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 | int rc; int nResult; int i; const char *z; rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0); if( rc!=SQLITE_OK || !pSelect ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; return rc; } rc = sqlite3_step(pSelect); nResult = sqlite3_column_count(pSelect); while( rc==SQLITE_ROW ){ if( zFirstRow ){ fprintf(p->out, "%s", zFirstRow); |
︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 | fprintf(p->out, ";\n"); } rc = sqlite3_step(pSelect); } rc = sqlite3_finalize(pSelect); if( rc!=SQLITE_OK ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | fprintf(p->out, ";\n"); } rc = sqlite3_step(pSelect); } rc = sqlite3_finalize(pSelect); if( rc!=SQLITE_OK ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++; } return rc; } /* ** Allocate space and save off current error string. */ |
︙ | ︙ | |||
1200 1201 1202 1203 1204 1205 1206 | for(i=0; i<nCol; i++){ azCols[i] = (char *)sqlite3_column_name(pStmt, i); } do{ /* extract the data and data types */ for(i=0; i<nCol; i++){ aiTypes[i] = x = sqlite3_column_type(pStmt, i); | | | 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 | for(i=0; i<nCol; i++){ azCols[i] = (char *)sqlite3_column_name(pStmt, i); } do{ /* extract the data and data types */ for(i=0; i<nCol; i++){ aiTypes[i] = x = sqlite3_column_type(pStmt, i); if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){ azVals[i] = ""; }else{ azVals[i] = (char*)sqlite3_column_text(pStmt, i); } if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ rc = SQLITE_NOMEM; break; /* from for */ |
︙ | ︙ |
Changes to src/skins.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Implementation of the Setup page for "skins". */ | < > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Implementation of the Setup page for "skins". */ #include "config.h" #include <assert.h> #include "skins.h" /* @-comment: ## */ /* ** A black-and-white theme with the project title in a bar across the top ** and no logo image. */ |
︙ | ︙ |
Changes to src/sqlite3.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif #ifndef SQLITE_API # define SQLITE_API #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif #ifndef SQLITE_API # define SQLITE_API #endif /************** Begin file sqlite3.h *****************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** |
︙ | ︙ | |||
654 655 656 657 658 659 660 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.1" #define SQLITE_VERSION_NUMBER 3008001 | | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.1" #define SQLITE_VERSION_NUMBER 3008001 #define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
2162 2163 2164 2165 2166 2167 2168 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI | | | | | | | | | | 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(This option takes a single argument of type int. If non-zero, then ** URI handling is globally enabled. If the parameter is zero, then URI handling ** is globally disabled.)^ ^If URI handling is globally enabled, all filenames ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined.)^ ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd>^This option takes a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. ^The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. |
︙ | ︙ | |||
2211 2212 2213 2214 2215 2216 2217 | ** the connection being passed as the second parameter is being closed. The ** third parameter is passed NULL In this case. An example of using this ** configuration option can be seen in the "test_sqllog.c" source file in ** the canonical SQLite source tree.</dd> ** ** [[SQLITE_CONFIG_MMAP_SIZE]] ** <dt>SQLITE_CONFIG_MMAP_SIZE | | | | | | | 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 | ** the connection being passed as the second parameter is being closed. The ** third parameter is passed NULL In this case. An example of using this ** configuration option can be seen in the "test_sqllog.c" source file in ** the canonical SQLite source tree.</dd> ** ** [[SQLITE_CONFIG_MMAP_SIZE]] ** <dt>SQLITE_CONFIG_MMAP_SIZE ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values ** that are the default mmap size limit (the default setting for ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. ** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size ** cannot be changed at run-time. Nor may the maximum allowed mmap size ** exceed the compile-time maximum mmap size set by the ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ |
︙ | ︙ | |||
7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 | } /* end of the 'extern "C"' block */ #endif #endif /* ifndef _SQLITE3RTREE_H_ */ /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include hash.h in the middle of sqliteInt.h ******************/ /************** Begin file hash.h ********************************************/ /* ** 2001 September 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 | } /* end of the 'extern "C"' block */ #endif #endif /* ifndef _SQLITE3RTREE_H_ */ /************** End of sqlite3.h *********************************************/ /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any ** system #includes. Hence, this block of code must be the very first ** code in all source files. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: Red Hat 7.2) but you want your code to work ** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in Red Hat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. ** ** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #ifdef _HAVE_SQLITE_CONFIG_H #include "config.h" #endif /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ /************** Begin file sqliteLimit.h *************************************/ /* ** 2007 May 7 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. */ /* ** The maximum length of a TEXT or BLOB in bytes. This also ** limits the size of a row in a table or index. ** ** The hard limit is the ability of a 32-bit signed integer ** to count the size: 2^31-1 or 2147483647. */ #ifndef SQLITE_MAX_LENGTH # define SQLITE_MAX_LENGTH 1000000000 #endif /* ** This is the maximum number of ** ** * Columns in a table ** * Columns in an index ** * Columns in a view ** * Terms in the SET clause of an UPDATE statement ** * Terms in the result set of a SELECT statement ** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. ** * Terms in the VALUES clause of an INSERT statement ** ** The hard upper limit here is 32676. Most database people will ** tell you that in a well-normalized database, you usually should ** not have more than a dozen or so columns in any table. And if ** that is the case, there is no point in having more than a few ** dozen values in any of the other situations described above. */ #ifndef SQLITE_MAX_COLUMN # define SQLITE_MAX_COLUMN 2000 #endif /* ** The maximum length of a single SQL statement in bytes. ** ** It used to be the case that setting this value to zero would ** turn the limit off. That is no longer true. It is not possible ** to turn this limit off. */ #ifndef SQLITE_MAX_SQL_LENGTH # define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* ** The maximum depth of an expression tree. This is limited to ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might ** want to place more severe limits on the complexity of an ** expression. ** ** A value of 0 used to mean that the limit was not enforced. ** But that is no longer true. The limit is now strictly enforced ** at all times. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 #endif /* ** The maximum number of terms in a compound SELECT statement. ** The code generator for compound SELECT statements does one ** level of recursion for each term. A stack overflow can result ** if the number of terms is too large. In practice, most SQL ** never has more than 3 or 4 terms. Use a value of 0 to disable ** any limit on the number of terms in a compount SELECT. */ #ifndef SQLITE_MAX_COMPOUND_SELECT # define SQLITE_MAX_COMPOUND_SELECT 500 #endif /* ** The maximum number of opcodes in a VDBE program. ** Not currently enforced. */ #ifndef SQLITE_MAX_VDBE_OP # define SQLITE_MAX_VDBE_OP 25000 #endif /* ** The maximum number of arguments to an SQL function. */ #ifndef SQLITE_MAX_FUNCTION_ARG # define SQLITE_MAX_FUNCTION_ARG 127 #endif /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE */ #ifndef SQLITE_DEFAULT_CACHE_SIZE # define SQLITE_DEFAULT_CACHE_SIZE 2000 #endif #ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE # define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 #endif /* ** The default number of frames to accumulate in the log file before ** checkpointing the database in WAL mode. */ #ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT # define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 #endif /* ** The maximum number of attached databases. This must be between 0 ** and 62. The upper bound on 62 is because a 64-bit integer bitmap ** is used internally to track attached databases. */ #ifndef SQLITE_MAX_ATTACHED # define SQLITE_MAX_ATTACHED 10 #endif /* ** The maximum value of a ?nnn wildcard that the parser will accept. */ #ifndef SQLITE_MAX_VARIABLE_NUMBER # define SQLITE_MAX_VARIABLE_NUMBER 999 #endif /* Maximum page size. The upper bound on this value is 65536. This a limit ** imposed by the use of 16-bit offsets within each page. ** ** Earlier versions of SQLite allowed the user to change this value at ** compile time. This is no longer permitted, on the grounds that it creates ** a library that is technically incompatible with an SQLite library ** compiled with a different limit. If a process operating on a database ** with a page-size of 65536 bytes crashes, then an instance of SQLite ** compiled with the default page-size limit will not be able to rollback ** the aborted transaction. This could lead to database corruption. */ #ifdef SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_PAGE_SIZE #endif #define SQLITE_MAX_PAGE_SIZE 65536 /* ** The default size of a database page. */ #ifndef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE 1024 #endif #if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE # undef SQLITE_DEFAULT_PAGE_SIZE # define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE #endif /* ** Ordinarily, if no value is explicitly provided, SQLite creates databases ** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain ** device characteristics (sector-size and atomic write() support), ** SQLite may choose a larger value. This constant is the maximum value ** SQLite will choose on its own. */ #ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE # define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 #endif #if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE # undef SQLITE_MAX_DEFAULT_PAGE_SIZE # define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE #endif /* ** Maximum number of pages in one database file. ** ** This is really just the default value for the max_page_count pragma. ** This value can be lowered (or raised) at run-time using that the ** max_page_count macro. */ #ifndef SQLITE_MAX_PAGE_COUNT # define SQLITE_MAX_PAGE_COUNT 1073741823 #endif /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH # define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 #endif /* ** Maximum depth of recursion for triggers. ** ** A value of 1 means that a trigger program will not be able to itself ** fire any triggers. A value of 0 means that no trigger programs at all ** may be executed. */ #ifndef SQLITE_MAX_TRIGGER_DEPTH # define SQLITE_MAX_TRIGGER_DEPTH 1000 #endif /************** End of sqliteLimit.h *****************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /* Disable nuisance warnings on Borland compilers */ #if defined(__BORLANDC__) #pragma warn -rch /* unreachable code */ #pragma warn -ccc /* Condition is always true or false */ #pragma warn -aus /* Assigned value is never used */ #pragma warn -csu /* Comparing signed and unsigned */ #pragma warn -spa /* Suspicious pointer arithmetic */ #endif /* Needed for various definitions... */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #if defined(__OpenBSD__) && !defined(_BSD_SOURCE) # define _BSD_SOURCE #endif /* ** Include standard header files as necessary */ #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif /* ** The following macros are used to cast pointers to integers and ** integers to pointers. The way you do this varies from one compiler ** to the next, so we have developed the following set of #if statements ** to generate appropriate macros for a wide range of compilers. ** ** The correct "ANSI" way to do this is to use the intptr_t type. ** Unfortunately, that typedef is not available on all compilers, or ** if it is available, it requires an #include of specific headers ** that vary from one machine to the next. ** ** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on ** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). ** So we have to define the macros in different ways depending on the ** compiler. */ #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ # define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) #elif !defined(__GNUC__) /* Works for compilers other than LLVM */ # define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ # define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never ** threadsafe. 1 means the library is serialized which is the highest ** level of threadsafety. 2 means the library is multithreaded - multiple ** threads can use SQLite as long as no two threads try to use the same ** database connection at the same time. ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. */ #if !defined(SQLITE_THREADSAFE) # if defined(THREADSAFE) # define SQLITE_THREADSAFE THREADSAFE # else # define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ # endif #endif /* ** Powersafe overwrite is on by default. But can be turned off using ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. */ #ifndef SQLITE_POWERSAFE_OVERWRITE # define SQLITE_POWERSAFE_OVERWRITE 1 #endif /* ** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. ** It determines whether or not the features related to ** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can ** be overridden at runtime using the sqlite3_config() API. */ #if !defined(SQLITE_DEFAULT_MEMSTATUS) # define SQLITE_DEFAULT_MEMSTATUS 1 #endif /* ** Exactly one of the following macros must be defined in order to ** specify which memory allocation subsystem to use. ** ** SQLITE_SYSTEM_MALLOC // Use normal system malloc() ** SQLITE_WIN32_MALLOC // Use Win32 native heap API ** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails ** SQLITE_MEMDEBUG // Debugging version of system malloc() ** ** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the ** assert() macro is enabled, each call into the Win32 native heap subsystem ** will cause HeapValidate to be called. If heap validation should fail, an ** assertion will be triggered. ** ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as ** the default. */ #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)>1 # error "Two or more of the following compile-time configuration options\ are defined but at most one is allowed:\ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\ SQLITE_ZERO_MALLOC" #endif #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ #if !defined(SQLITE_MALLOC_SOFT_LIMIT) # define SQLITE_MALLOC_SOFT_LIMIT 1024 #endif /* ** We need to define _XOPEN_SOURCE as follows in order to enable ** recursive mutexes on most Unix systems and fchmod() on OpenBSD. ** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit ** it. */ #if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) # define _XOPEN_SOURCE 600 #endif /* ** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that ** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, ** make it true by defining or undefining NDEBUG. ** ** Setting NDEBUG makes the code smaller and faster by disabling the ** assert() statements in the code. So we want the default action ** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG ** is set. Thus NDEBUG becomes an opt-in rather than an opt-out ** feature. */ #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) # undef NDEBUG #endif /* ** The testcase() macro is used to aid in coverage testing. When ** doing coverage testing, the condition inside the argument to ** testcase() must be evaluated both true and false in order to ** get full branch coverage. The testcase() macro is inserted ** to help ensure adequate test coverage in places where simple ** condition/decision coverage is inadequate. For example, testcase() ** can be used to make sure boundary values are tested. For ** bitmask tests, testcase() can be used to make sure each bit ** is significant and used at least once. On switch statements ** where multiple cases go to the same block of code, testcase() ** can insure that all cases are evaluated. ** */ #ifdef SQLITE_COVERAGE_TEST SQLITE_PRIVATE void sqlite3Coverage(int); # define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } #else # define testcase(X) #endif /* ** The TESTONLY macro is used to enclose variable declarations or ** other bits of code that are needed to support the arguments ** within testcase() and assert() macros. */ #if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) # define TESTONLY(X) X #else # define TESTONLY(X) #endif /* ** Sometimes we need a small amount of code such as a variable initialization ** to setup for a later assert() statement. We do not want this code to ** appear when assert() is disabled. The following macro is therefore ** used to contain that setup code. The "VVA" acronym stands for ** "Verification, Validation, and Accreditation". In other words, the ** code within VVA_ONLY() will only run during verification processes. */ #ifndef NDEBUG # define VVA_ONLY(X) X #else # define VVA_ONLY(X) #endif /* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience ** of SQLite to unexpected behavior - to make the code "self-healing" ** or "ductile" rather than being "brittle" and crashing at the first ** hint of unplanned behavior. ** ** In other words, ALWAYS and NEVER are added for defensive code. ** ** When doing coverage testing ALWAYS and NEVER are hard-coded to ** be true and false so that the unreachable code they specify will ** not be counted as untested code. */ #if defined(SQLITE_COVERAGE_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif /* ** Return true (non-zero) if the input is a integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() ** macros to verify that we have tested SQLite for large-file support. */ #define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds ** a boolean expression that is usually true. These hints could, ** in theory, be used by the compiler to generate better code, but ** currently they are just comments for human readers. */ #define likely(X) (X) #define unlikely(X) (X) /************** Include hash.h in the middle of sqliteInt.h ******************/ /************** Begin file hash.h ********************************************/ /* ** 2001 September 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: |
︙ | ︙ | |||
8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 | */ #ifdef SQLITE_64BIT_STATS typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ #else typedef u32 tRowcnt; /* 32-bit is the default */ #endif /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ #ifdef SQLITE_AMALGAMATION SQLITE_PRIVATE const int sqlite3one = 1; #else | > > > > > > > > > > > > > > > > > > > > > > > > > | 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 | */ #ifdef SQLITE_64BIT_STATS typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ #else typedef u32 tRowcnt; /* 32-bit is the default */ #endif /* ** Estimated quantities used for query planning are stored as 16-bit ** logarithms. For quantity X, the value stored is 10*log2(X). This ** gives a possible range of values of approximately 1.0e986 to 1e-986. ** But the allowed values are "grainy". Not every value is representable. ** For example, quantities 16 and 17 are both represented by a LogEst ** of 40. However, since LogEst quantatites are suppose to be estimates, ** not exact values, this imprecision is not a problem. ** ** "LogEst" is short for "Logarithimic Estimate". ** ** Examples: ** 1 -> 0 20 -> 43 10000 -> 132 ** 2 -> 10 25 -> 46 25000 -> 146 ** 3 -> 16 100 -> 66 1000000 -> 199 ** 4 -> 20 1000 -> 99 1048576 -> 200 ** 10 -> 33 1024 -> 100 4294967296 -> 320 ** ** The LogEst can be negative to indicate fractional values. ** Examples: ** ** 0.5 -> -10 0.1 -> -33 0.0625 -> -40 */ typedef INT16_TYPE LogEst; /* ** Macros to determine whether the machine is big or little endian, ** evaluated at runtime. */ #ifdef SQLITE_AMALGAMATION SQLITE_PRIVATE const int sqlite3one = 1; #else |
︙ | ︙ | |||
10417 10418 10419 10420 10421 10422 10423 | char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ | > | | 10440 10441 10442 10443 10444 10445 10446 10447 10448 10449 10450 10451 10452 10453 10454 10455 | char *zName; /* Name of this column */ Expr *pDflt; /* Default value of this column */ char *zDflt; /* Original text of the default value */ char *zType; /* Data type for this column */ char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of this column. INT==1 */ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.colFlags: */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ |
︙ | ︙ | |||
10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594 | ExprList *pCheck; /* All CHECK constraints */ #endif tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ int tnum; /* Root BTree node for this table (see note above) */ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nModuleArg; /* Number of arguments to the module */ | > | 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 | ExprList *pCheck; /* All CHECK constraints */ #endif tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ int tnum; /* Root BTree node for this table (see note above) */ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nModuleArg; /* Number of arguments to the module */ |
︙ | ︙ | |||
10692 10693 10694 10695 10696 10697 10698 | #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ #define OE_SetNull 7 /* Set the foreign key value to NULL */ #define OE_SetDflt 8 /* Set the foreign key value to its default */ #define OE_Cascade 9 /* Cascade the changes */ | | | 10717 10718 10719 10720 10721 10722 10723 10724 10725 10726 10727 10728 10729 10730 10731 | #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ #define OE_SetNull 7 /* Set the foreign key value to NULL */ #define OE_SetDflt 8 /* Set the foreign key value to its default */ #define OE_Cascade 9 /* Cascade the changes */ #define OE_Default 10 /* Do whatever the default action is */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** |
︙ | ︙ | |||
10779 10780 10781 10782 10783 10784 10785 10786 10787 10788 10789 10790 10791 10792 | char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ Expr *pPartIdxWhere; /* WHERE clause for partial indices */ int tnum; /* DB Page containing root of this index */ u16 nColumn; /* Number of columns in table used by this index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ | > | 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 | char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ Expr *pPartIdxWhere; /* WHERE clause for partial indices */ int tnum; /* DB Page containing root of this index */ LogEst szIdxRow; /* Estimated average row size in bytes */ u16 nColumn; /* Number of columns in table used by this index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ |
︙ | ︙ | |||
11634 11635 11636 11637 11638 11639 11640 11641 11642 11643 11644 11645 11646 11647 | ** routines as they walk the parse tree to make database references ** explicit. */ typedef struct DbFixer DbFixer; struct DbFixer { Parse *pParse; /* The parsing context. Error messages written here */ Schema *pSchema; /* Fix items to this schema */ const char *zDb; /* Make sure all objects are contained in this database */ const char *zType; /* Type of the container - used for error messages */ const Token *pName; /* Name of the container - used for error messages */ }; /* ** An objected used to accumulate the text of a string where we | > | 11660 11661 11662 11663 11664 11665 11666 11667 11668 11669 11670 11671 11672 11673 11674 | ** routines as they walk the parse tree to make database references ** explicit. */ typedef struct DbFixer DbFixer; struct DbFixer { Parse *pParse; /* The parsing context. Error messages written here */ Schema *pSchema; /* Fix items to this schema */ int bVarOnly; /* Check for variable references only */ const char *zDb; /* Make sure all objects are contained in this database */ const char *zType; /* Type of the container - used for error messages */ const Token *pName; /* Name of the container - used for error messages */ }; /* ** An objected used to accumulate the text of a string where we |
︙ | ︙ | |||
12172 12173 12174 12175 12176 12177 12178 | # define sqlite3AuthRead(a,b,c,d) # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK # define sqlite3AuthContextPush(a,b,c) # define sqlite3AuthContextPop(a) ((void)(a)) #endif SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); | | > > > > > > | 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224 12225 12226 12227 12228 12229 12230 | # define sqlite3AuthRead(a,b,c,d) # define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK # define sqlite3AuthContextPush(a,b,c) # define sqlite3AuthContextPop(a) ((void)(a)) #endif SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*); SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*); SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*); SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*); SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*); SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); SQLITE_PRIVATE int sqlite3Atoi(const char*); SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); #ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); #endif SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c ** file. Code should use the MACRO forms below, as the Varint32 versions ** are coded to assume the single byte case is already handled (which ** the MACRO form does). |
︙ | ︙ | |||
12300 12301 12302 12303 12304 12305 12306 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); | | | 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); |
︙ | ︙ | |||
12433 12434 12435 12436 12437 12438 12439 | SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*); SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); #else #define sqlite3FkActions(a,b,c,d,e,f) | | | | | 12466 12467 12468 12469 12470 12471 12472 12473 12474 12475 12476 12477 12478 12479 12480 12481 12482 12483 | SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*); SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); #else #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d,e,f) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); #else #define sqlite3FkDelete(a,b) #define sqlite3FkLocateIndex(a,b,c,d,e) |
︙ | ︙ | |||
14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406 14407 14408 | ** The following routine implements the rough equivalent of localtime_r() ** using whatever operating-system specific localtime facility that ** is available. This routine returns 0 on success and ** non-zero on any kind of error. ** ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this ** routine will always fail. */ static int osLocaltime(time_t *t, struct tm *pTm){ int rc; #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \ && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S) struct tm *pX; #if SQLITE_THREADSAFE>0 | > > > > | 14428 14429 14430 14431 14432 14433 14434 14435 14436 14437 14438 14439 14440 14441 14442 14443 14444 14445 | ** The following routine implements the rough equivalent of localtime_r() ** using whatever operating-system specific localtime facility that ** is available. This routine returns 0 on success and ** non-zero on any kind of error. ** ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this ** routine will always fail. ** ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C ** library function localtime_r() is used to assist in the calculation of ** local time. */ static int osLocaltime(time_t *t, struct tm *pTm){ int rc; #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \ && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S) struct tm *pX; #if SQLITE_THREADSAFE>0 |
︙ | ︙ | |||
14451 14452 14453 14454 14455 14456 14457 14458 14459 14460 14461 14462 14463 14464 | /* Initialize the contents of sLocal to avoid a compiler warning. */ memset(&sLocal, 0, sizeof(sLocal)); x = *p; computeYMD_HMS(&x); if( x.Y<1971 || x.Y>=2038 ){ x.Y = 2000; x.M = 1; x.D = 1; x.h = 0; x.m = 0; x.s = 0.0; } else { | > > > > > | 14488 14489 14490 14491 14492 14493 14494 14495 14496 14497 14498 14499 14500 14501 14502 14503 14504 14505 14506 | /* Initialize the contents of sLocal to avoid a compiler warning. */ memset(&sLocal, 0, sizeof(sLocal)); x = *p; computeYMD_HMS(&x); if( x.Y<1971 || x.Y>=2038 ){ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only ** works for years between 1970 and 2037. For dates outside this range, ** SQLite attempts to map the year into an equivalent year within this ** range, do the calculation, then map the year back. */ x.Y = 2000; x.M = 1; x.D = 1; x.h = 0; x.m = 0; x.s = 0.0; } else { |
︙ | ︙ | |||
22385 22386 22387 22388 22389 22390 22391 22392 22393 22394 22395 22396 22397 22398 | int i, sz; sz = sqlite3Strlen30(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); } } #endif /************** End of util.c ************************************************/ /************** Begin file hash.c ********************************************/ /* ** 2001 September 22 ** ** The author disclaims copyright to this source code. In place of | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 22427 22428 22429 22430 22431 22432 22433 22434 22435 22436 22437 22438 22439 22440 22441 22442 22443 22444 22445 22446 22447 22448 22449 22450 22451 22452 22453 22454 22455 22456 22457 22458 22459 22460 22461 22462 22463 22464 22465 22466 22467 22468 22469 22470 22471 22472 22473 22474 22475 22476 22477 22478 22479 22480 22481 22482 22483 22484 22485 22486 22487 22488 22489 22490 22491 22492 22493 22494 22495 22496 22497 22498 22499 22500 22501 22502 22503 22504 22505 22506 22507 22508 22509 22510 22511 22512 22513 22514 22515 22516 22517 | int i, sz; sz = sqlite3Strlen30(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); } } #endif /* ** Find (an approximate) sum of two LogEst values. This computation is ** not a simple "+" operator because LogEst is stored as a logarithmic ** value. ** */ SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ static const unsigned char x[] = { 10, 10, /* 0,1 */ 9, 9, /* 2,3 */ 8, 8, /* 4,5 */ 7, 7, 7, /* 6,7,8 */ 6, 6, 6, /* 9,10,11 */ 5, 5, 5, /* 12-14 */ 4, 4, 4, 4, /* 15-18 */ 3, 3, 3, 3, 3, 3, /* 19-24 */ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */ }; if( a>=b ){ if( a>b+49 ) return a; if( a>b+31 ) return a+1; return a+x[a-b]; }else{ if( b>a+49 ) return b; if( b>a+31 ) return b+1; return b+x[b-a]; } } /* ** Convert an integer into a LogEst. In other words, compute a ** good approximatation for 10*log2(x). */ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; LogEst y = 40; if( x<8 ){ if( x<2 ) return 0; while( x<8 ){ y -= 10; x <<= 1; } }else{ while( x>255 ){ y += 40; x >>= 4; } while( x>15 ){ y += 10; x >>= 1; } } return a[x&7] + y - 10; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Convert a double into a LogEst ** In other words, compute an approximation for 10*log2(x). */ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ u64 a; LogEst e; assert( sizeof(x)==8 && sizeof(a)==8 ); if( x<=1 ) return 0; if( x<=2000000000 ) return sqlite3LogEst((u64)x); memcpy(&a, &x, 8); e = (a>>52) - 1022; return e*10; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Convert a LogEst into an integer. */ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ u64 n; if( x<10 ) return 1; n = x%10; x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; if( x>=3 ) return (n+8)<<(x-3); return (n+8)>>(3-x); } /************** End of util.c ************************************************/ /************** Begin file hash.c ********************************************/ /* ** 2001 September 22 ** ** The author disclaims copyright to this source code. In place of |
︙ | ︙ | |||
31380 31381 31382 31383 31384 31385 31386 | #else { "GetVersionExA", (SYSCALL)0, 0 }, #endif #define osGetVersionExA ((BOOL(WINAPI*)( \ LPOSVERSIONINFOA))aSyscall[34].pCurrent) | | | 31499 31500 31501 31502 31503 31504 31505 31506 31507 31508 31509 31510 31511 31512 31513 | #else { "GetVersionExA", (SYSCALL)0, 0 }, #endif #define osGetVersionExA ((BOOL(WINAPI*)( \ LPOSVERSIONINFOA))aSyscall[34].pCurrent) #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, #else { "GetVersionExW", (SYSCALL)0, 0 }, #endif #define osGetVersionExW ((BOOL(WINAPI*)( \ LPOSVERSIONINFOW))aSyscall[35].pCurrent) |
︙ | ︙ | |||
32894 32895 32896 32897 32898 32899 32900 | #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); OSTRACE(("CLOSE file=%p\n", pFile->h)); #if SQLITE_MAX_MMAP_SIZE>0 | | < | 33013 33014 33015 33016 33017 33018 33019 33020 33021 33022 33023 33024 33025 33026 33027 | #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); OSTRACE(("CLOSE file=%p\n", pFile->h)); #if SQLITE_MAX_MMAP_SIZE>0 winUnmapfile(pFile); #endif do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE |
︙ | ︙ | |||
33701 33702 33703 33704 33705 33706 33707 | if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } *(i64*)pArg = pFile->mmapSizeMax; if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ pFile->mmapSizeMax = newLimit; if( pFile->mmapSize>0 ){ | | | 33819 33820 33821 33822 33823 33824 33825 33826 33827 33828 33829 33830 33831 33832 33833 | if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } *(i64*)pArg = pFile->mmapSizeMax; if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ pFile->mmapSizeMax = newLimit; if( pFile->mmapSize>0 ){ winUnmapfile(pFile); rc = winMapfile(pFile, -1); } } OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); return rc; } #endif |
︙ | ︙ | |||
33918 33919 33920 33921 33922 33923 33924 | assert( winShmMutexHeld() ); OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", osGetCurrentProcessId(), deleteFlag)); pp = &winShmNodeList; while( (p = *pp)!=0 ){ if( p->nRef==0 ){ int i; | | | 34036 34037 34038 34039 34040 34041 34042 34043 34044 34045 34046 34047 34048 34049 34050 | assert( winShmMutexHeld() ); OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", osGetCurrentProcessId(), deleteFlag)); pp = &winShmNodeList; while( (p = *pp)!=0 ){ if( p->nRef==0 ){ int i; if( p->mutex ){ sqlite3_mutex_free(p->mutex); } for(i=0; i<p->nRegion; i++){ BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); UNUSED_VARIABLE_VALUE(bRc); bRc = osCloseHandle(p->aRegion[i].hMap); OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", |
︙ | ︙ | |||
34771 34772 34773 34774 34775 34776 34777 34778 34779 34780 34781 34782 34783 34784 34785 34786 34787 34788 34789 34790 34791 34792 34793 34794 34795 34796 34797 34798 34799 34800 34801 34802 34803 34804 34805 34806 34807 34808 34809 34810 34811 34812 34813 34814 34815 34816 34817 34818 34819 34820 34821 34822 34823 34824 | ** character, assume it is already a native Win32 path; otherwise, ** it must be converted to a native Win32 path prior via the Cygwin ** API prior to using it. */ if( winIsDriveLetterAndColon(zDir) ){ zConverted = winConvertFromUtf8Filename(zDir); if( !zConverted ){ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } if( winIsDir(zConverted) ){ sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir); sqlite3_free(zConverted); break; } sqlite3_free(zConverted); }else{ zConverted = sqlite3MallocZero( nBuf+1 ); if( !zConverted ){ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } if( cygwin_conv_path( osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, zConverted, nBuf+1)<0 ){ sqlite3_free(zConverted); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, "winGetTempname1", zDir); } if( winIsDir(zConverted) ){ /* At this point, we know the candidate directory exists and should ** be used. However, we may need to convert the string containing ** its name into UTF-8 (i.e. if it is UTF-16 right now). */ if( osIsNT() ){ char *zUtf8 = winUnicodeToUtf8(zConverted); if( !zUtf8 ){ sqlite3_free(zConverted); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8); sqlite3_free(zUtf8); sqlite3_free(zConverted); break; }else{ sqlite3_snprintf(nBuf-30, zBuf, "%s", zConverted); sqlite3_free(zConverted); break; } } sqlite3_free(zConverted); } | > > > > < | 34889 34890 34891 34892 34893 34894 34895 34896 34897 34898 34899 34900 34901 34902 34903 34904 34905 34906 34907 34908 34909 34910 34911 34912 34913 34914 34915 34916 34917 34918 34919 34920 34921 34922 34923 34924 34925 34926 34927 34928 34929 34930 34931 34932 34933 34934 34935 34936 34937 34938 34939 34940 34941 34942 34943 34944 34945 34946 34947 34948 34949 34950 34951 34952 34953 | ** character, assume it is already a native Win32 path; otherwise, ** it must be converted to a native Win32 path prior via the Cygwin ** API prior to using it. */ if( winIsDriveLetterAndColon(zDir) ){ zConverted = winConvertFromUtf8Filename(zDir); if( !zConverted ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } if( winIsDir(zConverted) ){ sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir); sqlite3_free(zConverted); break; } sqlite3_free(zConverted); }else{ zConverted = sqlite3MallocZero( nBuf+1 ); if( !zConverted ){ sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } if( cygwin_conv_path( osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, zConverted, nBuf+1)<0 ){ sqlite3_free(zConverted); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, "winGetTempname1", zDir); } if( winIsDir(zConverted) ){ /* At this point, we know the candidate directory exists and should ** be used. However, we may need to convert the string containing ** its name into UTF-8 (i.e. if it is UTF-16 right now). */ if( osIsNT() ){ char *zUtf8 = winUnicodeToUtf8(zConverted); if( !zUtf8 ){ sqlite3_free(zConverted); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); return SQLITE_IOERR_NOMEM; } sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8); sqlite3_free(zUtf8); sqlite3_free(zConverted); break; }else{ sqlite3_snprintf(nBuf-30, zBuf, "%s", zConverted); sqlite3_free(zConverted); break; } } sqlite3_free(zConverted); } } } #elif !SQLITE_OS_WINRT && !defined(__CYGWIN__) else if( osIsNT() ){ char *zMulti; LPWSTR zWidePath = sqlite3MallocZero( nBuf*sizeof(WCHAR) ); if( !zWidePath ){ |
︙ | ︙ | |||
35188 35189 35190 35191 35192 35193 35194 | } if( isTemp ){ pFile->zDeleteOnClose = zConverted; }else #endif { sqlite3_free(zConverted); | < > | 35309 35310 35311 35312 35313 35314 35315 35316 35317 35318 35319 35320 35321 35322 35323 35324 35325 | } if( isTemp ){ pFile->zDeleteOnClose = zConverted; }else #endif { sqlite3_free(zConverted); } sqlite3_free(zTmpname); pFile->pMethod = &winIoMethod; pFile->pVfs = pVfs; pFile->h = h; if( isReadonly ){ pFile->ctrlFlags |= WINFILE_RDONLY; } if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ |
︙ | ︙ | |||
48984 48985 48986 48987 48988 48989 48990 | ** ** The first page is always a btree page. The first 100 bytes of the first ** page contain a special header (the "file header") that describes the file. ** The format of the file header is as follows: ** ** OFFSET SIZE DESCRIPTION ** 0 16 Header string: "SQLite format 3\000" | | | | | | | > | | 49105 49106 49107 49108 49109 49110 49111 49112 49113 49114 49115 49116 49117 49118 49119 49120 49121 49122 49123 49124 49125 49126 49127 49128 49129 49130 49131 49132 49133 49134 49135 49136 49137 49138 49139 49140 49141 49142 | ** ** The first page is always a btree page. The first 100 bytes of the first ** page contain a special header (the "file header") that describes the file. ** The format of the file header is as follows: ** ** OFFSET SIZE DESCRIPTION ** 0 16 Header string: "SQLite format 3\000" ** 16 2 Page size in bytes. (1 means 65536) ** 18 1 File format write version ** 19 1 File format read version ** 20 1 Bytes of unused space at the end of each page ** 21 1 Max embedded payload fraction (must be 64) ** 22 1 Min embedded payload fraction (must be 32) ** 23 1 Min leaf payload fraction (must be 32) ** 24 4 File change counter ** 28 4 Reserved for future use ** 32 4 First freelist page ** 36 4 Number of freelist pages in the file ** 40 60 15 4-byte meta values passed to higher layers ** ** 40 4 Schema cookie ** 44 4 File format of schema layer ** 48 4 Size of page cache ** 52 4 Largest root-page (auto/incr_vacuum) ** 56 4 1=UTF-8 2=UTF16le 3=UTF16be ** 60 4 User version ** 64 4 Incremental vacuum mode ** 68 4 Application-ID ** 72 20 unused ** 92 4 The version-valid-for number ** 96 4 SQLITE_VERSION_NUMBER ** ** All of the integer values are big-endian (most significant byte first). ** ** The file change counter is incremented when the database is changed ** This counter allows other processes to know when the file has changed ** and thus when they need to flush their cache. ** |
︙ | ︙ | |||
51920 51921 51922 51923 51924 51925 51926 51927 51928 51929 51930 51931 51932 51933 | /* ** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes. */ static void allocateTempSpace(BtShared *pBt){ if( !pBt->pTmpSpace ){ pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); } } /* ** Free the pBt->pTmpSpace allocation */ static void freeTempSpace(BtShared *pBt){ | > > > > > > > > > > > > | 52042 52043 52044 52045 52046 52047 52048 52049 52050 52051 52052 52053 52054 52055 52056 52057 52058 52059 52060 52061 52062 52063 52064 52065 52066 52067 | /* ** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes. */ static void allocateTempSpace(BtShared *pBt){ if( !pBt->pTmpSpace ){ pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); /* One of the uses of pBt->pTmpSpace is to format cells before ** inserting them into a leaf page (function fillInCell()). If ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes ** by the various routines that manipulate binary cells. Which ** can mean that fillInCell() only initializes the first 2 or 3 ** bytes of pTmpSpace, but that the first 4 bytes are copied from ** it into a database page. This is not actually a problem, but it ** does cause a valgrind error when the 1 or 2 bytes of unitialized ** data is passed to system call write(). So to avoid this error, ** zero the first 4 bytes of temp space here. */ if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4); } } /* ** Free the pBt->pTmpSpace allocation */ static void freeTempSpace(BtShared *pBt){ |
︙ | ︙ | |||
52376 52377 52378 52379 52380 52381 52382 | pBt->max1bytePayload = 127; }else{ pBt->max1bytePayload = (u8)pBt->maxLocal; } assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); pBt->pPage1 = pPage1; pBt->nPage = nPage; | < | 52510 52511 52512 52513 52514 52515 52516 52517 52518 52519 52520 52521 52522 52523 | pBt->max1bytePayload = 127; }else{ pBt->max1bytePayload = (u8)pBt->maxLocal; } assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); pBt->pPage1 = pPage1; pBt->nPage = nPage; return SQLITE_OK; page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } |
︙ | ︙ | |||
52536 52537 52538 52539 52540 52541 52542 | /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } | | | 52669 52670 52671 52672 52673 52674 52675 52676 52677 52678 52679 52680 52681 52682 52683 | /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ rc = SQLITE_READONLY; goto trans_begun; } |
︙ | ︙ | |||
60187 60188 60189 60190 60191 60192 60193 | if( pRec==0 ) return 0; p->ppRec[0] = pRec; } pRec->nField = p->iVal+1; return &pRec->aMem[p->iVal]; } | | > > | | 60320 60321 60322 60323 60324 60325 60326 60327 60328 60329 60330 60331 60332 60333 60334 60335 60336 60337 60338 60339 60340 60341 60342 60343 60344 60345 60346 60347 60348 60349 60350 | if( pRec==0 ) return 0; p->ppRec[0] = pRec; } pRec->nField = p->iVal+1; return &pRec->aMem[p->iVal]; } #else UNUSED_PARAMETER(p); #endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ return sqlite3ValueNew(db); } /* ** Extract a value from the supplied expression in the manner described ** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object ** using valueNew(). ** ** If pCtx is NULL and an error occurs after the sqlite3_value object ** has been allocated, it is freed before returning. Or, if pCtx is not ** NULL, it is assumed that the caller will free any allocated object ** in all cases. */ static int valueFromExpr( sqlite3 *db, /* The database connection */ Expr *pExpr, /* The expression to evaluate */ u8 enc, /* Encoding to use */ u8 affinity, /* Affinity to use */ sqlite3_value **ppVal, /* Write the new value here */ struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ ){ |
︙ | ︙ | |||
60358 60359 60360 60361 60362 60363 60364 60365 60366 60367 60368 60369 60370 60371 | int iSerial; /* Serial type */ int nSerial; /* Bytes of space for iSerial as varint */ int nVal; /* Bytes of space required for argv[0] */ int nRet; sqlite3 *db; u8 *aRet; iSerial = sqlite3VdbeSerialType(argv[0], file_format); nSerial = sqlite3VarintLen(iSerial); nVal = sqlite3VdbeSerialTypeLen(iSerial); db = sqlite3_context_db_handle(context); nRet = 1 + nSerial + nVal; aRet = sqlite3DbMallocRaw(db, nRet); | > | 60493 60494 60495 60496 60497 60498 60499 60500 60501 60502 60503 60504 60505 60506 60507 | int iSerial; /* Serial type */ int nSerial; /* Bytes of space for iSerial as varint */ int nVal; /* Bytes of space required for argv[0] */ int nRet; sqlite3 *db; u8 *aRet; UNUSED_PARAMETER( argc ); iSerial = sqlite3VdbeSerialType(argv[0], file_format); nSerial = sqlite3VarintLen(iSerial); nVal = sqlite3VdbeSerialTypeLen(iSerial); db = sqlite3_context_db_handle(context); nRet = 1 + nSerial + nVal; aRet = sqlite3DbMallocRaw(db, nRet); |
︙ | ︙ | |||
62975 62976 62977 62978 62979 62980 62981 62982 62983 62984 62985 62986 62987 62988 | ); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); } } #endif p->magic = VDBE_MAGIC_INIT; return p->rc & db->errMask; } /* ** Clean up and delete a VDBE after execution. Return an integer which is ** the result code. Write any error message text into *pzErrMsg. | > | 63111 63112 63113 63114 63115 63116 63117 63118 63119 63120 63121 63122 63123 63124 63125 | ); sqlite3VdbePrintOp(out, i, &p->aOp[i]); } fclose(out); } } #endif p->iCurrentTime = 0; p->magic = VDBE_MAGIC_INIT; return p->rc & db->errMask; } /* ** Clean up and delete a VDBE after execution. Return an integer which is ** the result code. Write any error message text into *pzErrMsg. |
︙ | ︙ | |||
75297 75298 75299 75300 75301 75302 75303 75304 75305 75306 75307 75308 75309 75310 | pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ } } } #ifndef SQLITE_OMIT_AUTHORIZATION if( pDef ){ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); | > > > > | 75434 75435 75436 75437 75438 75439 75440 75441 75442 75443 75444 75445 75446 75447 75448 75449 75450 75451 | pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to ** likelihood(X, 0.0625). ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for ** likelihood(X,0.0625). */ pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ } } } #ifndef SQLITE_OMIT_AUTHORIZATION if( pDef ){ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); |
︙ | ︙ | |||
76080 76081 76082 76083 76084 76085 76086 | if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); | | | 76221 76222 76223 76224 76225 76226 76227 76228 76229 76230 76231 76232 76233 76234 76235 | if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){ /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ |
︙ | ︙ | |||
78500 78501 78502 78503 78504 78505 78506 | } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); assert( !ExprHasProperty(pExpr, EP_IntValue) ); | | | 78641 78642 78643 78644 78645 78646 78647 78648 78649 78650 78651 78652 78653 78654 78655 | } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); assert( !ExprHasProperty(pExpr, EP_IntValue) ); aff = sqlite3AffinityType(pExpr->u.zToken, 0); to_op = aff - SQLITE_AFF_TEXT + OP_ToText; assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); testcase( to_op==OP_ToText ); |
︙ | ︙ | |||
79167 79168 79169 79170 79171 79172 79173 | sqlite3ExplainExpr(pOut, pExpr->pLeft); break; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ const char *zAff = "unk"; | | | 79308 79309 79310 79311 79312 79313 79314 79315 79316 79317 79318 79319 79320 79321 79322 | sqlite3ExplainExpr(pOut, pExpr->pLeft); break; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ const char *zAff = "unk"; switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){ case SQLITE_AFF_TEXT: zAff = "TEXT"; break; case SQLITE_AFF_NONE: zAff = "NONE"; break; case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break; case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break; case SQLITE_AFF_REAL: zAff = "REAL"; break; } sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff); |
︙ | ︙ | |||
81171 81172 81173 81174 81175 81176 81177 | ** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled ** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only ** created and used by SQLite versions 3.7.9 and later and with ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced ** version of sqlite_stat3 and is only available when compiled with | | | 81312 81313 81314 81315 81316 81317 81318 81319 81320 81321 81322 81323 81324 81325 81326 | ** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled ** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only ** created and used by SQLite versions 3.7.9 and later and with ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced ** version of sqlite_stat3 and is only available when compiled with ** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is ** not possible to enable both STAT3 and STAT4 at the same time. If they ** are both enabled, then STAT4 takes precedence. ** ** For most applications, sqlite_stat1 provides all the statisics required ** for the query planner to make good choices. ** ** Format of sqlite_stat1: |
︙ | ︙ | |||
81247 81248 81249 81250 81251 81252 81253 | ** that indexed columns are compared against in the WHERE clauses of ** queries. ** ** The sqlite_stat4 table contains multiple entries for each index. ** The idx column names the index and the tbl column is the table of the ** index. If the idx and tbl columns are the same, then the sample is ** of the INTEGER PRIMARY KEY. The sample column is a blob which is the | | | | | | | | 81388 81389 81390 81391 81392 81393 81394 81395 81396 81397 81398 81399 81400 81401 81402 81403 81404 81405 81406 81407 | ** that indexed columns are compared against in the WHERE clauses of ** queries. ** ** The sqlite_stat4 table contains multiple entries for each index. ** The idx column names the index and the tbl column is the table of the ** index. If the idx and tbl columns are the same, then the sample is ** of the INTEGER PRIMARY KEY. The sample column is a blob which is the ** binary encoding of a key from the index. The nEq column is a ** list of integers. The first integer is the approximate number ** of entries in the index whose left-most column exactly matches ** the left-most column of the sample. The second integer in nEq ** is the approximate number of entries in the index where the ** first two columns match the first two columns of the sample. ** And so forth. nLt is another list of integers that show the approximate ** number of entries that are strictly less than the sample. The first ** integer in nLt contains the number of entries in the index where the ** left-most column is less than the left-most column of the sample. ** The K-th integer in the nLt entry is the number of index entries ** where the first K columns are less than the first K columns of the ** sample. The nDLt column is like nLt except that it contains the |
︙ | ︙ | |||
81583 81584 81585 81586 81587 81588 81589 | return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); #endif } /* ** Copy the contents of object (*pFrom) into (*pTo). */ | | | 81724 81725 81726 81727 81728 81729 81730 81731 81732 81733 81734 81735 81736 81737 81738 | return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); #endif } /* ** Copy the contents of object (*pFrom) into (*pTo). */ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ pTo->iRowid = pFrom->iRowid; pTo->isPSample = pFrom->isPSample; pTo->iCol = pFrom->iCol; pTo->iHash = pFrom->iHash; memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol); memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol); memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol); |
︙ | ︙ | |||
81728 81729 81730 81731 81732 81733 81734 81735 81736 81737 81738 81739 81740 81741 | if( p->nSample<p->mxSample || sampleIsBetter(p, &p->current, &p->a[p->iMin]) ){ sampleInsert(p, &p->current, 0); } } #endif } /* ** Implementation of the stat_push SQL function: stat_push(P,R,C) ** Arguments: ** ** P Pointer to the Stat4Accum object created by stat_init() | > > > > > | 81869 81870 81871 81872 81873 81874 81875 81876 81877 81878 81879 81880 81881 81882 81883 81884 81885 81886 81887 | if( p->nSample<p->mxSample || sampleIsBetter(p, &p->current, &p->a[p->iMin]) ){ sampleInsert(p, &p->current, 0); } } #endif #ifndef SQLITE_ENABLE_STAT3_OR_STAT4 UNUSED_PARAMETER( p ); UNUSED_PARAMETER( iChng ); #endif } /* ** Implementation of the stat_push SQL function: stat_push(P,R,C) ** Arguments: ** ** P Pointer to the Stat4Accum object created by stat_init() |
︙ | ︙ | |||
81753 81754 81755 81756 81757 81758 81759 81760 81761 81762 81763 81764 81765 81766 | ){ int i; /* The three function arguments */ Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); int iChng = sqlite3_value_int(argv[1]); assert( p->nCol>1 ); /* Includes rowid field */ assert( iChng<p->nCol ); if( p->nRow==0 ){ /* This is the first call to this function. Do initialization. */ for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1; }else{ | > > | 81899 81900 81901 81902 81903 81904 81905 81906 81907 81908 81909 81910 81911 81912 81913 81914 | ){ int i; /* The three function arguments */ Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); int iChng = sqlite3_value_int(argv[1]); UNUSED_PARAMETER( argc ); UNUSED_PARAMETER( context ); assert( p->nCol>1 ); /* Includes rowid field */ assert( iChng<p->nCol ); if( p->nRow==0 ){ /* This is the first call to this function. Do initialization. */ for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1; }else{ |
︙ | ︙ | |||
81882 81883 81884 81885 81886 81887 81888 | char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); return; } | | | | | | 82030 82031 82032 82033 82034 82035 82036 82037 82038 82039 82040 82041 82042 82043 82044 82045 82046 82047 82048 82049 | char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); return; } sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); z = zRet + sqlite3Strlen30(zRet); for(i=0; i<(p->nCol-1); i++){ u64 nDistinct = p->current.anDLt[i] + 1; u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; sqlite3_snprintf(24, z, " %llu", iVal); z += sqlite3Strlen30(z); assert( p->current.anEq[i] ); } assert( z[0]=='\0' && z>zRet ); sqlite3_result_text(context, zRet, -1, sqlite3_free); } |
︙ | ︙ | |||
81928 81929 81930 81931 81932 81933 81934 | char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); }else{ int i; char *z = zRet; for(i=0; i<p->nCol; i++){ | | > > > | > > | 82076 82077 82078 82079 82080 82081 82082 82083 82084 82085 82086 82087 82088 82089 82090 82091 82092 82093 82094 82095 82096 82097 82098 82099 82100 82101 82102 82103 82104 82105 82106 82107 82108 82109 82110 82111 82112 82113 82114 82115 82116 82117 82118 82119 82120 82121 82122 82123 82124 | char *zRet = sqlite3MallocZero(p->nCol * 25); if( zRet==0 ){ sqlite3_result_error_nomem(context); }else{ int i; char *z = zRet; for(i=0; i<p->nCol; i++){ sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]); z += sqlite3Strlen30(z); } assert( z[0]=='\0' && z>zRet ); z[-1] = '\0'; sqlite3_result_text(context, zRet, -1, sqlite3_free); } } } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( argc ); #endif } static const FuncDef statGetFuncdef = { 1+IsStat34, /* nArg */ SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xFunc */ 0, /* xStep */ 0, /* xFinalize */ "stat_get", /* zName */ 0, /* pHash */ 0 /* pDestructor */ }; static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ assert( regOut!=regStat4 && regOut!=regStat4+1 ); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1); #elif SQLITE_DEBUG assert( iParam==STAT_GET_STAT1 ); #else UNUSED_PARAMETER( iParam ); #endif sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut); sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 1 + IsStat34); } /* |
︙ | ︙ | |||
82389 82390 82391 82392 82393 82394 82395 | /* ** The first argument points to a nul-terminated string containing a ** list of space separated integers. Read the first nOut of these into ** the array aOut[]. */ static void decodeIntArray( | | | | | < < > > > > > > | | > > > > > | 82542 82543 82544 82545 82546 82547 82548 82549 82550 82551 82552 82553 82554 82555 82556 82557 82558 82559 82560 82561 82562 82563 82564 82565 82566 82567 82568 82569 82570 82571 82572 82573 82574 82575 82576 82577 82578 82579 82580 82581 82582 82583 82584 82585 82586 82587 82588 82589 82590 82591 82592 | /* ** The first argument points to a nul-terminated string containing a ** list of space separated integers. Read the first nOut of these into ** the array aOut[]. */ static void decodeIntArray( char *zIntArray, /* String containing int array to decode */ int nOut, /* Number of slots in aOut[] */ tRowcnt *aOut, /* Store integers here */ Index *pIndex /* Handle extra flags for this index, if not NULL */ ){ char *z = zIntArray; int c; int i; tRowcnt v; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else if( NEVER(z==0) ) z = ""; #endif for(i=0; *z && i<nOut; i++){ v = 0; while( (c=z[0])>='0' && c<='9' ){ v = v*10 + c - '0'; z++; } aOut[i] = v; if( *z==' ' ) z++; } #ifndef SQLITE_ENABLE_STAT3_OR_STAT4 assert( pIndex!=0 ); #else if( pIndex ) #endif { if( strcmp(z, "unordered")==0 ){ pIndex->bUnordered = 1; }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ int v32 = 0; sqlite3GetInt32(z+3, &v32); pIndex->szIdxRow = sqlite3LogEst(v32); } } } /* ** This callback is invoked once for each index when reading the ** sqlite_stat1 table. ** |
︙ | ︙ | |||
82455 82456 82457 82458 82459 82460 82461 | pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); }else{ pIndex = 0; } z = argv[2]; if( pIndex ){ | < | < > > | > | 82617 82618 82619 82620 82621 82622 82623 82624 82625 82626 82627 82628 82629 82630 82631 82632 82633 82634 82635 82636 82637 | pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); }else{ pIndex = 0; } z = argv[2]; if( pIndex ){ decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex); if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0]; }else{ Index fakeIdx; fakeIdx.szIdxRow = pTable->szTabRow; decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx); pTable->szTabRow = fakeIdx.szIdxRow; } return 0; } /* ** If the Index.aSample variable is not NULL, delete the aSample[] array |
︙ | ︙ | |||
83183 83184 83185 83186 83187 83188 83189 | codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); } #endif /* SQLITE_OMIT_ATTACH */ /* ** Initialize a DbFixer structure. This routine must be called prior ** to passing the structure to one of the sqliteFixAAAA() routines below. | < < < | < | | 83346 83347 83348 83349 83350 83351 83352 83353 83354 83355 83356 83357 83358 83359 83360 83361 83362 83363 83364 83365 83366 83367 83368 83369 83370 83371 83372 83373 83374 83375 83376 83377 | codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); } #endif /* SQLITE_OMIT_ATTACH */ /* ** Initialize a DbFixer structure. This routine must be called prior ** to passing the structure to one of the sqliteFixAAAA() routines below. */ SQLITE_PRIVATE void sqlite3FixInit( DbFixer *pFix, /* The fixer to be initialized */ Parse *pParse, /* Error messages will be written here */ int iDb, /* This is the database that must be used */ const char *zType, /* "view", "trigger", or "index" */ const Token *pName /* Name of the view, trigger, or index */ ){ sqlite3 *db; db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; pFix->bVarOnly = (iDb==1); } /* ** The following set of routines walk through the parse tree and assign ** a specific database to all table references where the database name ** was left unspecified in the original SQL statement. The pFix structure ** must have been initialized by a prior call to sqlite3FixInit(). |
︙ | ︙ | |||
83232 83233 83234 83235 83236 83237 83238 | int i; const char *zDb; struct SrcList_item *pItem; if( NEVER(pList==0) ) return 0; zDb = pFix->zDb; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ | > | | | | | | | | | > | 83391 83392 83393 83394 83395 83396 83397 83398 83399 83400 83401 83402 83403 83404 83405 83406 83407 83408 83409 83410 83411 83412 83413 83414 83415 | int i; const char *zDb; struct SrcList_item *pItem; if( NEVER(pList==0) ) return 0; zDb = pFix->zDb; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pFix->bVarOnly==0 ){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif } return 0; } |
︙ | ︙ | |||
83262 83263 83264 83265 83266 83267 83268 83269 83270 83271 83272 83273 83274 83275 83276 83277 83278 83279 83280 83281 83282 83283 83284 83285 83286 83287 83288 | return 1; } if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ return 1; } pSelect = pSelect->pPrior; } return 0; } SQLITE_PRIVATE int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } if( sqlite3FixExpr(pFix, pExpr->pRight) ){ | > > > > > > > > > > > > > > > > > > > > | 83423 83424 83425 83426 83427 83428 83429 83430 83431 83432 83433 83434 83435 83436 83437 83438 83439 83440 83441 83442 83443 83444 83445 83446 83447 83448 83449 83450 83451 83452 83453 83454 83455 83456 83457 83458 83459 83460 83461 83462 83463 83464 83465 83466 83467 83468 83469 | return 1; } if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ return 1; } if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ return 1; } if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ return 1; } pSelect = pSelect->pPrior; } return 0; } SQLITE_PRIVATE int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ if( pExpr->op==TK_VARIABLE ){ if( pFix->pParse->db->init.busy ){ pExpr->op = TK_NULL; }else{ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); return 1; } } if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } if( sqlite3FixExpr(pFix, pExpr->pRight) ){ |
︙ | ︙ | |||
84458 84459 84460 84461 84462 84463 84464 | pParse->nErr++; goto begin_table_error; } pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; | | | 84639 84640 84641 84642 84643 84644 84645 84646 84647 84648 84649 84650 84651 84652 84653 | pParse->nErr++; goto begin_table_error; } pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; pTable->nRowEst = 1048576; assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure ** so that INSERT can find the table easily. */ |
︙ | ︙ | |||
84605 84606 84607 84608 84609 84610 84611 84612 84613 84614 84615 84616 84617 84618 | pCol->zName = z; /* If there is no type specified, columns have the default affinity ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; p->nCol++; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on | > | 84786 84787 84788 84789 84790 84791 84792 84793 84794 84795 84796 84797 84798 84799 84800 | pCol->zName = z; /* If there is no type specified, columns have the default affinity ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; pCol->szEst = 1; p->nCol++; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on |
︙ | ︙ | |||
84646 84647 84648 84649 84650 84651 84652 | ** 'REAL' | SQLITE_AFF_REAL ** 'FLOA' | SQLITE_AFF_REAL ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ | | > > | | > > > > > > > > > > > > > > > > > > > > > > > > | 84828 84829 84830 84831 84832 84833 84834 84835 84836 84837 84838 84839 84840 84841 84842 84843 84844 84845 84846 84847 84848 84849 84850 84851 84852 84853 84854 84855 84856 84857 84858 84859 84860 84861 84862 84863 84864 84865 84866 84867 84868 84869 84870 84871 84872 84873 84874 84875 84876 84877 84878 84879 84880 84881 84882 84883 84884 84885 84886 84887 84888 84889 84890 84891 84892 84893 84894 84895 84896 84897 84898 84899 84900 | ** 'REAL' | SQLITE_AFF_REAL ** 'FLOA' | SQLITE_AFF_REAL ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const char *zChar = 0; if( zIn==0 ) return aff; while( zIn[0] ){ h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ aff = SQLITE_AFF_TEXT; zChar = zIn; }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ aff = SQLITE_AFF_TEXT; }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ aff = SQLITE_AFF_TEXT; }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ aff = SQLITE_AFF_NONE; if( zIn[0]=='(' ) zChar = zIn; #ifndef SQLITE_OMIT_FLOATING_POINT }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ && aff==SQLITE_AFF_NUMERIC ){ aff = SQLITE_AFF_REAL; }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ && aff==SQLITE_AFF_NUMERIC ){ aff = SQLITE_AFF_REAL; }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ && aff==SQLITE_AFF_NUMERIC ){ aff = SQLITE_AFF_REAL; #endif }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ aff = SQLITE_AFF_INTEGER; break; } } /* If pszEst is not NULL, store an estimate of the field size. The ** estimate is scaled so that the size of an integer is 1. */ if( pszEst ){ *pszEst = 1; /* default size is approx 4 bytes */ if( aff<=SQLITE_AFF_NONE ){ if( zChar ){ while( zChar[0] ){ if( sqlite3Isdigit(zChar[0]) ){ int v = 0; sqlite3GetInt32(zChar, &v); v = v/4 + 1; if( v>255 ) v = 255; *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ break; } zChar++; } }else{ *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ } } } return aff; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. The pFirst token is the first ** token in the sequence of tokens that describe the type of the |
︙ | ︙ | |||
84700 84701 84702 84703 84704 84705 84706 | Column *pCol; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); | | | 84908 84909 84910 84911 84912 84913 84914 84915 84916 84917 84918 84919 84920 84921 84922 | Column *pCol; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } /* ** The expression is the default value for the most recently added column ** of the table currently under construction. ** ** Default value expressions must be constant. Raise an exception if this |
︙ | ︙ | |||
85048 85049 85050 85051 85052 85053 85054 | testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); testcase( pCol->affinity==SQLITE_AFF_INTEGER ); testcase( pCol->affinity==SQLITE_AFF_REAL ); zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; len = sqlite3Strlen30(zType); assert( pCol->affinity==SQLITE_AFF_NONE | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 85256 85257 85258 85259 85260 85261 85262 85263 85264 85265 85266 85267 85268 85269 85270 85271 85272 85273 85274 85275 85276 85277 85278 85279 85280 85281 85282 85283 85284 85285 85286 85287 85288 85289 85290 85291 85292 85293 85294 85295 85296 85297 85298 85299 85300 85301 85302 85303 85304 85305 | testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); testcase( pCol->affinity==SQLITE_AFF_INTEGER ); testcase( pCol->affinity==SQLITE_AFF_REAL ); zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; len = sqlite3Strlen30(zType); assert( pCol->affinity==SQLITE_AFF_NONE || pCol->affinity==sqlite3AffinityType(zType, 0) ); memcpy(&zStmt[k], zType, len); k += len; assert( k<=n ); } sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); return zStmt; } /* ** Estimate the total row width for a table. */ static void estimateTableWidth(Table *pTab){ unsigned wTable = 0; const Column *pTabCol; int i; for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){ wTable += pTabCol->szEst; } if( pTab->iPKey<0 ) wTable++; pTab->szTabRow = sqlite3LogEst(wTable*4); } /* ** Estimate the average size of a row for an index. */ static void estimateIndexWidth(Index *pIdx){ unsigned wIndex = 1; int i; const Column *aCol = pIdx->pTable->aCol; for(i=0; i<pIdx->nColumn; i++){ assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol ); wIndex += aCol[pIdx->aiColumn[i]].szEst; } pIdx->szIdxRow = sqlite3LogEst(wIndex*4); } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure that other action routines have been building ** is added to the internal hash tables, assuming no errors have |
︙ | ︙ | |||
85083 85084 85085 85086 85087 85088 85089 | */ SQLITE_PRIVATE void sqlite3EndTable( Parse *pParse, /* Parse context */ Token *pCons, /* The ',' token after the last column defn. */ Token *pEnd, /* The final ')' token in the CREATE TABLE */ Select *pSelect /* Select from a "CREATE ... AS SELECT" */ ){ | | | | > > > > > > > | 85319 85320 85321 85322 85323 85324 85325 85326 85327 85328 85329 85330 85331 85332 85333 85334 85335 85336 85337 85338 85339 85340 85341 85342 85343 85344 85345 85346 85347 85348 85349 85350 85351 85352 85353 85354 85355 85356 85357 85358 85359 85360 | */ SQLITE_PRIVATE void sqlite3EndTable( Parse *pParse, /* Parse context */ Token *pCons, /* The ',' token after the last column defn. */ Token *pEnd, /* The final ')' token in the CREATE TABLE */ Select *pSelect /* Select from a "CREATE ... AS SELECT" */ ){ Table *p; /* The new table */ sqlite3 *db = pParse->db; /* The database connection */ int iDb; /* Database in which the table lives */ Index *pIdx; /* An implied index of the table */ if( (pEnd==0 && pSelect==0) || db->mallocFailed ){ return; } p = pParse->pNewTable; if( p==0 ) return; assert( !db->init.busy || !pSelect ); iDb = sqlite3SchemaToIndex(db, p->pSchema); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. */ if( p->pCheck ){ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* Estimate the average row size for the table and for all implied indices */ estimateTableWidth(p); for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ estimateIndexWidth(pIdx); } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) */ |
︙ | ︙ | |||
85301 85302 85303 85304 85305 85306 85307 | p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(db, pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); | | | < | 85544 85545 85546 85547 85548 85549 85550 85551 85552 85553 85554 85555 85556 85557 85558 85559 | p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(db, pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ){ sqlite3SelectDelete(db, pSelect); return; } /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that |
︙ | ︙ | |||
86064 86065 86066 86067 86068 86069 86070 | DbFixer sFix; /* For assigning database names to pTable */ int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ sqlite3 *db = pParse->db; Db *pDb; /* The specific table containing the indexed database */ int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ | > | | | | 86306 86307 86308 86309 86310 86311 86312 86313 86314 86315 86316 86317 86318 86319 86320 86321 86322 86323 | DbFixer sFix; /* For assigning database names to pTable */ int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ sqlite3 *db = pParse->db; Db *pDb; /* The specific table containing the indexed database */ int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ const Column *pTabCol; /* A column in the table */ int nCol; /* Number of columns */ int nExtra = 0; /* Space allocated for zExtra[] */ char *zExtra; /* Extra space after the Index object */ assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed || IN_DECLARE_VTAB ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; |
︙ | ︙ | |||
86103 86104 86105 86106 86107 86108 86109 | pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } #endif | | | < | 86346 86347 86348 86349 86350 86351 86352 86353 86354 86355 86356 86357 86358 86359 86360 86361 | pTab = sqlite3SrcListLookup(pParse, pTblName); if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } #endif sqlite3FixInit(&sFix, pParse, iDb, "index", pName); if( sqlite3FixSrcList(&sFix, pTblName) ){ /* Because the parser constructs pTblName from a single identifier, ** sqlite3FixSrcList can never fail. */ assert(0); } pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); assert( db->mallocFailed==0 || pTab==0 ); if( pTab==0 ) goto exit_create_index; |
︙ | ︙ | |||
86294 86295 86296 86297 86298 86299 86300 | ** more than once within the same index. Only the first instance of ** the column will ever be used by the optimizer. Note that using the ** same column more than once cannot be an error because that would ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; | < | 86536 86537 86538 86539 86540 86541 86542 86543 86544 86545 86546 86547 86548 86549 | ** more than once within the same index. Only the first instance of ** the column will ever be used by the optimizer. Note that using the ** same column more than once cannot be an error because that would ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; int requestedSortOrder; char *zColl; /* Collation sequence name */ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ |
︙ | ︙ | |||
86331 86332 86333 86334 86335 86336 86337 86338 86339 86340 86341 86342 86343 86344 | } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0; } sqlite3DefaultRowEst(pIndex); if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or ** a PRIMARY KEY or UNIQUE clause following the column definitions. ** i.e. one of: ** | > | 86572 86573 86574 86575 86576 86577 86578 86579 86580 86581 86582 86583 86584 86585 86586 | } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0; } sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or ** a PRIMARY KEY or UNIQUE clause following the column definitions. ** i.e. one of: ** |
︙ | ︙ | |||
88236 88237 88238 88239 88240 88241 88242 88243 88244 88245 88246 88247 88248 88249 | ** It is easier just to erase the whole table. Prior to version 3.6.5, ** this optimization caused the row change count (the value returned by ** API function sqlite3_count_changes) to be set incorrectly. */ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) && 0==sqlite3FkRequired(pParse, pTab, 0, 0) ){ assert( !isView ); sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, pTab->zName, P4_STATIC); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else | > | 88478 88479 88480 88481 88482 88483 88484 88485 88486 88487 88488 88489 88490 88491 88492 | ** It is easier just to erase the whole table. Prior to version 3.6.5, ** this optimization caused the row change count (the value returned by ** API function sqlite3_count_changes) to be set incorrectly. */ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) && 0==sqlite3FkRequired(pParse, pTab, 0, 0) ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, pTab->zName, P4_STATIC); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else |
︙ | ︙ | |||
90941 90942 90943 90944 90945 90946 90947 | /* Search for a deferred foreign key constraint for which this table ** is the child table. If one cannot be found, return without ** generating any VDBE code. If one can be found, then jump over ** the entire DELETE if there are no outstanding deferred constraints ** when this statement is run. */ FKey *p; for(p=pTab->pFKey; p; p=p->pNextFrom){ | | | > > > > > > | | | | > | 91184 91185 91186 91187 91188 91189 91190 91191 91192 91193 91194 91195 91196 91197 91198 91199 91200 91201 91202 91203 91204 91205 91206 91207 91208 91209 91210 91211 91212 91213 91214 91215 91216 91217 91218 91219 91220 91221 91222 91223 | /* Search for a deferred foreign key constraint for which this table ** is the child table. If one cannot be found, return without ** generating any VDBE code. If one can be found, then jump over ** the entire DELETE if there are no outstanding deferred constraints ** when this statement is run. */ FKey *p; for(p=pTab->pFKey; p; p=p->pNextFrom){ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; } if( !p ) return; iSkip = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); } pParse->disableTriggers = 1; sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); pParse->disableTriggers = 0; /* If the DELETE has generated immediate foreign key constraint ** violations, halt the VDBE and return an error at this point, before ** any modifications to the schema are made. This is because statement ** transactions are not able to rollback schema changes. ** ** If the SQLITE_DeferFKs flag is set, then this is not required, as ** the statement transaction will not be rolled back even if FK ** constraints are violated. */ if( (db->flags & SQLITE_DeferFKs)==0 ){ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, "foreign key constraint failed", P4_STATIC ); } if( iSkip ){ sqlite3VdbeResolveLabel(v, iSkip); } } } |
︙ | ︙ | |||
93485 93486 93487 93488 93489 93490 93491 93492 93493 93494 93495 93496 93497 93498 | pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pSrcIdx->zName)); pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); sqlite3VdbeJumpHere(v, addr1); } | > | 93735 93736 93737 93738 93739 93740 93741 93742 93743 93744 93745 93746 93747 93748 93749 | pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pSrcIdx->zName)); pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, (char*)pKey, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); sqlite3VdbeJumpHere(v, addr1); } |
︙ | ︙ | |||
94960 94961 94962 94963 94964 94965 94966 | #define PragTyp_LOCKING_MODE 21 #define PragTyp_PAGE_COUNT 22 #define PragTyp_MMAP_SIZE 23 #define PragTyp_PAGE_SIZE 24 #define PragTyp_SECURE_DELETE 25 #define PragTyp_SHRINK_MEMORY 26 #define PragTyp_SOFT_HEAP_LIMIT 27 | > | | | | | | | | | | | | > > > | > > > | > > > | > > | > > | > | > > > | > > | > > | > | > > | > > | > | > > > | > > | > > | > | > > > | > > > | > > | > > | | > > | > | > > > | > > > | > > | > > | > | > > | > > | > | > | > | > > > > > > | > > | > | > > > | > > > | > > > | > > > | > > > | > > > | > > | > > | > | > > > | > > > | > > > | > > > | > > > | > > > | > > > | > > > | > | > | > > | > > | | > > | > | > > | > > | > | > > > | > > | > > | > | > > > | > > > | > | > > > > > > > | > > > | > > > | > > > | > > > | > > | > > | > | > | | > > | > | > | > | > > > | > > | > > | | | 95211 95212 95213 95214 95215 95216 95217 95218 95219 95220 95221 95222 95223 95224 95225 95226 95227 95228 95229 95230 95231 95232 95233 95234 95235 95236 95237 95238 95239 95240 95241 95242 95243 95244 95245 95246 95247 95248 95249 95250 95251 95252 95253 95254 95255 95256 95257 95258 95259 95260 95261 95262 95263 95264 95265 95266 95267 95268 95269 95270 95271 95272 95273 95274 95275 95276 95277 95278 95279 95280 95281 95282 95283 95284 95285 95286 95287 95288 95289 95290 95291 95292 95293 95294 95295 95296 95297 95298 95299 95300 95301 95302 95303 95304 95305 95306 95307 95308 95309 95310 95311 95312 95313 95314 95315 95316 95317 95318 95319 95320 95321 95322 95323 95324 95325 95326 95327 95328 95329 95330 95331 95332 95333 95334 95335 95336 95337 95338 95339 95340 95341 95342 95343 95344 95345 95346 95347 95348 95349 95350 95351 95352 95353 95354 95355 95356 95357 95358 95359 95360 95361 95362 95363 95364 95365 95366 95367 95368 95369 95370 95371 95372 95373 95374 95375 95376 95377 95378 95379 95380 95381 95382 95383 95384 95385 95386 95387 95388 95389 95390 95391 95392 95393 95394 95395 95396 95397 95398 95399 95400 95401 95402 95403 95404 95405 95406 95407 95408 95409 95410 95411 95412 95413 95414 95415 95416 95417 95418 95419 95420 95421 95422 95423 95424 95425 95426 95427 95428 95429 95430 95431 95432 95433 95434 95435 95436 95437 95438 95439 95440 95441 95442 95443 95444 95445 95446 95447 95448 95449 95450 95451 95452 95453 95454 95455 95456 95457 95458 95459 95460 95461 95462 95463 95464 95465 95466 95467 95468 95469 95470 95471 95472 95473 95474 95475 95476 95477 95478 95479 95480 95481 95482 95483 95484 95485 95486 95487 95488 95489 95490 95491 95492 95493 95494 95495 95496 95497 95498 95499 95500 95501 95502 95503 95504 95505 95506 95507 95508 95509 95510 95511 95512 95513 95514 95515 95516 95517 95518 95519 95520 95521 95522 95523 95524 95525 95526 95527 95528 95529 95530 95531 95532 95533 95534 95535 95536 95537 95538 95539 95540 95541 95542 95543 95544 95545 95546 95547 95548 95549 95550 95551 95552 95553 95554 95555 95556 95557 95558 95559 95560 95561 95562 95563 95564 95565 95566 95567 95568 95569 95570 95571 95572 95573 95574 95575 95576 95577 95578 95579 95580 95581 95582 95583 95584 95585 95586 95587 95588 95589 95590 95591 95592 95593 95594 95595 95596 | #define PragTyp_LOCKING_MODE 21 #define PragTyp_PAGE_COUNT 22 #define PragTyp_MMAP_SIZE 23 #define PragTyp_PAGE_SIZE 24 #define PragTyp_SECURE_DELETE 25 #define PragTyp_SHRINK_MEMORY 26 #define PragTyp_SOFT_HEAP_LIMIT 27 #define PragTyp_STATS 28 #define PragTyp_SYNCHRONOUS 29 #define PragTyp_TABLE_INFO 30 #define PragTyp_TEMP_STORE 31 #define PragTyp_TEMP_STORE_DIRECTORY 32 #define PragTyp_WAL_AUTOCHECKPOINT 33 #define PragTyp_WAL_CHECKPOINT 34 #define PragTyp_ACTIVATE_EXTENSIONS 35 #define PragTyp_HEXKEY 36 #define PragTyp_KEY 37 #define PragTyp_REKEY 38 #define PragTyp_LOCK_STATUS 39 #define PragTyp_PARSER_TRACE 40 #define PragFlag_NeedSchema 0x01 static const struct sPragmaNames { const char *const zName; /* Name of pragma */ u8 ePragTyp; /* PragTyp_XXX value */ u8 mPragFlag; /* Zero or more PragFlag_XXX values */ u32 iArg; /* Extra argument */ } aPragmaNames[] = { #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) { /* zName: */ "activate_extensions", /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "application_id", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) { /* zName: */ "auto_vacuum", /* ePragTyp: */ PragTyp_AUTO_VACUUM, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) { /* zName: */ "automatic_index", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_AutoIndex }, #endif { /* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlag: */ 0, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "cache_size", /* ePragTyp: */ PragTyp_CACHE_SIZE, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif { /* zName: */ "cache_spill", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CacheSpill }, { /* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "checkpoint_fullfsync", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CkptFullFSync }, #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) { /* zName: */ "compile_options", /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "count_changes", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CountRows }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN { /* zName: */ "data_store_directory", /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) { /* zName: */ "default_cache_size", /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { /* zName: */ "defer_foreign_keys", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_DeferFKs }, #endif { /* zName: */ "empty_result_callbacks", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_NullCallback }, #if !defined(SQLITE_OMIT_UTF16) { /* zName: */ "encoding", /* ePragTyp: */ PragTyp_ENCODING, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { /* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) { /* zName: */ "foreign_key_list", /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { /* zName: */ "foreign_keys", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ForeignKeys }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "freelist_count", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "full_column_names", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_FullColNames }, { /* zName: */ "fullfsync", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_FullFSync }, #if defined(SQLITE_HAS_CODEC) { /* zName: */ "hexkey", /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "hexrekey", /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_CHECK) { /* zName: */ "ignore_check_constraints", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_IgnoreChecks }, #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) { /* zName: */ "incremental_vacuum", /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "index_info", /* ePragTyp: */ PragTyp_INDEX_INFO, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, { /* zName: */ "index_list", /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) { /* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "journal_mode", /* ePragTyp: */ PragTyp_JOURNAL_MODE, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, { /* zName: */ "journal_size_limit", /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if defined(SQLITE_HAS_CODEC) { /* zName: */ "key", /* ePragTyp: */ PragTyp_KEY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "legacy_file_format", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_LegacyFileFmt }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE { /* zName: */ "lock_proxy_file", /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) { /* zName: */ "lock_status", /* ePragTyp: */ PragTyp_LOCK_STATUS, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "locking_mode", /* ePragTyp: */ PragTyp_LOCKING_MODE, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "max_page_count", /* ePragTyp: */ PragTyp_PAGE_COUNT, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, { /* zName: */ "mmap_size", /* ePragTyp: */ PragTyp_MMAP_SIZE, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "page_count", /* ePragTyp: */ PragTyp_PAGE_COUNT, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, { /* zName: */ "page_size", /* ePragTyp: */ PragTyp_PAGE_SIZE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if defined(SQLITE_DEBUG) { /* zName: */ "parser_trace", /* ePragTyp: */ PragTyp_PARSER_TRACE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "query_only", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_QueryOnly }, #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) { /* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif { /* zName: */ "read_uncommitted", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ReadUncommitted }, { /* zName: */ "recursive_triggers", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_RecTriggers }, #if defined(SQLITE_HAS_CODEC) { /* zName: */ "rekey", /* ePragTyp: */ PragTyp_REKEY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "reverse_unordered_selects", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ReverseOrder }, #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "schema_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "secure_delete", /* ePragTyp: */ PragTyp_SECURE_DELETE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif { /* zName: */ "short_column_names", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_ShortColNames }, { /* zName: */ "shrink_memory", /* ePragTyp: */ PragTyp_SHRINK_MEMORY, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "soft_heap_limit", /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, /* ePragFlag: */ 0, /* iArg: */ 0 }, #if defined(SQLITE_DEBUG) { /* zName: */ "sql_trace", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_SqlTrace }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "stats", /* ePragTyp: */ PragTyp_STATS, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "synchronous", /* ePragTyp: */ PragTyp_SYNCHRONOUS, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) { /* zName: */ "table_info", /* ePragTyp: */ PragTyp_TABLE_INFO, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "temp_store", /* ePragTyp: */ PragTyp_TEMP_STORE, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "temp_store_directory", /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) { /* zName: */ "user_version", /* ePragTyp: */ PragTyp_HEADER_VALUE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if defined(SQLITE_DEBUG) { /* zName: */ "vdbe_addoptrace", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_VdbeAddopTrace }, { /* zName: */ "vdbe_debug", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, { /* zName: */ "vdbe_listing", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_VdbeListing }, { /* zName: */ "vdbe_trace", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_VdbeTrace }, #endif #if !defined(SQLITE_OMIT_WAL) { /* zName: */ "wal_autocheckpoint", /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, /* ePragFlag: */ 0, /* iArg: */ 0 }, { /* zName: */ "wal_checkpoint", /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, /* ePragFlag: */ PragFlag_NeedSchema, /* iArg: */ 0 }, #endif { /* zName: */ "writable_schema", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, }; /* Number of pragmas: 56 on by default, 68 total. */ /* End of the automatically generated pragma table. ***************************************************************************/ /* ** Interpret the given string as a safety level. Return 0 for OFF, ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or ** unrecognized string argument. The FULL option is disallowed |
︙ | ︙ | |||
95474 95475 95476 95477 95478 95479 95480 95481 95482 95483 95484 95485 95486 95487 | if( rc<0 ){ upr = mid - 1; }else{ lwr = mid + 1; } } if( lwr>upr ) goto pragma_out; /* Jump to the appropriate pragma handler */ switch( aPragmaNames[mid].ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* ** PRAGMA [database.]default_cache_size | > > > > > | 95914 95915 95916 95917 95918 95919 95920 95921 95922 95923 95924 95925 95926 95927 95928 95929 95930 95931 95932 | if( rc<0 ){ upr = mid - 1; }else{ lwr = mid + 1; } } if( lwr>upr ) goto pragma_out; /* Make sure the database schema is loaded if the pragma requires that */ if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } /* Jump to the appropriate pragma handler */ switch( aPragmaNames[mid].ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* ** PRAGMA [database.]default_cache_size |
︙ | ︙ | |||
95508 95509 95510 95511 95512 95513 95514 | { OP_Subtract, 1, 2, 1}, { OP_IfPos, 1, 8, 0}, { OP_Integer, 0, 1, 0}, /* 6 */ { OP_Noop, 0, 0, 0}, { OP_ResultRow, 1, 1, 0}, }; int addr; | < | 95953 95954 95955 95956 95957 95958 95959 95960 95961 95962 95963 95964 95965 95966 | { OP_Subtract, 1, 2, 1}, { OP_IfPos, 1, 8, 0}, { OP_Integer, 0, 1, 0}, /* 6 */ { OP_Noop, 0, 0, 0}, { OP_ResultRow, 1, 1, 0}, }; int addr; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); |
︙ | ︙ | |||
95604 95605 95606 95607 95608 95609 95610 | ** ** PRAGMA [database.]page_count ** ** Return the number of pages in the specified database. */ case PragTyp_PAGE_COUNT: { int iReg; | < | 96048 96049 96050 96051 96052 96053 96054 96055 96056 96057 96058 96059 96060 96061 | ** ** PRAGMA [database.]page_count ** ** Return the number of pages in the specified database. */ case PragTyp_PAGE_COUNT: { int iReg; sqlite3CodeVerifySchema(pParse, iDb); iReg = ++pParse->nMem; if( sqlite3Tolower(zLeft[0])=='p' ){ sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); }else{ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3AbsInt32(sqlite3Atoi(zRight))); |
︙ | ︙ | |||
95677 95678 95679 95680 95681 95682 95683 | ** PRAGMA [database.]journal_mode = ** (delete|persist|off|truncate|memory|wal|off) */ case PragTyp_JOURNAL_MODE: { int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ int ii; /* Loop counter */ | < < < < < < < < | 96120 96121 96122 96123 96124 96125 96126 96127 96128 96129 96130 96131 96132 96133 | ** PRAGMA [database.]journal_mode = ** (delete|persist|off|truncate|memory|wal|off) */ case PragTyp_JOURNAL_MODE: { int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ int ii; /* Loop counter */ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); if( zRight==0 ){ /* If there is no "=MODE" part of the pragma, do a query for the ** current mode */ eMode = PAGER_JOURNALMODE_QUERY; |
︙ | ︙ | |||
95750 95751 95752 95753 95754 95755 95756 | ** Get or set the value of the database 'auto-vacuum' parameter. ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_AUTO_VACUUM: { Btree *pBt = pDb->pBt; assert( pBt!=0 ); | < < < < < < < < < | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < | 96185 96186 96187 96188 96189 96190 96191 96192 96193 96194 96195 96196 96197 96198 96199 96200 96201 96202 96203 96204 96205 96206 96207 96208 96209 96210 96211 96212 96213 96214 96215 96216 96217 96218 96219 96220 96221 96222 96223 96224 96225 96226 96227 96228 96229 96230 96231 96232 96233 96234 96235 96236 96237 96238 96239 96240 96241 96242 96243 96244 96245 96246 | ** Get or set the value of the database 'auto-vacuum' parameter. ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_AUTO_VACUUM: { Btree *pBt = pDb->pBt; assert( pBt!=0 ); if( !zRight ){ returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); }else{ int eAuto = getAutoVacuum(zRight); assert( eAuto>=0 && eAuto<=2 ); db->nextAutovac = (u8)eAuto; /* Call SetAutoVacuum() to set initialize the internal auto and ** incr-vacuum flags. This is required in case this connection ** creates the database file. It is important that it is created ** as an auto-vacuum capable db. */ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ /* When setting the auto_vacuum mode to either "full" or ** "incremental", write the value of meta[6] in the database ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ static const VdbeOpList setMeta6[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, { OP_If, 1, 0, 0}, /* 2 */ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ { OP_Integer, 0, 1, 0}, /* 4 */ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ }; int iAddr; iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); sqlite3VdbeChangeP1(v, iAddr, iDb); sqlite3VdbeChangeP1(v, iAddr+1, iDb); sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); sqlite3VdbeChangeP1(v, iAddr+5, iDb); sqlite3VdbeUsesBtree(v, iDb); } } break; } #endif /* ** PRAGMA [database.]incremental_vacuum(N) ** ** Do N steps of incremental vacuuming on a database. */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_INCREMENTAL_VACUUM: { int iLimit, addr; if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ iLimit = 0x7fffffff; } sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); sqlite3VdbeAddOp1(v, OP_ResultRow, 1); |
︙ | ︙ | |||
95839 95840 95841 95842 95843 95844 95845 | ** page cache size. The second form sets the local ** page cache size value. If N is positive then that is the ** number of pages in the cache. If N is negative, then the ** number of pages is adjusted so that the cache uses -N kibibytes ** of memory. */ case PragTyp_CACHE_SIZE: { | < | 96260 96261 96262 96263 96264 96265 96266 96267 96268 96269 96270 96271 96272 96273 | ** page cache size. The second form sets the local ** page cache size value. If N is positive then that is the ** number of pages in the cache. If N is negative, then the ** number of pages is adjusted so that the cache uses -N kibibytes ** of memory. */ case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
︙ | ︙ | |||
96060 96061 96062 96063 96064 96065 96066 | ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the ** default value will be restored the next time the database is ** opened. */ case PragTyp_SYNCHRONOUS: { | < | 96480 96481 96482 96483 96484 96485 96486 96487 96488 96489 96490 96491 96492 96493 | ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the ** default value will be restored the next time the database is ** opened. */ case PragTyp_SYNCHRONOUS: { if( !zRight ){ returnSingleInt(pParse, "synchronous", pDb->safety_level-1); }else{ if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ |
︙ | ︙ | |||
96122 96123 96124 96125 96126 96127 96128 | ** name: Column name ** type: Column declaration type. ** notnull: True if 'NOT NULL' is part of column declaration ** dflt_value: The default value for the column, if any. */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; | < | 96541 96542 96543 96544 96545 96546 96547 96548 96549 96550 96551 96552 96553 96554 | ** name: Column name ** type: Column declaration type. ** notnull: True if 'NOT NULL' is part of column declaration ** dflt_value: The default value for the column, if any. */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ int i, k; int nHidden = 0; Column *pCol; Index *pPk; for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} |
︙ | ︙ | |||
96168 96169 96170 96171 96172 96173 96174 96175 96176 96177 96178 | } sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } } break; case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | 96586 96587 96588 96589 96590 96591 96592 96593 96594 96595 96596 96597 96598 96599 96600 96601 96602 96603 96604 96605 96606 96607 96608 96609 96610 96611 96612 96613 96614 96615 96616 96617 96618 96619 96620 96621 96622 96623 96624 96625 96626 96627 96628 96629 96630 96631 96632 96633 | } sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } } break; case PragTyp_STATS: { Index *pIdx; HashElem *i; v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 4); pParse->nMem = 4; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC); for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0); sqlite3VdbeAddOp2(v, OP_Null, 0, 2); sqlite3VdbeAddOp2(v, OP_Integer, (int)sqlite3LogEstToInt(pTab->szTabRow), 3); sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3); sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); } } } break; case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); |
︙ | ︙ | |||
96198 96199 96200 96201 96202 96203 96204 | } } break; case PragTyp_INDEX_LIST: if( zRight ){ Index *pIdx; Table *pTab; | | < < < | | | | | | | | | | | < < < < | 96645 96646 96647 96648 96649 96650 96651 96652 96653 96654 96655 96656 96657 96658 96659 96660 96661 96662 96663 96664 96665 96666 96667 96668 96669 96670 96671 96672 96673 96674 96675 96676 96677 96678 96679 96680 | } } break; case PragTyp_INDEX_LIST: if( zRight ){ Index *pIdx; Table *pTab; int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } } } break; case PragTyp_DATABASE_LIST: { int i; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC); for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ) continue; |
︙ | ︙ | |||
96265 96266 96267 96268 96269 96270 96271 | break; #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ #ifndef SQLITE_OMIT_FOREIGN_KEY case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ FKey *pFK; Table *pTab; | < | 96705 96706 96707 96708 96709 96710 96711 96712 96713 96714 96715 96716 96717 96718 | break; #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ #ifndef SQLITE_OMIT_FOREIGN_KEY case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ FKey *pFK; Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 8); |
︙ | ︙ | |||
96327 96328 96329 96330 96331 96332 96333 | int regResult; /* 3 registers to hold a result row */ int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ | < | 96766 96767 96768 96769 96770 96771 96772 96773 96774 96775 96776 96777 96778 96779 | int regResult; /* 3 registers to hold a result row */ int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ regResult = pParse->nMem+1; pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 4); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
︙ | ︙ | |||
96355 96356 96357 96358 96359 96360 96361 | if( pTab==0 || pTab->pFKey==0 ) continue; sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, P4_TRANSIENT); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ | | | > | < > | | > | | > | | | | > | 96793 96794 96795 96796 96797 96798 96799 96800 96801 96802 96803 96804 96805 96806 96807 96808 96809 96810 96811 96812 96813 96814 96815 96816 96817 96818 96819 96820 96821 96822 96823 96824 96825 96826 96827 96828 96829 96830 96831 96832 96833 96834 96835 96836 96837 96838 96839 96840 96841 96842 96843 96844 96845 96846 96847 96848 96849 96850 96851 96852 96853 96854 96855 96856 96857 96858 96859 96860 96861 96862 96863 96864 | if( pTab==0 || pTab->pFKey==0 ) continue; sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, P4_TRANSIENT); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); }else{ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); } }else{ k = 0; break; } } assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTab<i ) pParse->nTab = i; addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); pIdx = 0; aiCols = 0; if( pParent ){ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); assert( x==0 ); } addrOk = sqlite3VdbeMakeLabel(v); if( pParent && pIdx==0 ){ int iKey = pFK->aCol[0].iFrom; assert( iKey>=0 && iKey<pTab->nCol ); if( iKey!=pTab->iPKey ){ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, sqlite3VdbeCurrentAddr(v)+3); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ for(j=0; j<pFK->nCol; j++){ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); } if( pParent ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); } } sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, pFK->zTo, P4_TRANSIENT); sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); sqlite3VdbeResolveLabel(v, addrOk); |
︙ | ︙ | |||
96488 96489 96490 96491 96492 96493 96494 | ** to -1 here, to indicate that the VDBE should verify the integrity ** of all attached databases. */ assert( iDb>=0 ); assert( iDb==0 || pId2->z ); if( pId2->z==0 ) iDb = -1; /* Initialize the VDBE program */ | < | 96930 96931 96932 96933 96934 96935 96936 96937 96938 96939 96940 96941 96942 96943 | ** to -1 here, to indicate that the VDBE should verify the integrity ** of all attached databases. */ assert( iDb>=0 ); assert( iDb==0 || pId2->z ); if( pId2->z==0 ) iDb = -1; /* Initialize the VDBE program */ pParse->nMem = 6; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ |
︙ | ︙ | |||
96812 96813 96814 96815 96816 96817 96818 | if( zRight ){ if( sqlite3StrICmp(zRight, "full")==0 ){ eMode = SQLITE_CHECKPOINT_FULL; }else if( sqlite3StrICmp(zRight, "restart")==0 ){ eMode = SQLITE_CHECKPOINT_RESTART; } } | < | 97253 97254 97255 97256 97257 97258 97259 97260 97261 97262 97263 97264 97265 97266 | if( zRight ){ if( sqlite3StrICmp(zRight, "full")==0 ){ eMode = SQLITE_CHECKPOINT_FULL; }else if( sqlite3StrICmp(zRight, "restart")==0 ){ eMode = SQLITE_CHECKPOINT_RESTART; } } sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC); sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); |
︙ | ︙ | |||
96932 96933 96934 96935 96936 96937 96938 | } case PragTyp_REKEY: { if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); break; } case PragTyp_HEXKEY: { if( zRight ){ | > | | < | | | 97372 97373 97374 97375 97376 97377 97378 97379 97380 97381 97382 97383 97384 97385 97386 97387 97388 97389 97390 97391 | } case PragTyp_REKEY: { if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); break; } case PragTyp_HEXKEY: { if( zRight ){ u8 iByte; int i; char zKey[40]; for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); if( (i&1)!=0 ) zKey[i/2] = iByte; } if( (zLeft[3] & 0xf)==0xb ){ sqlite3_key_v2(db, zDb, zKey, i/2); }else{ sqlite3_rekey_v2(db, zDb, zKey, i/2); } } |
︙ | ︙ | |||
98911 98912 98913 98914 98915 98916 98917 98918 98919 98920 98921 98922 98923 98924 98925 98926 98927 98928 98929 98930 98931 98932 | sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); } } /* ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. ** ** The declaration type is the exact datatype definition extracted from the ** original CREATE TABLE statement if the expression is a column. The ** declaration type for a ROWID field is INTEGER. Exactly when an expression ** is considered a column can be complex in the presence of subqueries. The ** result-set expression in all of the following SELECT statements is ** considered a column by this function. ** ** SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl); ** SELECT abc FROM (SELECT col AS abc FROM tbl); ** ** The declaration type for any expression other than a column is NULL. */ | > > > > > > > > | | | | > | | | > > > > > > > > | < > > | 99351 99352 99353 99354 99355 99356 99357 99358 99359 99360 99361 99362 99363 99364 99365 99366 99367 99368 99369 99370 99371 99372 99373 99374 99375 99376 99377 99378 99379 99380 99381 99382 99383 99384 99385 99386 99387 99388 99389 99390 99391 99392 99393 99394 99395 99396 99397 99398 99399 99400 99401 99402 99403 99404 99405 99406 99407 99408 99409 99410 99411 | sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); } } /* ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. ** ** Also try to estimate the size of the returned value and return that ** result in *pEstWidth. ** ** The declaration type is the exact datatype definition extracted from the ** original CREATE TABLE statement if the expression is a column. The ** declaration type for a ROWID field is INTEGER. Exactly when an expression ** is considered a column can be complex in the presence of subqueries. The ** result-set expression in all of the following SELECT statements is ** considered a column by this function. ** ** SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl; ** SELECT (SELECT col FROM tbl); ** SELECT abc FROM (SELECT col AS abc FROM tbl); ** ** The declaration type for any expression other than a column is NULL. ** ** This routine has either 3 or 6 parameters depending on whether or not ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. */ #ifdef SQLITE_ENABLE_COLUMN_METADATA # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) static const char *columnTypeImpl( NameContext *pNC, Expr *pExpr, const char **pzOrigDb, const char **pzOrigTab, const char **pzOrigCol, u8 *pEstWidth ){ char const *zOrigDb = 0; char const *zOrigTab = 0; char const *zOrigCol = 0; #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ # define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) static const char *columnTypeImpl( NameContext *pNC, Expr *pExpr, u8 *pEstWidth ){ #endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */ char const *zType = 0; int j; u8 estWidth = 1; if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0; switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { /* The expression is a column. Locate the table the column is being ** extracted from in NameContext.pSrcList. This table may be real ** database table or a subquery. */ |
︙ | ︙ | |||
99000 99001 99002 99003 99004 99005 99006 | ** test case misc2.2.2) - it always evaluates to NULL. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; | | > | | > | | > > > > > > > > | | > | | | | | > > | 99458 99459 99460 99461 99462 99463 99464 99465 99466 99467 99468 99469 99470 99471 99472 99473 99474 99475 99476 99477 99478 99479 99480 99481 99482 99483 99484 99485 99486 99487 99488 99489 99490 99491 99492 99493 99494 99495 99496 99497 99498 99499 99500 99501 99502 99503 99504 99505 99506 99507 99508 99509 99510 99511 99512 99513 99514 99515 99516 99517 99518 99519 99520 99521 99522 99523 99524 99525 99526 99527 99528 99529 99530 99531 | ** test case misc2.2.2) - it always evaluates to NULL. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); } }else if( ALWAYS(pTab->pSchema) ){ /* A real table */ assert( !pS ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); #ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ zType = pTab->aCol[iCol].zType; zOrigCol = pTab->aCol[iCol].zName; estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; if( pNC->pParse ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); zOrigDb = pNC->pParse->db->aDb[iDb].zName; } #else if( iCol<0 ){ zType = "INTEGER"; }else{ zType = pTab->aCol[iCol].zType; estWidth = pTab->aCol[iCol].szEst; } #endif } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: { /* The expression is a sub-select. Return the declaration type and ** origin info for the single column in the result set of the SELECT ** statement. */ NameContext sNC; Select *pS = pExpr->x.pSelect; Expr *p = pS->pEList->a[0].pExpr; assert( ExprHasProperty(pExpr, EP_xIsSelect) ); sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); break; } #endif } #ifdef SQLITE_ENABLE_COLUMN_METADATA if( pzOrigDb ){ assert( pzOrigTab && pzOrigCol ); *pzOrigDb = zOrigDb; *pzOrigTab = zOrigTab; *pzOrigCol = zOrigCol; } #endif if( pEstWidth ) *pEstWidth = estWidth; return zType; } /* ** Generate code that will tell the VDBE the declaration types of columns ** in the result set. */ |
︙ | ︙ | |||
99072 99073 99074 99075 99076 99077 99078 | for(i=0; i<pEList->nExpr; i++){ Expr *p = pEList->a[i].pExpr; const char *zType; #ifdef SQLITE_ENABLE_COLUMN_METADATA const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; | | | | | 99543 99544 99545 99546 99547 99548 99549 99550 99551 99552 99553 99554 99555 99556 99557 99558 99559 99560 99561 99562 99563 99564 99565 99566 99567 99568 99569 99570 99571 | for(i=0; i<pEList->nExpr; i++){ Expr *p = pEList->a[i].pExpr; const char *zType; #ifdef SQLITE_ENABLE_COLUMN_METADATA const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0); /* The vdbe must make its own copy of the column-type and other ** column specific strings, in case the schema is reset before this ** virtual machine is deleted. */ sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else zType = columnType(&sNC, p, 0, 0, 0, 0); #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } /* ** Generate code that will tell the VDBE the names of columns ** in the result set. This information is used to provide the ** azCol[] values in the callback. */ |
︙ | ︙ | |||
99275 99276 99277 99278 99279 99280 99281 | ** routine goes through and adds the types and collations. ** ** This routine requires that all identifiers in the SELECT ** statement be resolved. */ static void selectAddColumnTypeAndCollation( Parse *pParse, /* Parsing contexts */ | | < > | | | > > | 99746 99747 99748 99749 99750 99751 99752 99753 99754 99755 99756 99757 99758 99759 99760 99761 99762 99763 99764 99765 99766 99767 99768 99769 99770 99771 99772 99773 99774 99775 99776 99777 99778 99779 99780 99781 99782 99783 99784 99785 99786 99787 99788 99789 99790 | ** routine goes through and adds the types and collations. ** ** This routine requires that all identifiers in the SELECT ** statement be resolved. */ static void selectAddColumnTypeAndCollation( Parse *pParse, /* Parsing contexts */ Table *pTab, /* Add column type information to this table */ Select *pSelect /* SELECT used to determine types and collations */ ){ sqlite3 *db = pParse->db; NameContext sNC; Column *pCol; CollSeq *pColl; int i; Expr *p; struct ExprList_item *a; u64 szAll = 0; assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); if( db->mallocFailed ) return; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ p = a[i].pExpr; pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } pTab->szTabRow = sqlite3LogEst(szAll*4); } /* ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ |
︙ | ︙ | |||
99331 99332 99333 99334 99335 99336 99337 | return 0; } /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ assert( db->lookaside.bEnabled==0 ); pTab->nRef = 1; pTab->zName = 0; | | | | 99804 99805 99806 99807 99808 99809 99810 99811 99812 99813 99814 99815 99816 99817 99818 99819 99820 | return 0; } /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ assert( db->lookaside.bEnabled==0 ); pTab->nRef = 1; pTab->zName = 0; pTab->nRowEst = 1048576; selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab, pSelect); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); return 0; } return pTab; } |
︙ | ︙ | |||
101245 101246 101247 101248 101249 101250 101251 | /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); sqlite3WalkSelect(pWalker, pSel); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; | | | | 101718 101719 101720 101721 101722 101723 101724 101725 101726 101727 101728 101729 101730 101731 101732 101733 101734 101735 101736 | /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); sqlite3WalkSelect(pWalker, pSel); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; pTab->nRowEst = 1048576; pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; |
︙ | ︙ | |||
101533 101534 101535 101536 101537 101538 101539 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; assert( pSel ); while( pSel->pPrior ) pSel = pSel->pPrior; | | | 102006 102007 102008 102009 102010 102011 102012 102013 102014 102015 102016 102017 102018 102019 102020 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; assert( pSel ); while( pSel->pPrior ) pSel = pSel->pPrior; selectAddColumnTypeAndCollation(pParse, pTab, pSel); } } } return WRC_Continue; } #endif |
︙ | ︙ | |||
102448 102449 102450 102451 102452 102453 102454 | KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ Index *pBest = 0; /* Best index found so far */ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); | | < < < < < < > > | > > > > | | 102921 102922 102923 102924 102925 102926 102927 102928 102929 102930 102931 102932 102933 102934 102935 102936 102937 102938 102939 102940 102941 102942 102943 102944 102945 102946 102947 102948 102949 102950 102951 102952 102953 | KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ Index *pBest = 0; /* Best index found so far */ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); /* Search for the index that has the lowest scan cost. ** ** (2011-04-15) Do not do a full scan of an unordered index. ** ** (2013-10-03) Do not count the entires in a partial index. ** ** In practice the KeyInfo structure will not be used. It is only ** passed to keep OP_OpenRead happy. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->bUnordered==0 && pIdx->szIdxRow<pTab->szTabRow && pIdx->pPartIdxWhere==0 && (!pBest || pIdx->szIdxRow<pBest->szIdxRow) ){ pBest = pIdx; } } if( pBest ){ iRoot = pBest->tnum; pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest); } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb); if( pKeyInfo ){ |
︙ | ︙ | |||
103044 103045 103046 103047 103048 103049 103050 | && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } /* Ensure the table name matches database name and that the table exists */ if( db->mallocFailed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); | | | | 103517 103518 103519 103520 103521 103522 103523 103524 103525 103526 103527 103528 103529 103530 103531 103532 | && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } /* Ensure the table name matches database name and that the table exists */ if( db->mallocFailed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName); if( sqlite3FixSrcList(&sFix, pTableName) ){ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ if( db->init.iDb==1 ){ /* Ticket #3810. |
︙ | ︙ | |||
103187 103188 103189 103190 103191 103192 103193 | pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); | | | > > | 103660 103661 103662 103663 103664 103665 103666 103667 103668 103669 103670 103671 103672 103673 103674 103675 103676 103677 | pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) || sqlite3FixExpr(&sFix, pTrig->pWhen) ){ goto triggerfinish_cleanup; } /* if we are not initializing, ** build the sqlite_master entry */ if( !db->init.busy ){ |
︙ | ︙ | |||
104779 104780 104781 104782 104783 104784 104785 | } } return vacuumFinalize(db, pStmt, pzErrMsg); } /* | | | | | | > > | > > > > > > > > > > > > > > > > > > | 105254 105255 105256 105257 105258 105259 105260 105261 105262 105263 105264 105265 105266 105267 105268 105269 105270 105271 105272 105273 105274 105275 105276 105277 105278 105279 105280 105281 105282 105283 105284 105285 105286 105287 105288 105289 105290 105291 105292 105293 105294 105295 | } } return vacuumFinalize(db, pStmt, pzErrMsg); } /* ** The VACUUM command is used to clean up the database, ** collapse free space, etc. It is modelled after the VACUUM command ** in PostgreSQL. The VACUUM command works as follows: ** ** (1) Create a new transient database file ** (2) Copy all content from the database being vacuumed into ** the new transient database file ** (3) Copy content from the transient database back into the ** original database. ** ** The transient database requires temporary disk space approximately ** equal to the size of the original database. The copy operation of ** step (3) requires additional temporary disk space approximately equal ** to the size of the original database for the rollback journal. ** Hence, temporary disk space that is approximately 2x the size of the ** orginal database is required. Every page of the database is written ** approximately 3 times: Once for step (2) and twice for step (3). ** Two writes per page are required in step (3) because the original ** database content must be written into the rollback journal prior to ** overwriting the database with the vacuumed content. ** ** Only 1x temporary space and only 1x writes would be required if ** the copy of step (3) were replace by deleting the original database ** and renaming the transient database as the original. But that will ** not work if other processes are attached to the original database. ** And a power loss in between deleting the original and renaming the ** transient would cause the database file to appear to be deleted ** following reboot. */ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); sqlite3VdbeUsesBtree(v, 0); } |
︙ | ︙ | |||
106204 106205 106206 106207 106208 106209 106210 | typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; | < < < < < < < < < < < < < < < < < < < < | 106699 106700 106701 106702 106703 106704 106705 106706 106707 106708 106709 106710 106711 106712 | typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; /* ** This object contains information needed to implement a single nested ** loop in WHERE clause. ** ** Contrast this object with WhereLoop. This object describes the ** implementation of the loop. WhereLoop describes the algorithm. ** This object contains a pointer to the WhereLoop algorithm as one of |
︙ | ︙ | |||
106288 106289 106290 106291 106292 106293 106294 | Bitmask prereq; /* Bitmask of other loops that must run first */ Bitmask maskSelf; /* Bitmask identifying table iTab */ #ifdef SQLITE_DEBUG char cId; /* Symbolic ID of this loop for debugging use */ #endif u8 iTab; /* Position in FROM clause of table for this loop */ u8 iSortIdx; /* Sorting index number. 0==None */ | | | | | 106763 106764 106765 106766 106767 106768 106769 106770 106771 106772 106773 106774 106775 106776 106777 106778 106779 | Bitmask prereq; /* Bitmask of other loops that must run first */ Bitmask maskSelf; /* Bitmask identifying table iTab */ #ifdef SQLITE_DEBUG char cId; /* Symbolic ID of this loop for debugging use */ #endif u8 iTab; /* Position in FROM clause of table for this loop */ u8 iSortIdx; /* Sorting index number. 0==None */ LogEst rSetup; /* One-time setup cost (ex: create transient index) */ LogEst rRun; /* Cost of running each loop */ LogEst nOut; /* Estimated number of output rows */ union { struct { /* Information for internal btree tables */ int nEq; /* Number of equality constraints */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ |
︙ | ︙ | |||
106320 106321 106322 106323 106324 106325 106326 | /* This object holds the prerequisites and the cost of running a ** subquery on one operand of an OR operator in the WHERE clause. ** See WhereOrSet for additional information */ struct WhereOrCost { Bitmask prereq; /* Prerequisites */ | | | | 106795 106796 106797 106798 106799 106800 106801 106802 106803 106804 106805 106806 106807 106808 106809 106810 | /* This object holds the prerequisites and the cost of running a ** subquery on one operand of an OR operator in the WHERE clause. ** See WhereOrSet for additional information */ struct WhereOrCost { Bitmask prereq; /* Prerequisites */ LogEst rRun; /* Cost of running this subquery */ LogEst nOut; /* Number of outputs for this subquery */ }; /* The WhereOrSet object holds a set of possible WhereOrCosts that ** correspond to the subquery(s) of OR-clause processing. Only the ** best N_OR_COST elements are retained. */ #define N_OR_COST 3 |
︙ | ︙ | |||
106359 106360 106361 106362 106363 106364 106365 | ** of length 2. And so forth until the length of WherePaths equals the ** number of nodes in the FROM clause. The best (lowest cost) WherePath ** at the end is the choosen query plan. */ struct WherePath { Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ | | | | 106834 106835 106836 106837 106838 106839 106840 106841 106842 106843 106844 106845 106846 106847 106848 106849 | ** of length 2. And so forth until the length of WherePaths equals the ** number of nodes in the FROM clause. The best (lowest cost) WherePath ** at the end is the choosen query plan. */ struct WherePath { Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ LogEst nRow; /* Estimated number of rows generated by this path */ LogEst rCost; /* Total cost of this path */ u8 isOrdered; /* True if this path satisfies ORDER BY */ u8 isOrderedValid; /* True if the isOrdered field is valid */ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ }; /* ** The query generator uses an array of instances of this structure to |
︙ | ︙ | |||
106426 106427 106428 106429 106430 106431 106432 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; | | | 106901 106902 106903 106904 106905 106906 106907 106908 106909 106910 106911 106912 106913 106914 106915 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; LogEst truthProb; /* Probability of truth for this expression */ u16 eOperator; /* A WO_xx value describing <op> */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ }; |
︙ | ︙ | |||
106574 106575 106576 106577 106578 106579 106580 | struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set. DISTINCT operates on these */ WhereLoop *pLoops; /* List of all WhereLoop objects */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ | | | 107049 107050 107051 107052 107053 107054 107055 107056 107057 107058 107059 107060 107061 107062 107063 | struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set. DISTINCT operates on these */ WhereLoop *pLoops; /* List of all WhereLoop objects */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ LogEst nRowOut; /* Estimated number of output rows */ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ u8 bOBSat; /* ORDER BY satisfied by indices */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ int iTop; /* The very beginning of the WHERE loop */ |
︙ | ︙ | |||
106634 106635 106636 106637 106638 106639 106640 | #define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */ #define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */ #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */ #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */ #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ | < < < < < < < < < < < < < < < | | 107109 107110 107111 107112 107113 107114 107115 107116 107117 107118 107119 107120 107121 107122 107123 107124 107125 107126 107127 | #define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */ #define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */ #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */ #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */ #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ /* ** Return the estimated number of output rows from a WHERE clause */ SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){ return sqlite3LogEstToInt(pWInfo->nRowOut); } /* ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this ** WHERE clause returns outputs for DISTINCT processing. */ SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){ |
︙ | ︙ | |||
106715 106716 106717 106718 106719 106720 106721 | ** The new entry might overwrite an existing entry, or it might be ** appended, or it might be discarded. Do whatever is the right thing ** so that pSet keeps the N_OR_COST best entries seen so far. */ static int whereOrInsert( WhereOrSet *pSet, /* The WhereOrSet to be updated */ Bitmask prereq, /* Prerequisites of the new entry */ | | | | 107175 107176 107177 107178 107179 107180 107181 107182 107183 107184 107185 107186 107187 107188 107189 107190 | ** The new entry might overwrite an existing entry, or it might be ** appended, or it might be discarded. Do whatever is the right thing ** so that pSet keeps the N_OR_COST best entries seen so far. */ static int whereOrInsert( WhereOrSet *pSet, /* The WhereOrSet to be updated */ Bitmask prereq, /* Prerequisites of the new entry */ LogEst rRun, /* Run-cost of the new entry */ LogEst nOut /* Number of outputs for the new entry */ ){ u16 i; WhereOrCost *p; for(i=pSet->n, p=pSet->a; i>0; i--, p++){ if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ goto whereOrInsert_done; } |
︙ | ︙ | |||
106801 106802 106803 106804 106805 106806 106807 | } } if( pWC->a!=pWC->aStatic ){ sqlite3DbFree(db, pWC->a); } } | < < < | 107261 107262 107263 107264 107265 107266 107267 107268 107269 107270 107271 107272 107273 107274 | } } if( pWC->a!=pWC->aStatic ){ sqlite3DbFree(db, pWC->a); } } /* ** Add a single new WhereTerm entry to the WhereClause object pWC. ** The new WhereTerm object is constructed from Expr p and with wtFlags. ** The index in pWC->a[] of the new WhereTerm is returned on success. ** 0 is returned if the new WhereTerm could not be added due to a memory ** allocation error. The memory allocation failure will be recorded in ** the db->mallocFailed flag so that higher-level functions can detect it. |
︙ | ︙ | |||
106846 106847 106848 106849 106850 106851 106852 | if( pOld!=pWC->aStatic ){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; if( p && ExprHasProperty(p, EP_Unlikely) ){ | | | 107303 107304 107305 107306 107307 107308 107309 107310 107311 107312 107313 107314 107315 107316 107317 | if( pOld!=pWC->aStatic ){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; if( p && ExprHasProperty(p, EP_Unlikely) ){ pTerm->truthProb = sqlite3LogEst(p->iTable) - 99; }else{ pTerm->truthProb = -1; } pTerm->pExpr = sqlite3ExprSkipCollate(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; |
︙ | ︙ | |||
108110 108111 108112 108113 108114 108115 108116 | return 1; } } return 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 108567 108568 108569 108570 108571 108572 108573 108574 108575 108576 108577 108578 108579 108580 108581 108582 108583 108584 108585 108586 | return 1; } } return 0; } /* ** Estimate the logarithm of the input value to base 2. */ static LogEst estLog(LogEst N){ LogEst x = sqlite3LogEst(N); return x>33 ? x - 33 : 0; } /* ** Two routines for printing the content of an sqlite3_index_info ** structure. Used for testing and debugging only. If neither ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines |
︙ | ︙ | |||
108594 108595 108596 108597 108598 108599 108600 108601 108602 108603 108604 108605 108606 108607 | IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ int iMin = 0; /* Smallest sample not yet tested */ int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ int iTest; /* Next sample to test */ int res; /* Result of comparison operation */ assert( pRec!=0 || pParse->db->mallocFailed ); if( pRec==0 ) return; iCol = pRec->nField - 1; assert( pIdx->nSample>0 ); assert( pRec->nField>0 && iCol<pIdx->nSampleCol ); do{ iTest = (iMin+i)/2; | > > > | 108988 108989 108990 108991 108992 108993 108994 108995 108996 108997 108998 108999 109000 109001 109002 109003 109004 | IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ int iMin = 0; /* Smallest sample not yet tested */ int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ int iTest; /* Next sample to test */ int res; /* Result of comparison operation */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 || pParse->db->mallocFailed ); if( pRec==0 ) return; iCol = pRec->nField - 1; assert( pIdx->nSample>0 ); assert( pRec->nField>0 && iCol<pIdx->nSampleCol ); do{ iTest = (iMin+i)/2; |
︙ | ︙ | |||
108691 108692 108693 108694 108695 108696 108697 | ** then nEq is set to 1 (as the range restricted column, b, is the second ** left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** ** then nEq is set to 0. ** | | | | | | | | 109088 109089 109090 109091 109092 109093 109094 109095 109096 109097 109098 109099 109100 109101 109102 109103 109104 109105 109106 109107 109108 109109 109110 109111 109112 109113 109114 109115 109116 109117 109118 109119 109120 109121 109122 109123 109124 109125 109126 | ** then nEq is set to 1 (as the range restricted column, b, is the second ** left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** ** then nEq is set to 0. ** ** When this function is called, *pnOut is set to the sqlite3LogEst() of the ** number of rows that the index scan is expected to visit without ** considering the range constraints. If nEq is 0, this is the number of ** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced) ** to account for the range contraints pLower and pUpper. ** ** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be ** used, each range inequality reduces the search space by a factor of 4. ** Hence a pair of constraints (x>? AND x<?) reduces the expected number of ** rows visited by a factor of 16. */ static int whereRangeScanEst( Parse *pParse, /* Parsing & code generating context */ WhereLoopBuilder *pBuilder, WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ ){ int rc = SQLITE_OK; int nOut = pLoop->nOut; LogEst nNew; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 Index *p = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; if( p->nSample>0 && nEq==pBuilder->nRecValid && nEq<p->nSampleCol && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){ UnpackedRecord *pRec = pBuilder->pRec; |
︙ | ︙ | |||
108796 108797 108798 108799 108800 108801 108802 | nOut--; } } pBuilder->pRec = pRec; if( rc==SQLITE_OK ){ if( iUpper>iLower ){ | | | | | | | | 109193 109194 109195 109196 109197 109198 109199 109200 109201 109202 109203 109204 109205 109206 109207 109208 109209 109210 109211 109212 109213 109214 109215 109216 109217 109218 109219 109220 109221 109222 109223 109224 109225 109226 109227 109228 109229 109230 109231 109232 109233 109234 109235 109236 109237 109238 | nOut--; } } pBuilder->pRec = pRec; if( rc==SQLITE_OK ){ if( iUpper>iLower ){ nNew = sqlite3LogEst(iUpper - iLower); }else{ nNew = 10; assert( 10==sqlite3LogEst(2) ); } if( nNew<nOut ){ nOut = nNew; } pLoop->nOut = (LogEst)nOut; WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n", (u32)iLower, (u32)iUpper, nOut)); return SQLITE_OK; } } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(pBuilder); #endif assert( pLower || pUpper ); /* TUNING: Each inequality constraint reduces the search space 4-fold. ** A BETWEEN operator, therefore, reduces the search space 16-fold */ nNew = nOut; if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){ nNew -= 20; assert( 20==sqlite3LogEst(4) ); nOut--; } if( pUpper ){ nNew -= 20; assert( 20==sqlite3LogEst(4) ); nOut--; } if( nNew<10 ) nNew = 10; if( nNew<nOut ) nOut = nNew; pLoop->nOut = (LogEst)nOut; return rc; } #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Estimate the number of rows that will be returned based on ** an equality constraint x=VALUE and where that VALUE occurs in |
︙ | ︙ | |||
110439 110440 110441 110442 110443 110444 110445 | ** WHERE clause that reference the loop but which are not used by an ** index. ** ** In the current implementation, the first extra WHERE clause term reduces ** the number of output rows by a factor of 10 and each additional term ** reduces the number of output rows by sqrt(2). */ | | | 110836 110837 110838 110839 110840 110841 110842 110843 110844 110845 110846 110847 110848 110849 110850 | ** WHERE clause that reference the loop but which are not used by an ** index. ** ** In the current implementation, the first extra WHERE clause term reduces ** the number of output rows by a factor of 10 and each additional term ** reduces the number of output rows by sqrt(2). */ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){ WhereTerm *pTerm, *pX; Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); int i, j; if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){ return; } |
︙ | ︙ | |||
110471 110472 110473 110474 110475 110476 110477 | ** If pProbe->tnum==0, that means pIndex is a fake index used for the ** INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex( WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ struct SrcList_item *pSrc, /* FROM clause term being analyzed */ Index *pProbe, /* An index on pSrc */ | | | | | | | | 110868 110869 110870 110871 110872 110873 110874 110875 110876 110877 110878 110879 110880 110881 110882 110883 110884 110885 110886 110887 110888 110889 110890 110891 110892 110893 110894 110895 110896 110897 110898 110899 110900 110901 110902 110903 110904 110905 110906 110907 110908 110909 110910 110911 110912 110913 110914 110915 110916 110917 110918 110919 110920 110921 110922 110923 110924 110925 110926 110927 110928 110929 110930 110931 110932 110933 | ** If pProbe->tnum==0, that means pIndex is a fake index used for the ** INTEGER PRIMARY KEY. */ static int whereLoopAddBtreeIndex( WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ struct SrcList_item *pSrc, /* FROM clause term being analyzed */ Index *pProbe, /* An index on pSrc */ LogEst nInMul /* log(Number of iterations due to IN) */ ){ WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ int opMask; /* Valid operators for constraints */ WhereScan scan; /* Iterator for WHERE terms */ Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ int saved_nEq; /* Original value of pNew->u.btree.nEq */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ LogEst saved_nOut; /* Original value of pNew->nOut */ int iCol; /* Index of the column in the table */ int rc = SQLITE_OK; /* Return code */ LogEst nRowEst; /* Estimated index selectivity */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM; assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; }else{ opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; } if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); assert( pNew->u.btree.nEq<=pProbe->nColumn ); if( pNew->u.btree.nEq < pProbe->nColumn ){ iCol = pProbe->aiColumn[pNew->u.btree.nEq]; nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]); if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; }else{ iCol = -1; nRowEst = 0; } pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, opMask, pProbe); saved_nEq = pNew->u.btree.nEq; saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0])); for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nRecValid = pBuilder->nRecValid; #endif if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) && (iCol<0 || pSrc->pTab->aCol[iCol].notNull) |
︙ | ︙ | |||
110549 110550 110551 110552 110553 110554 110555 | pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; pNew->wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ | | | | 110946 110947 110948 110949 110950 110951 110952 110953 110954 110955 110956 110957 110958 110959 110960 110961 110962 110963 | pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; pNew->wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ nIn = 46; assert( 46==sqlite3LogEst(25) ); }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); } pNew->rRun += nIn; pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul + nIn; }else if( pTerm->eOperator & (WO_EQ) ){ assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 || nInMul==0 ); |
︙ | ︙ | |||
110574 110575 110576 110577 110578 110579 110580 | } pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul; }else if( pTerm->eOperator & (WO_ISNULL) ){ pNew->wsFlags |= WHERE_COLUMN_NULL; pNew->u.btree.nEq++; /* TUNING: IS NULL selects 2 rows */ | | | | | | | | | 110971 110972 110973 110974 110975 110976 110977 110978 110979 110980 110981 110982 110983 110984 110985 110986 110987 110988 110989 110990 110991 110992 110993 110994 110995 110996 110997 110998 110999 111000 111001 111002 111003 111004 111005 111006 111007 111008 111009 111010 111011 111012 111013 111014 111015 111016 111017 111018 111019 111020 111021 111022 111023 111024 111025 111026 111027 111028 111029 111030 111031 111032 111033 111034 111035 111036 111037 | } pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul; }else if( pTerm->eOperator & (WO_ISNULL) ){ pNew->wsFlags |= WHERE_COLUMN_NULL; pNew->u.btree.nEq++; /* TUNING: IS NULL selects 2 rows */ nIn = 10; assert( 10==sqlite3LogEst(2) ); pNew->nOut = nRowEst + nInMul + nIn; }else if( pTerm->eOperator & (WO_GT|WO_GE) ){ testcase( pTerm->eOperator & WO_GT ); testcase( pTerm->eOperator & WO_GE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; pBtm = pTerm; pTop = 0; }else{ assert( pTerm->eOperator & (WO_LT|WO_LE) ); testcase( pTerm->eOperator & WO_LT ); testcase( pTerm->eOperator & WO_LE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; pTop = pTerm; pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? pNew->aLTerm[pNew->nLTerm-2] : 0; } if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ /* Adjust nOut and rRun for STAT3 range values */ assert( pNew->nOut==saved_nOut ); whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); } #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( nInMul==0 && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol && OptimizationEnabled(db, SQLITE_Stat3) ){ Expr *pExpr = pTerm->pExpr; tRowcnt nOut = 0; if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ testcase( pTerm->eOperator & WO_EQ ); testcase( pTerm->eOperator & WO_ISNULL ); rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); }else if( (pTerm->eOperator & WO_IN) && !ExprHasProperty(pExpr, EP_xIsSelect) ){ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } assert( nOut==0 || rc==SQLITE_OK ); if( nOut ){ pNew->nOut = sqlite3LogEst(nOut); if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; } } #endif if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ /* Each row involves a step of the index, then a binary search of ** the main table */ pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10); } /* Step cost for each output row */ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut); whereLoopOutputAdjust(pBuilder->pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0)) ){ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } pNew->nOut = saved_nOut; |
︙ | ︙ | |||
110725 110726 110727 110728 110729 110730 110731 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ struct SrcList_item *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ | | | > > | | | | 111122 111123 111124 111125 111126 111127 111128 111129 111130 111131 111132 111133 111134 111135 111136 111137 111138 111139 111140 111141 111142 111143 111144 111145 111146 111147 111148 111149 111150 111151 111152 111153 111154 111155 111156 111157 111158 111159 111160 111161 111162 111163 111164 111165 111166 111167 111168 111169 111170 111171 111172 111173 111174 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ struct SrcList_item *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ LogEst rSize; /* number of rows in the table */ LogEst rLogSize; /* Logarithm of the number of rows in the table */ WhereClause *pWC; /* The parsed WHERE clause */ Table *pTab; /* Table being queried */ pNew = pBuilder->pNew; pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; pTab = pSrc->pTab; pWC = pBuilder->pWC; assert( !IsVirtual(pSrc->pTab) ); if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ pProbe = pSrc->pIndex; }else{ /* There is no INDEXED BY clause. Create a fake Index object in local ** variable sPk to represent the rowid primary key index. Make this ** fake index the first in a chain of Index objects with all of the real ** indices to follow */ Index *pFirst; /* First of real indices on the table */ memset(&sPk, 0, sizeof(Index)); sPk.nColumn = 1; sPk.aiColumn = &aiColumnPk; sPk.aiRowEst = aiRowEstPk; sPk.onError = OE_Replace; sPk.pTable = pTab; aiRowEstPk[0] = pTab->nRowEst; aiRowEstPk[1] = 1; pFirst = pSrc->pTab->pIndex; if( pSrc->notIndexed==0 ){ /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; } pProbe = &sPk; } rSize = sqlite3LogEst(pTab->nRowEst); rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIndex==0 |
︙ | ︙ | |||
110786 110787 110788 110789 110790 110791 110792 | pNew->u.btree.nEq = 1; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** approximately 7*N*log2(N) where N is the number of rows in ** the table being indexed. */ | | | | | 111185 111186 111187 111188 111189 111190 111191 111192 111193 111194 111195 111196 111197 111198 111199 111200 111201 111202 111203 111204 111205 | pNew->u.btree.nEq = 1; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** approximately 7*N*log2(N) where N is the number of rows in ** the table being indexed. */ pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) ); /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way ** of knowning how selective the index will ultimately be. It would ** not be unreasonable to make this value much larger. */ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) ); pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut); pNew->wsFlags = WHERE_AUTO_INDEX; pNew->prereq = mExtra | pTerm->prereqRight; rc = whereLoopInsert(pBuilder, pNew); } } } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ |
︙ | ︙ | |||
110826 110827 110828 110829 110830 110831 110832 | /* Integer primary key index */ pNew->wsFlags = WHERE_IPK; /* Full table scan */ pNew->iSortIdx = b ? iSortIdx : 0; /* TUNING: Cost of full table scan is 3*(N + log2(N)). ** + The extra 3 factor is to encourage the use of indexed lookups | | < < | | > | | | | | < < < | > | | 111225 111226 111227 111228 111229 111230 111231 111232 111233 111234 111235 111236 111237 111238 111239 111240 111241 111242 111243 111244 111245 111246 111247 111248 111249 111250 111251 111252 111253 111254 111255 111256 111257 111258 111259 111260 111261 111262 111263 111264 111265 111266 111267 111268 111269 111270 111271 111272 111273 111274 | /* Integer primary key index */ pNew->wsFlags = WHERE_IPK; /* Full table scan */ pNew->iSortIdx = b ? iSortIdx : 0; /* TUNING: Cost of full table scan is 3*(N + log2(N)). ** + The extra 3 factor is to encourage the use of indexed lookups ** over full scans. FIXME */ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16; whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; }else{ Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe); pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; /* Full scan via index */ if( b || ( m==0 && pProbe->bUnordered==0 && pProbe->szIdxRow<pTab->szTabRow && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) ) ){ pNew->iSortIdx = b ? iSortIdx : 0; if( m==0 ){ /* TUNING: Cost of a covering index scan is K*(N + log2(N)). ** + The extra factor K of between 1.1 and 3.0 that depends ** on the relative sizes of the table and the index. K ** is smaller for smaller indices, thus favoring them. */ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; }else{ assert( b!=0 ); /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) ** which we will simplify to just N*log2(N) */ pNew->rRun = rSize + rLogSize; } whereLoopOutputAdjust(pWC, pNew); rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; if( rc ) break; } } rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); |
︙ | ︙ | |||
111035 111036 111037 111038 111039 111040 111041 | pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0) && pIdxInfo->orderByConsumed); pNew->rSetup = 0; | | | | 111431 111432 111433 111434 111435 111436 111437 111438 111439 111440 111441 111442 111443 111444 111445 111446 111447 | pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0) && pIdxInfo->orderByConsumed); pNew->rSetup = 0; pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost); /* TUNING: Every virtual table query returns 25 rows */ pNew->nOut = 46; assert( 46==sqlite3LogEst(25) ); whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; } } } |
︙ | ︙ | |||
111074 111075 111076 111077 111078 111079 111080 111081 111082 111083 111084 111085 111086 111087 111088 111089 111090 111091 | struct SrcList_item *pItem; pWC = pBuilder->pWC; if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; pWCEnd = pWC->a + pWC->nTerm; pNew = pBuilder->pNew; memset(&sSum, 0, sizeof(sSum)); for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){ if( (pTerm->eOperator & WO_OR)!=0 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int once = 1; int i, j; | > > < < | 111470 111471 111472 111473 111474 111475 111476 111477 111478 111479 111480 111481 111482 111483 111484 111485 111486 111487 111488 111489 111490 111491 111492 111493 111494 111495 111496 | struct SrcList_item *pItem; pWC = pBuilder->pWC; if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; pWCEnd = pWC->a + pWC->nTerm; pNew = pBuilder->pNew; memset(&sSum, 0, sizeof(sSum)); pItem = pWInfo->pTabList->a + pNew->iTab; iCur = pItem->iCursor; for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){ if( (pTerm->eOperator & WO_OR)!=0 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int once = 1; int i, j; sSubBuild = *pBuilder; sSubBuild.pOrderBy = 0; sSubBuild.pOrSet = &sCur; for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ if( (pOrTerm->eOperator & WO_AND)!=0 ){ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; |
︙ | ︙ | |||
111127 111128 111129 111130 111131 111132 111133 | once = 0; }else{ whereOrMove(&sPrev, &sSum); sSum.n = 0; for(i=0; i<sPrev.n; i++){ for(j=0; j<sCur.n; j++){ whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq, | | | | 111523 111524 111525 111526 111527 111528 111529 111530 111531 111532 111533 111534 111535 111536 111537 111538 | once = 0; }else{ whereOrMove(&sPrev, &sSum); sSum.n = 0; for(i=0; i<sPrev.n; i++){ for(j=0; j<sCur.n; j++){ whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq, sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun), sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut)); } } } } pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; pNew->wsFlags = WHERE_MULTI_OR; |
︙ | ︙ | |||
111466 111467 111468 111469 111470 111471 111472 | ** Assume that the total number of output rows that will need to be sorted ** will be nRowEst (in the 10*log2 representation). Or, ignore sorting ** costs if nRowEst==0. ** ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation ** error occurs. */ | | | | | | | | 111862 111863 111864 111865 111866 111867 111868 111869 111870 111871 111872 111873 111874 111875 111876 111877 111878 111879 111880 111881 111882 111883 111884 111885 111886 111887 111888 | ** Assume that the total number of output rows that will need to be sorted ** will be nRowEst (in the 10*log2 representation). Or, ignore sorting ** costs if nRowEst==0. ** ** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation ** error occurs. */ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ int mxChoice; /* Maximum number of simultaneous paths tracked */ int nLoop; /* Number of terms in the join */ Parse *pParse; /* Parsing context */ sqlite3 *db; /* The database connection */ int iLoop; /* Loop counter over the terms of the join */ int ii, jj; /* Loop counters */ int mxI = 0; /* Index of next entry to replace */ LogEst rCost; /* Cost of a path */ LogEst nOut; /* Number of outputs */ LogEst mxCost = 0; /* Maximum cost of a set of paths */ LogEst mxOut = 0; /* Maximum nOut value on the set of paths */ LogEst rSortCost; /* Cost to do a sort */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aTo; /* The nTo best paths at the current level */ WherePath *pFrom; /* An element of aFrom[] that we are working on */ WherePath *pTo; /* An element of aTo[] that we are working on */ WhereLoop *pWLoop; /* One of the WhereLoop objects */ WhereLoop **pX; /* Used to divy up the pSpace memory */ |
︙ | ︙ | |||
111515 111516 111517 111518 111519 111520 111521 | } /* Seed the search with a single WherePath containing zero WhereLoops. ** ** TUNING: Do not let the number of iterations go above 25. If the cost ** of computing an automatic index is not paid back within the first 25 ** rows, then do not use the automatic index. */ | | | | > > | | | | 111911 111912 111913 111914 111915 111916 111917 111918 111919 111920 111921 111922 111923 111924 111925 111926 111927 111928 111929 111930 111931 111932 111933 111934 111935 111936 111937 111938 111939 111940 111941 111942 111943 111944 111945 111946 111947 111948 111949 111950 111951 111952 111953 111954 111955 111956 111957 111958 111959 111960 111961 111962 111963 111964 111965 111966 111967 111968 111969 111970 111971 111972 | } /* Seed the search with a single WherePath containing zero WhereLoops. ** ** TUNING: Do not let the number of iterations go above 25. If the cost ** of computing an automatic index is not paid back within the first 25 ** rows, then do not use the automatic index. */ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) ); nFrom = 1; /* Precompute the cost of sorting the final result set, if the caller ** to sqlite3WhereBegin() was concerned about sorting */ rSortCost = 0; if( pWInfo->pOrderBy==0 || nRowEst==0 ){ aFrom[0].isOrderedValid = 1; }else{ /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the ** number of output rows. The 48 is the expected size of a row to sort. ** FIXME: compute a better estimate of the 48 multiplier based on the ** result set expressions. */ rSortCost = nRowEst + estLog(nRowEst); WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost)); } /* Compute successively longer WherePaths using the previous generation ** of WherePaths as the basis for the next. Keep track of the mxChoice ** best paths at each generation */ for(iLoop=0; iLoop<nLoop; iLoop++){ nTo = 0; for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ Bitmask maskNew; Bitmask revMask = 0; u8 isOrderedValid = pFrom->isOrderedValid; u8 isOrdered = pFrom->isOrdered; if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); rCost = sqlite3LogEstAdd(rCost, pFrom->rCost); nOut = pFrom->nRow + pWLoop->nOut; maskNew = pFrom->maskLoop | pWLoop->maskSelf; if( !isOrderedValid ){ switch( wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, iLoop, pWLoop, &revMask) ){ case 1: /* Yes. pFrom+pWLoop does satisfy the ORDER BY clause */ isOrdered = 1; isOrderedValid = 1; break; case 0: /* No. pFrom+pWLoop will require a separate sort */ isOrdered = 0; isOrderedValid = 1; rCost = sqlite3LogEstAdd(rCost, rSortCost); break; default: /* Cannot tell yet. Try again on the next iteration */ break; } }else{ revMask = pFrom->revLoop; } |
︙ | ︙ | |||
111767 111768 111769 111770 111771 111772 111773 | pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0); if( pTerm ){ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->aLTerm[0] = pTerm; pLoop->nLTerm = 1; pLoop->u.btree.nEq = 1; /* TUNING: Cost of a rowid lookup is 10 */ | | | 112165 112166 112167 112168 112169 112170 112171 112172 112173 112174 112175 112176 112177 112178 112179 | pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0); if( pTerm ){ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->aLTerm[0] = pTerm; pLoop->nLTerm = 1; pLoop->u.btree.nEq = 1; /* TUNING: Cost of a rowid lookup is 10 */ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pLoop->aLTermSpace==pLoop->aLTerm ); assert( ArraySize(pLoop->aLTermSpace)==4 ); if( pIdx->onError==OE_None || pIdx->pPartIdxWhere!=0 || pIdx->nColumn>ArraySize(pLoop->aLTermSpace) |
︙ | ︙ | |||
111790 111791 111792 111793 111794 111795 111796 | if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ pLoop->wsFlags |= WHERE_IDX_ONLY; } pLoop->nLTerm = j; pLoop->u.btree.nEq = j; pLoop->u.btree.pIndex = pIdx; /* TUNING: Cost of a unique index lookup is 15 */ | | | | 112188 112189 112190 112191 112192 112193 112194 112195 112196 112197 112198 112199 112200 112201 112202 112203 112204 112205 112206 112207 | if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ pLoop->wsFlags |= WHERE_IDX_ONLY; } pLoop->nLTerm = j; pLoop->u.btree.nEq = j; pLoop->u.btree.pIndex = pIdx; /* TUNING: Cost of a unique index lookup is 15 */ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */ break; } } if( pLoop->wsFlags ){ pLoop->nOut = (LogEst)1; pWInfo->a[0].pWLoop = pLoop; pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur); pWInfo->a[0].iTabCur = iCur; pWInfo->nRowOut = 1; if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1; if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; |
︙ | ︙ | |||
112163 112164 112165 112166 112167 112168 112169 | } } WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. | | | 112561 112562 112563 112564 112565 112566 112567 112568 112569 112570 112571 112572 112573 112574 112575 | } } WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. ** The one-pass algorithm only works if the WHERE clause constrains ** the statement to update a single row. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){ pWInfo->okOnePass = 1; pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; |
︙ | ︙ | |||
121581 121582 121583 121584 121585 121586 121587 121588 121589 121590 121591 121592 121593 121594 | ** methods of the virtual table are called at appropriate times. These ** values do not contribute to FTS functionality; they are used for ** verifying the operation of the SQLite core. */ int inTransaction; /* True after xBegin but before xCommit/xRollback */ int mxSavepoint; /* Largest valid xSavepoint integer */ #endif }; /* ** When the core wants to read from the virtual table, it creates a ** virtual table cursor (an instance of the following structure) using ** the xOpen method. Cursors are destroyed using the xClose method. */ | > > > > > > | 121979 121980 121981 121982 121983 121984 121985 121986 121987 121988 121989 121990 121991 121992 121993 121994 121995 121996 121997 121998 | ** methods of the virtual table are called at appropriate times. These ** values do not contribute to FTS functionality; they are used for ** verifying the operation of the SQLite core. */ int inTransaction; /* True after xBegin but before xCommit/xRollback */ int mxSavepoint; /* Largest valid xSavepoint integer */ #endif #ifdef SQLITE_TEST /* True to disable the incremental doclist optimization. This is controled ** by special insert command 'test-no-incr-doclist'. */ int bNoIncrDoclist; #endif }; /* ** When the core wants to read from the virtual table, it creates a ** virtual table cursor (an instance of the following structure) using ** the xOpen method. Cursors are destroyed using the xClose method. */ |
︙ | ︙ | |||
121606 121607 121608 121609 121610 121611 121612 | char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ u8 bDesc; /* True to sort in descending order */ int eEvalmode; /* An FTS3_EVAL_XX constant */ int nRowAvg; /* Average size of database rows, in pages */ sqlite3_int64 nDoc; /* Documents in table */ | | > | 122010 122011 122012 122013 122014 122015 122016 122017 122018 122019 122020 122021 122022 122023 122024 122025 | char *pNextId; /* Pointer into the body of aDoclist */ char *aDoclist; /* List of docids for full-text queries */ int nDoclist; /* Size of buffer at aDoclist */ u8 bDesc; /* True to sort in descending order */ int eEvalmode; /* An FTS3_EVAL_XX constant */ int nRowAvg; /* Average size of database rows, in pages */ sqlite3_int64 nDoc; /* Documents in table */ i64 iMinDocid; /* Minimum docid to return */ i64 iMaxDocid; /* Maximum docid to return */ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ u32 *aMatchinfo; /* Information about most recent match */ int nMatchinfo; /* Number of elements in aMatchinfo[] */ char *zMatchinfo; /* Matchinfo specification */ }; #define FTS3_EVAL_FILTER 0 |
︙ | ︙ | |||
121636 121637 121638 121639 121640 121641 121642 121643 121644 121645 121646 121647 121648 121649 | ** indicating that all columns should be searched, ** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. */ #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ struct Fts3Doclist { char *aAll; /* Array containing doclist (or NULL) */ int nAll; /* Size of a[] in bytes */ char *pNextDocid; /* Pointer to next docid */ sqlite3_int64 iDocid; /* Current docid (if pList!=0) */ | > > > > > > > > > | 122041 122042 122043 122044 122045 122046 122047 122048 122049 122050 122051 122052 122053 122054 122055 122056 122057 122058 122059 122060 122061 122062 122063 | ** indicating that all columns should be searched, ** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. */ #define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ #define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ #define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ /* ** The lower 16-bits of the sqlite3_index_info.idxNum value set by ** the xBestIndex() method contains the Fts3Cursor.eSearch value described ** above. The upper 16-bits contain a combination of the following ** bits, used to describe extra constraints on full-text searches. */ #define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */ #define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */ #define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */ struct Fts3Doclist { char *aAll; /* Array containing doclist (or NULL) */ int nAll; /* Size of a[] in bytes */ char *pNextDocid; /* Pointer to next docid */ sqlite3_int64 iDocid; /* Current docid (if pList!=0) */ |
︙ | ︙ | |||
123056 123057 123058 123059 123060 123061 123062 123063 123064 123065 123066 123067 123068 123069 123070 123071 123072 123073 123074 123075 | ** 2. Full-text search using a MATCH operator on a non-docid column. ** 3. Linear scan of %_content table. */ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts3Table *p = (Fts3Table *)pVTab; int i; /* Iterator variable */ int iCons = -1; /* Index of constraint to use */ int iLangidCons = -1; /* Index of langid=x constraint, if present */ /* By default use a full table scan. This is an expensive option, ** so search through the constraints to see if a more efficient ** strategy is possible. */ pInfo->idxNum = FTS3_FULLSCAN_SEARCH; pInfo->estimatedCost = 5000000; for(i=0; i<pInfo->nConstraint; i++){ struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; if( pCons->usable==0 ) continue; /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ | > > > > > > > < | < < | 123470 123471 123472 123473 123474 123475 123476 123477 123478 123479 123480 123481 123482 123483 123484 123485 123486 123487 123488 123489 123490 123491 123492 123493 123494 123495 123496 123497 123498 123499 123500 123501 123502 123503 123504 | ** 2. Full-text search using a MATCH operator on a non-docid column. ** 3. Linear scan of %_content table. */ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts3Table *p = (Fts3Table *)pVTab; int i; /* Iterator variable */ int iCons = -1; /* Index of constraint to use */ int iLangidCons = -1; /* Index of langid=x constraint, if present */ int iDocidGe = -1; /* Index of docid>=x constraint, if present */ int iDocidLe = -1; /* Index of docid<=x constraint, if present */ int iIdx; /* By default use a full table scan. This is an expensive option, ** so search through the constraints to see if a more efficient ** strategy is possible. */ pInfo->idxNum = FTS3_FULLSCAN_SEARCH; pInfo->estimatedCost = 5000000; for(i=0; i<pInfo->nConstraint; i++){ int bDocid; /* True if this constraint is on docid */ struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; if( pCons->usable==0 ) continue; bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1); /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){ pInfo->idxNum = FTS3_DOCID_SEARCH; pInfo->estimatedCost = 1.0; iCons = i; } /* A MATCH constraint. Use a full-text search. ** |
︙ | ︙ | |||
123101 123102 123103 123104 123105 123106 123107 | /* Equality constraint on the langid column */ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && pCons->iColumn==p->nColumn + 2 ){ iLangidCons = i; } | | > > > > > > > > > > > > > > > | > | > > > > > > > > | 123519 123520 123521 123522 123523 123524 123525 123526 123527 123528 123529 123530 123531 123532 123533 123534 123535 123536 123537 123538 123539 123540 123541 123542 123543 123544 123545 123546 123547 123548 123549 123550 123551 123552 123553 123554 123555 123556 123557 123558 123559 123560 123561 123562 123563 123564 | /* Equality constraint on the langid column */ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && pCons->iColumn==p->nColumn + 2 ){ iLangidCons = i; } if( bDocid ){ switch( pCons->op ){ case SQLITE_INDEX_CONSTRAINT_GE: case SQLITE_INDEX_CONSTRAINT_GT: iDocidGe = i; break; case SQLITE_INDEX_CONSTRAINT_LE: case SQLITE_INDEX_CONSTRAINT_LT: iDocidLe = i; break; } } } iIdx = 1; if( iCons>=0 ){ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; pInfo->aConstraintUsage[iCons].omit = 1; } if( iLangidCons>=0 ){ pInfo->idxNum |= FTS3_HAVE_LANGID; pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++; } if( iDocidGe>=0 ){ pInfo->idxNum |= FTS3_HAVE_DOCID_GE; pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++; } if( iDocidLe>=0 ){ pInfo->idxNum |= FTS3_HAVE_DOCID_LE; pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++; } /* Regardless of the strategy selected, FTS can deliver rows in rowid (or ** docid) order. Both ascending and descending are possible. */ if( pInfo->nOrderBy==1 ){ struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0]; |
︙ | ︙ | |||
124554 124555 124556 124557 124558 124559 124560 124561 124562 124563 124564 124565 124566 124567 | } }else{ rc = fts3EvalNext((Fts3Cursor *)pCursor); } assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); return rc; } /* ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 124996 124997 124998 124999 125000 125001 125002 125003 125004 125005 125006 125007 125008 125009 125010 125011 125012 125013 125014 125015 125016 125017 125018 125019 125020 125021 125022 125023 125024 125025 125026 125027 125028 125029 125030 125031 125032 125033 125034 125035 125036 | } }else{ rc = fts3EvalNext((Fts3Cursor *)pCursor); } assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); return rc; } /* ** The following are copied from sqliteInt.h. ** ** Constants for the largest and smallest possible 64-bit signed integers. ** These macros are designed to work correctly on both 32-bit and 64-bit ** compilers. */ #ifndef SQLITE_AMALGAMATION # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) #endif /* ** If the numeric type of argument pVal is "integer", then return it ** converted to a 64-bit signed integer. Otherwise, return a copy of ** the second parameter, iDefault. */ static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){ if( pVal ){ int eType = sqlite3_value_numeric_type(pVal); if( eType==SQLITE_INTEGER ){ return sqlite3_value_int64(pVal); } } return iDefault; } /* ** This is the xFilter interface for the virtual table. See ** the virtual table xFilter method documentation for additional ** information. ** ** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against |
︙ | ︙ | |||
124580 124581 124582 124583 124584 124585 124586 124587 124588 124589 124590 124591 124592 | int idxNum, /* Strategy index */ const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ int rc; char *zSql; /* SQL statement used to access %_content */ Fts3Table *p = (Fts3Table *)pCursor->pVtab; Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; UNUSED_PARAMETER(idxStr); UNUSED_PARAMETER(nVal); | > > > > > > > > | > | > > | > > > | > > > > | | | | | | | 125049 125050 125051 125052 125053 125054 125055 125056 125057 125058 125059 125060 125061 125062 125063 125064 125065 125066 125067 125068 125069 125070 125071 125072 125073 125074 125075 125076 125077 125078 125079 125080 125081 125082 125083 125084 125085 125086 125087 125088 125089 125090 125091 125092 125093 125094 125095 125096 125097 125098 125099 125100 125101 125102 125103 125104 125105 125106 125107 125108 125109 125110 125111 125112 125113 125114 | int idxNum, /* Strategy index */ const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ int rc; char *zSql; /* SQL statement used to access %_content */ int eSearch; Fts3Table *p = (Fts3Table *)pCursor->pVtab; Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */ sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */ sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */ sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */ int iIdx; UNUSED_PARAMETER(idxStr); UNUSED_PARAMETER(nVal); eSearch = (idxNum & 0x0000FFFF); assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); assert( p->pSegments==0 ); /* Collect arguments into local variables */ iIdx = 0; if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++]; if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++]; if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; assert( iIdx==nVal ); /* In case the cursor has been used before, clear it now. */ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); /* Set the lower and upper bounds on docids to return */ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); if( idxStr ){ pCsr->bDesc = (idxStr[0]=='D'); }else{ pCsr->bDesc = p->bDescIdx; } pCsr->eSearch = (i16)eSearch; if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){ int iCol = eSearch-FTS3_FULLTEXT_SEARCH; const char *zQuery = (const char *)sqlite3_value_text(pCons); if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){ return SQLITE_NOMEM; } pCsr->iLangid = 0; if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid); assert( p->base.zErrMsg==0 ); rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, &p->base.zErrMsg ); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
124636 124637 124638 124639 124640 124641 124642 | } /* Compile a SELECT statement for this cursor. For a full-table-scan, the ** statement loops through all rows of the %_content table. For a ** full-text query or docid lookup, the statement retrieves a single ** row by docid. */ | | | | | 125123 125124 125125 125126 125127 125128 125129 125130 125131 125132 125133 125134 125135 125136 125137 125138 125139 125140 125141 125142 125143 125144 125145 125146 125147 125148 125149 125150 125151 | } /* Compile a SELECT statement for this cursor. For a full-table-scan, the ** statement loops through all rows of the %_content table. For a ** full-text query or docid lookup, the statement retrieves a single ** row by docid. */ if( eSearch==FTS3_FULLSCAN_SEARCH ){ zSql = sqlite3_mprintf( "SELECT %s ORDER BY rowid %s", p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") ); if( zSql ){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); }else{ rc = SQLITE_NOMEM; } }else if( eSearch==FTS3_DOCID_SEARCH ){ rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); if( rc==SQLITE_OK ){ rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); } } if( rc!=SQLITE_OK ) return rc; return fts3NextMethod(pCursor); } |
︙ | ︙ | |||
125541 125542 125543 125544 125545 125546 125547 125548 125549 125550 125551 125552 125553 125554 125555 125556 125557 125558 125559 125560 | sqlite3_free(aPoslist); } } return SQLITE_OK; } /* ** This function is called for each Fts3Phrase in a full-text query ** expression to initialize the mechanism for returning rows. Once this ** function has been called successfully on an Fts3Phrase, it may be ** used with fts3EvalPhraseNext() to iterate through the matching docids. ** ** If parameter bOptOk is true, then the phrase may (or may not) use the ** incremental loading strategy. Otherwise, the entire doclist is loaded into ** memory within this call. ** ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. */ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ | > > > > > > < < > > > > > > > > > | | | > | > > > > | > > > > | | > > > > | < < | > > | 126028 126029 126030 126031 126032 126033 126034 126035 126036 126037 126038 126039 126040 126041 126042 126043 126044 126045 126046 126047 126048 126049 126050 126051 126052 126053 126054 126055 126056 126057 126058 126059 126060 126061 126062 126063 126064 126065 126066 126067 126068 126069 126070 126071 126072 126073 126074 126075 126076 126077 126078 126079 126080 126081 126082 126083 126084 126085 126086 126087 126088 126089 126090 126091 126092 126093 126094 126095 126096 126097 | sqlite3_free(aPoslist); } } return SQLITE_OK; } /* ** Maximum number of tokens a phrase may have to be considered for the ** incremental doclists strategy. */ #define MAX_INCR_PHRASE_TOKENS 4 /* ** This function is called for each Fts3Phrase in a full-text query ** expression to initialize the mechanism for returning rows. Once this ** function has been called successfully on an Fts3Phrase, it may be ** used with fts3EvalPhraseNext() to iterate through the matching docids. ** ** If parameter bOptOk is true, then the phrase may (or may not) use the ** incremental loading strategy. Otherwise, the entire doclist is loaded into ** memory within this call. ** ** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. */ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; int rc = SQLITE_OK; /* Error code */ int i; /* Determine if doclists may be loaded from disk incrementally. This is ** possible if the bOptOk argument is true, the FTS doclists will be ** scanned in forward order, and the phrase consists of ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" ** tokens or prefix tokens that cannot use a prefix-index. */ int bHaveIncr = 0; int bIncrOk = (bOptOk && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 #ifdef SQLITE_TEST && pTab->bNoIncrDoclist==0 #endif ); for(i=0; bIncrOk==1 && i<p->nToken; i++){ Fts3PhraseToken *pToken = &p->aToken[i]; if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ bIncrOk = 0; } if( pToken->pSegcsr ) bHaveIncr = 1; } if( bIncrOk && bHaveIncr ){ /* Use the incremental approach. */ int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn); for(i=0; rc==SQLITE_OK && i<p->nToken; i++){ Fts3PhraseToken *pToken = &p->aToken[i]; Fts3MultiSegReader *pSegcsr = pToken->pSegcsr; if( pSegcsr ){ rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n); } } p->bIncr = 1; }else{ /* Load the full doclist for the phrase into memory. */ rc = fts3EvalPhraseLoad(pCsr, p); p->bIncr = 0; } assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr ); |
︙ | ︙ | |||
125678 125679 125680 125681 125682 125683 125684 125685 125686 125687 125688 125689 125690 125691 125692 125693 125694 125695 125696 125697 125698 125699 125700 125701 125702 125703 125704 | p += sqlite3Fts3GetVarint(p, &iVar); *piDocid += ((bDescIdx ? -1 : 1) * iVar); } } *ppIter = p; } /* ** Attempt to move the phrase iterator to point to the next matching docid. ** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. ** ** If there is no "next" entry and no error occurs, then *pbEof is set to ** 1 before returning. Otherwise, if no error occurs and the iterator is ** successfully advanced, *pbEof is set to 0. */ static int fts3EvalPhraseNext( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Phrase *p, /* Phrase object to advance to next docid */ u8 *pbEof /* OUT: Set to 1 if EOF */ ){ int rc = SQLITE_OK; Fts3Doclist *pDL = &p->doclist; Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; if( p->bIncr ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 126191 126192 126193 126194 126195 126196 126197 126198 126199 126200 126201 126202 126203 126204 126205 126206 126207 126208 126209 126210 126211 126212 126213 126214 126215 126216 126217 126218 126219 126220 126221 126222 126223 126224 126225 126226 126227 126228 126229 126230 126231 126232 126233 126234 126235 126236 126237 126238 126239 126240 126241 126242 126243 126244 126245 126246 126247 126248 126249 126250 126251 126252 126253 126254 126255 126256 126257 126258 126259 126260 126261 126262 126263 126264 126265 126266 126267 126268 126269 126270 126271 126272 126273 126274 126275 126276 126277 126278 126279 126280 126281 126282 126283 126284 126285 126286 126287 126288 126289 126290 126291 126292 126293 126294 126295 126296 126297 126298 126299 126300 126301 126302 126303 126304 126305 126306 126307 126308 126309 126310 126311 126312 126313 126314 126315 126316 126317 126318 126319 126320 126321 126322 126323 126324 126325 126326 126327 126328 126329 126330 126331 126332 126333 126334 126335 126336 126337 126338 126339 126340 126341 126342 126343 126344 126345 126346 126347 126348 126349 126350 126351 126352 126353 126354 126355 126356 126357 126358 126359 126360 126361 126362 126363 126364 126365 126366 126367 126368 126369 126370 126371 126372 126373 126374 126375 126376 126377 126378 126379 126380 126381 126382 126383 126384 126385 126386 126387 126388 126389 126390 126391 126392 126393 126394 126395 126396 126397 126398 126399 126400 126401 126402 126403 126404 126405 126406 126407 126408 126409 126410 126411 126412 126413 126414 126415 126416 126417 126418 126419 126420 126421 126422 126423 126424 126425 126426 126427 126428 126429 126430 126431 126432 126433 126434 126435 126436 126437 126438 126439 126440 126441 126442 | p += sqlite3Fts3GetVarint(p, &iVar); *piDocid += ((bDescIdx ? -1 : 1) * iVar); } } *ppIter = p; } /* ** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof ** to true if EOF is reached. */ static void fts3EvalDlPhraseNext( Fts3Table *pTab, Fts3Doclist *pDL, u8 *pbEof ){ char *pIter; /* Used to iterate through aAll */ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */ if( pDL->pNextDocid ){ pIter = pDL->pNextDocid; }else{ pIter = pDL->aAll; } if( pIter>=pEnd ){ /* We have already reached the end of this doclist. EOF. */ *pbEof = 1; }else{ sqlite3_int64 iDelta; pIter += sqlite3Fts3GetVarint(pIter, &iDelta); if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){ pDL->iDocid += iDelta; }else{ pDL->iDocid -= iDelta; } pDL->pList = pIter; fts3PoslistCopy(0, &pIter); pDL->nList = (int)(pIter - pDL->pList); /* pIter now points just past the 0x00 that terminates the position- ** list for document pDL->iDocid. However, if this position-list was ** edited in place by fts3EvalNearTrim(), then pIter may not actually ** point to the start of the next docid value. The following line deals ** with this case by advancing pIter past the zero-padding added by ** fts3EvalNearTrim(). */ while( pIter<pEnd && *pIter==0 ) pIter++; pDL->pNextDocid = pIter; assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter ); *pbEof = 0; } } /* ** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext(). */ typedef struct TokenDoclist TokenDoclist; struct TokenDoclist { int bIgnore; sqlite3_int64 iDocid; char *pList; int nList; }; /* ** Token pToken is an incrementally loaded token that is part of a ** multi-token phrase. Advance it to the next matching document in the ** database and populate output variable *p with the details of the new ** entry. Or, if the iterator has reached EOF, set *pbEof to true. ** ** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. */ static int incrPhraseTokenNext( Fts3Table *pTab, /* Virtual table handle */ Fts3Phrase *pPhrase, /* Phrase to advance token of */ int iToken, /* Specific token to advance */ TokenDoclist *p, /* OUT: Docid and doclist for new entry */ u8 *pbEof /* OUT: True if iterator is at EOF */ ){ int rc = SQLITE_OK; if( pPhrase->iDoclistToken==iToken ){ assert( p->bIgnore==0 ); assert( pPhrase->aToken[iToken].pSegcsr==0 ); fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof); p->pList = pPhrase->doclist.pList; p->nList = pPhrase->doclist.nList; p->iDocid = pPhrase->doclist.iDocid; }else{ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; assert( pToken->pDeferred==0 ); assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 ); if( pToken->pSegcsr ){ assert( p->bIgnore==0 ); rc = sqlite3Fts3MsrIncrNext( pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList ); if( p->pList==0 ) *pbEof = 1; }else{ p->bIgnore = 1; } } return rc; } /* ** The phrase iterator passed as the second argument: ** ** * features at least one token that uses an incremental doclist, and ** ** * does not contain any deferred tokens. ** ** Advance it to the next matching documnent in the database and populate ** the Fts3Doclist.pList and nList fields. ** ** If there is no "next" entry and no error occurs, then *pbEof is set to ** 1 before returning. Otherwise, if no error occurs and the iterator is ** successfully advanced, *pbEof is set to 0. ** ** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. */ static int fts3EvalIncrPhraseNext( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Phrase *p, /* Phrase object to advance to next docid */ u8 *pbEof /* OUT: Set to 1 if EOF */ ){ int rc = SQLITE_OK; Fts3Doclist *pDL = &p->doclist; Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; u8 bEof = 0; /* This is only called if it is guaranteed that the phrase has at least ** one incremental token. In which case the bIncr flag is set. */ assert( p->bIncr==1 ); if( p->nToken==1 && p->bIncr ){ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, &pDL->iDocid, &pDL->pList, &pDL->nList ); if( pDL->pList==0 ) bEof = 1; }else{ int bDescDoclist = pCsr->bDesc; struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS]; memset(a, 0, sizeof(a)); assert( p->nToken<=MAX_INCR_PHRASE_TOKENS ); assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS ); while( bEof==0 ){ int bMaxSet = 0; sqlite3_int64 iMax = 0; /* Largest docid for all iterators */ int i; /* Used to iterate through tokens */ /* Advance the iterator for each token in the phrase once. */ for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){ iMax = a[i].iDocid; bMaxSet = 1; } } assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 ); assert( rc!=SQLITE_OK || bMaxSet ); /* Keep advancing iterators until they all point to the same document */ for(i=0; i<p->nToken; i++){ while( rc==SQLITE_OK && bEof==0 && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0 ){ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); if( DOCID_CMP(a[i].iDocid, iMax)>0 ){ iMax = a[i].iDocid; i = 0; } } } /* Check if the current entries really are a phrase match */ if( bEof==0 ){ int nList = 0; int nByte = a[p->nToken-1].nList; char *aDoclist = sqlite3_malloc(nByte+1); if( !aDoclist ) return SQLITE_NOMEM; memcpy(aDoclist, a[p->nToken-1].pList, nByte+1); for(i=0; i<(p->nToken-1); i++){ if( a[i].bIgnore==0 ){ char *pL = a[i].pList; char *pR = aDoclist; char *pOut = aDoclist; int nDist = p->nToken-1-i; int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR); if( res==0 ) break; nList = (int)(pOut - aDoclist); } } if( i==(p->nToken-1) ){ pDL->iDocid = iMax; pDL->pList = aDoclist; pDL->nList = nList; pDL->bFreeList = 1; break; } sqlite3_free(aDoclist); } } } *pbEof = bEof; return rc; } /* ** Attempt to move the phrase iterator to point to the next matching docid. ** If an error occurs, return an SQLite error code. Otherwise, return ** SQLITE_OK. ** ** If there is no "next" entry and no error occurs, then *pbEof is set to ** 1 before returning. Otherwise, if no error occurs and the iterator is ** successfully advanced, *pbEof is set to 0. */ static int fts3EvalPhraseNext( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Phrase *p, /* Phrase object to advance to next docid */ u8 *pbEof /* OUT: Set to 1 if EOF */ ){ int rc = SQLITE_OK; Fts3Doclist *pDL = &p->doclist; Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; if( p->bIncr ){ rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof); }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){ sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof ); pDL->pList = pDL->pNextDocid; }else{ fts3EvalDlPhraseNext(pTab, pDL, pbEof); } return rc; } /* ** |
︙ | ︙ | |||
125771 125772 125773 125774 125775 125776 125777 | ** ** If an error occurs within this function, *pRc is set to an SQLite error ** code before returning. */ static void fts3EvalStartReaders( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Expr *pExpr, /* Expression to initialize phrases in */ | < | | | | 126453 126454 126455 126456 126457 126458 126459 126460 126461 126462 126463 126464 126465 126466 126467 126468 126469 126470 126471 126472 126473 126474 126475 126476 126477 126478 126479 126480 | ** ** If an error occurs within this function, *pRc is set to an SQLite error ** code before returning. */ static void fts3EvalStartReaders( Fts3Cursor *pCsr, /* FTS Cursor handle */ Fts3Expr *pExpr, /* Expression to initialize phrases in */ int *pRc /* IN/OUT: Error code */ ){ if( pExpr && SQLITE_OK==*pRc ){ if( pExpr->eType==FTSQUERY_PHRASE ){ int i; int nToken = pExpr->pPhrase->nToken; for(i=0; i<nToken; i++){ if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break; } pExpr->bDeferred = (i==nToken); *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); }else{ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); fts3EvalStartReaders(pCsr, pExpr->pRight, pRc); pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); } } } /* ** An array of the following structures is assembled as part of the process |
︙ | ︙ | |||
126027 126028 126029 126030 126031 126032 126033 | pToken->pSegcsr = 0; }else{ /* Set nLoad4 to the value of (4^nOther) for the next iteration of the ** for-loop. Except, limit the value to 2^24 to prevent it from ** overflowing the 32-bit integer it is stored in. */ if( ii<12 ) nLoad4 = nLoad4*4; | | | 126708 126709 126710 126711 126712 126713 126714 126715 126716 126717 126718 126719 126720 126721 126722 | pToken->pSegcsr = 0; }else{ /* Set nLoad4 to the value of (4^nOther) for the next iteration of the ** for-loop. Except, limit the value to 2^24 to prevent it from ** overflowing the 32-bit integer it is stored in. */ if( ii<12 ) nLoad4 = nLoad4*4; if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){ /* Either this is the cheapest token in the entire query, or it is ** part of a multi-token phrase. Either way, the entire doclist will ** (eventually) be loaded into memory. It may as well be now. */ Fts3PhraseToken *pToken = pTC->pToken; int nList = 0; char *pList = 0; rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); |
︙ | ︙ | |||
126107 126108 126109 126110 126111 126112 126113 | } sqlite3_free(aTC); } } #endif | | | 126788 126789 126790 126791 126792 126793 126794 126795 126796 126797 126798 126799 126800 126801 126802 | } sqlite3_free(aTC); } } #endif fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc); return rc; } /* ** Invalidate the current position list for phrase pPhrase. */ static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){ |
︙ | ︙ | |||
126590 126591 126592 126593 126594 126595 126596 126597 126598 126599 126600 126601 126602 126603 | fts3EvalNextRow(pCsr, pExpr, &rc); pCsr->isEof = pExpr->bEof; pCsr->isRequireSeek = 1; pCsr->isMatchinfoNeeded = 1; pCsr->iPrevId = pExpr->iDocid; }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); } return rc; } /* ** Restart interation for expression pExpr so that the next call to ** fts3EvalNext() visits the first row. Do not allow incremental ** loading or merging of phrase doclists for this iteration. | > > > > > > > > > > | 127271 127272 127273 127274 127275 127276 127277 127278 127279 127280 127281 127282 127283 127284 127285 127286 127287 127288 127289 127290 127291 127292 127293 127294 | fts3EvalNextRow(pCsr, pExpr, &rc); pCsr->isEof = pExpr->bEof; pCsr->isRequireSeek = 1; pCsr->isMatchinfoNeeded = 1; pCsr->iPrevId = pExpr->iDocid; }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); } /* Check if the cursor is past the end of the docid range specified ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */ if( rc==SQLITE_OK && ( (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid) || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid) )){ pCsr->isEof = 1; } return rc; } /* ** Restart interation for expression pExpr so that the next call to ** fts3EvalNext() visits the first row. Do not allow incremental ** loading or merging of phrase doclists for this iteration. |
︙ | ︙ | |||
126613 126614 126615 126616 126617 126618 126619 | ){ if( pExpr && *pRc==SQLITE_OK ){ Fts3Phrase *pPhrase = pExpr->pPhrase; if( pPhrase ){ fts3EvalInvalidatePoslist(pPhrase); if( pPhrase->bIncr ){ | > | | > > | < | | > > | 127304 127305 127306 127307 127308 127309 127310 127311 127312 127313 127314 127315 127316 127317 127318 127319 127320 127321 127322 127323 127324 127325 127326 127327 | ){ if( pExpr && *pRc==SQLITE_OK ){ Fts3Phrase *pPhrase = pExpr->pPhrase; if( pPhrase ){ fts3EvalInvalidatePoslist(pPhrase); if( pPhrase->bIncr ){ int i; for(i=0; i<pPhrase->nToken; i++){ Fts3PhraseToken *pToken = &pPhrase->aToken[i]; assert( pToken->pDeferred==0 ); if( pToken->pSegcsr ){ sqlite3Fts3MsrIncrRestart(pToken->pSegcsr); } } *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); } pPhrase->doclist.pNextDocid = 0; pPhrase->doclist.iDocid = 0; } pExpr->iDocid = 0; pExpr->bEof = 0; pExpr->bStart = 0; |
︙ | ︙ | |||
126867 126868 126869 126870 126871 126872 126873 126874 126875 | return SQLITE_OK; } iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int bOr = 0; u8 bEof = 0; | > > | > | > > > > > | > > | > > | > > | > > > | | > > > > > > > > > > > > > > > > | | | | | | | > > > > | | | | | > | 127562 127563 127564 127565 127566 127567 127568 127569 127570 127571 127572 127573 127574 127575 127576 127577 127578 127579 127580 127581 127582 127583 127584 127585 127586 127587 127588 127589 127590 127591 127592 127593 127594 127595 127596 127597 127598 127599 127600 127601 127602 127603 127604 127605 127606 127607 127608 127609 127610 127611 127612 127613 127614 127615 127616 127617 127618 127619 127620 127621 127622 127623 127624 127625 127626 127627 127628 127629 127630 127631 127632 127633 127634 127635 127636 127637 127638 127639 127640 127641 127642 127643 127644 127645 127646 127647 127648 127649 127650 127651 127652 127653 127654 127655 127656 127657 127658 127659 127660 127661 127662 127663 | return SQLITE_OK; } iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int iMul; /* +1 if csr dir matches index dir, else -1 */ int bOr = 0; u8 bEof = 0; u8 bTreeEof = 0; Fts3Expr *p; /* Used to iterate from pExpr to root */ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ /* Check if this phrase descends from an OR expression node. If not, ** return NULL. Otherwise, the entry that corresponds to docid ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the ** tree that the node is part of has been marked as EOF, but the node ** itself is not EOF, then it may point to an earlier entry. */ pNear = pExpr; for(p=pExpr->pParent; p; p=p->pParent){ if( p->eType==FTSQUERY_OR ) bOr = 1; if( p->eType==FTSQUERY_NEAR ) pNear = p; if( p->bEof ) bTreeEof = 1; } if( bOr==0 ) return SQLITE_OK; /* This is the descendent of an OR node. In this case we cannot use ** an incremental phrase. Load the entire doclist for the phrase ** into memory in this case. */ if( pPhrase->bIncr ){ int rc = SQLITE_OK; int bEofSave = pExpr->bEof; fts3EvalRestart(pCsr, pExpr, &rc); while( rc==SQLITE_OK && !pExpr->bEof ){ fts3EvalNextRow(pCsr, pExpr, &rc); if( bEofSave==0 && pExpr->iDocid==iDocid ) break; } pIter = pPhrase->doclist.pList; assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); if( rc!=SQLITE_OK ) return rc; } iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1); while( bTreeEof==1 && pNear->bEof==0 && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0 ){ int rc = SQLITE_OK; fts3EvalNextRow(pCsr, pExpr, &rc); if( rc!=SQLITE_OK ) return rc; iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; } bEof = (pPhrase->doclist.nAll==0); assert( bDescDoclist==0 || bDescDoclist==1 ); assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); if( bEof==0 ){ if( pCsr->bDesc==bDescDoclist ){ int dummy; if( pNear->bEof ){ /* This expression is already at EOF. So position it to point to the ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable ** iDocid is already set for this entry, so all that is required is ** to set pIter to point to the first byte of the last position-list ** in the doclist. ** ** It would also be correct to set pIter and iDocid to zero. In ** this case, the first call to sqltie3Fts4DoclistPrev() below ** would also move the iterator to point to the last entry in the ** doclist. However, this is expensive, as to do so it has to ** iterate through the entire doclist from start to finish (since ** it does not know the docid for the last entry). */ pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1]; fts3ReversePoslist(pPhrase->doclist.aAll, &pIter); } while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ sqlite3Fts3DoclistPrev( bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, &pIter, &iDocid, &dummy, &bEof ); } }else{ if( pNear->bEof ){ pIter = 0; iDocid = 0; } while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ sqlite3Fts3DoclistNext( bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, &pIter, &iDocid, &bEof ); } } } if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; } if( pIter==0 ) return SQLITE_OK; |
︙ | ︙ | |||
127024 127025 127026 127027 127028 127029 127030 127031 127032 127033 127034 127035 127036 127037 127038 127039 127040 127041 127042 127043 127044 | struct Fts3auxCursor { sqlite3_vtab_cursor base; /* Base class used by SQLite core */ Fts3MultiSegReader csr; /* Must be right after "base" */ Fts3SegFilter filter; char *zStop; int nStop; /* Byte-length of string zStop */ int isEof; /* True if cursor is at EOF */ sqlite3_int64 iRowid; /* Current rowid */ int iCol; /* Current value of 'col' column */ int nStat; /* Size of aStat[] array */ struct Fts3auxColstats { sqlite3_int64 nDoc; /* 'documents' values for current csr row */ sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ } *aStat; }; /* ** Schema of the terms table. */ | > > | | 127757 127758 127759 127760 127761 127762 127763 127764 127765 127766 127767 127768 127769 127770 127771 127772 127773 127774 127775 127776 127777 127778 127779 127780 127781 127782 127783 127784 127785 127786 127787 | struct Fts3auxCursor { sqlite3_vtab_cursor base; /* Base class used by SQLite core */ Fts3MultiSegReader csr; /* Must be right after "base" */ Fts3SegFilter filter; char *zStop; int nStop; /* Byte-length of string zStop */ int iLangid; /* Language id to query */ int isEof; /* True if cursor is at EOF */ sqlite3_int64 iRowid; /* Current rowid */ int iCol; /* Current value of 'col' column */ int nStat; /* Size of aStat[] array */ struct Fts3auxColstats { sqlite3_int64 nDoc; /* 'documents' values for current csr row */ sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ } *aStat; }; /* ** Schema of the terms table. */ #define FTS3_AUX_SCHEMA \ "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)" /* ** This function does all the work for both the xConnect and xCreate methods. ** These tables have no persistent representation of their own, so xConnect ** and xCreate are identical operations. */ static int fts3auxConnectMethod( |
︙ | ︙ | |||
127085 127086 127087 127088 127089 127090 127091 | goto bad_args; } }else{ zFts3 = argv[3]; } nFts3 = (int)strlen(zFts3); | | | 127820 127821 127822 127823 127824 127825 127826 127827 127828 127829 127830 127831 127832 127833 127834 | goto bad_args; } }else{ zFts3 = argv[3]; } nFts3 = (int)strlen(zFts3); rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA); if( rc!=SQLITE_OK ) return rc; nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; p = (Fts3auxTable *)sqlite3_malloc(nByte); if( !p ) return SQLITE_NOMEM; memset(p, 0, nByte); |
︙ | ︙ | |||
127145 127146 127147 127148 127149 127150 127151 127152 127153 127154 127155 127156 127157 127158 127159 127160 127161 127162 | sqlite3_vtab *pVTab, sqlite3_index_info *pInfo ){ int i; int iEq = -1; int iGe = -1; int iLe = -1; UNUSED_PARAMETER(pVTab); /* This vtab delivers always results in "ORDER BY term ASC" order. */ if( pInfo->nOrderBy==1 && pInfo->aOrderBy[0].iColumn==0 && pInfo->aOrderBy[0].desc==0 ){ pInfo->orderByConsumed = 1; } | > > | > | > > > | | | | | > > > > | | | > > > > | 127880 127881 127882 127883 127884 127885 127886 127887 127888 127889 127890 127891 127892 127893 127894 127895 127896 127897 127898 127899 127900 127901 127902 127903 127904 127905 127906 127907 127908 127909 127910 127911 127912 127913 127914 127915 127916 127917 127918 127919 127920 127921 127922 127923 127924 127925 127926 127927 127928 127929 127930 127931 127932 127933 127934 127935 127936 127937 127938 127939 127940 127941 127942 127943 127944 127945 127946 127947 127948 | sqlite3_vtab *pVTab, sqlite3_index_info *pInfo ){ int i; int iEq = -1; int iGe = -1; int iLe = -1; int iLangid = -1; int iNext = 1; /* Next free argvIndex value */ UNUSED_PARAMETER(pVTab); /* This vtab delivers always results in "ORDER BY term ASC" order. */ if( pInfo->nOrderBy==1 && pInfo->aOrderBy[0].iColumn==0 && pInfo->aOrderBy[0].desc==0 ){ pInfo->orderByConsumed = 1; } /* Search for equality and range constraints on the "term" column. ** And equality constraints on the hidden "languageid" column. */ for(i=0; i<pInfo->nConstraint; i++){ if( pInfo->aConstraint[i].usable ){ int op = pInfo->aConstraint[i].op; int iCol = pInfo->aConstraint[i].iColumn; if( iCol==0 ){ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; } if( iCol==4 ){ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i; } } } if( iEq>=0 ){ pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; pInfo->aConstraintUsage[iEq].argvIndex = iNext++; pInfo->estimatedCost = 5; }else{ pInfo->idxNum = 0; pInfo->estimatedCost = 20000; if( iGe>=0 ){ pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; pInfo->aConstraintUsage[iGe].argvIndex = iNext++; pInfo->estimatedCost /= 2; } if( iLe>=0 ){ pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; pInfo->aConstraintUsage[iLe].argvIndex = iNext++; pInfo->estimatedCost /= 2; } } if( iLangid>=0 ){ pInfo->aConstraintUsage[iLangid].argvIndex = iNext++; pInfo->estimatedCost--; } return SQLITE_OK; } /* ** xOpen - Open a cursor. */ |
︙ | ︙ | |||
127345 127346 127347 127348 127349 127350 127351 | const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; int rc; | | > > > > > > > > | > > > > > > > > > > > > > | > | | | | | > > > > > > > > > > > > | | 128094 128095 128096 128097 128098 128099 128100 128101 128102 128103 128104 128105 128106 128107 128108 128109 128110 128111 128112 128113 128114 128115 128116 128117 128118 128119 128120 128121 128122 128123 128124 128125 128126 128127 128128 128129 128130 128131 128132 128133 128134 128135 128136 128137 128138 128139 128140 128141 128142 128143 128144 128145 128146 128147 128148 128149 128150 128151 128152 128153 128154 128155 128156 128157 128158 128159 128160 128161 128162 128163 128164 128165 128166 128167 128168 128169 128170 128171 128172 128173 128174 128175 128176 128177 128178 128179 | const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; int rc; int isScan = 0; int iLangVal = 0; /* Language id to query */ int iEq = -1; /* Index of term=? value in apVal */ int iGe = -1; /* Index of term>=? value in apVal */ int iLe = -1; /* Index of term<=? value in apVal */ int iLangid = -1; /* Index of languageid=? value in apVal */ int iNext = 0; UNUSED_PARAMETER(nVal); UNUSED_PARAMETER(idxStr); assert( idxStr==0 ); assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ); if( idxNum==FTS4AUX_EQ_CONSTRAINT ){ iEq = iNext++; }else{ isScan = 1; if( idxNum & FTS4AUX_GE_CONSTRAINT ){ iGe = iNext++; } if( idxNum & FTS4AUX_LE_CONSTRAINT ){ iLe = iNext++; } } if( iNext<nVal ){ iLangid = iNext++; } /* In case this cursor is being reused, close and zero it. */ testcase(pCsr->filter.zTerm); sqlite3Fts3SegReaderFinish(&pCsr->csr); sqlite3_free((void *)pCsr->filter.zTerm); sqlite3_free(pCsr->aStat); memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; if( iEq>=0 || iGe>=0 ){ const unsigned char *zStr = sqlite3_value_text(apVal[0]); assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) ); if( zStr ){ pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]); if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; } } if( iLe>=0 ){ pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe])); pCsr->nStop = sqlite3_value_bytes(apVal[iLe]); if( pCsr->zStop==0 ) return SQLITE_NOMEM; } if( iLangid>=0 ){ iLangVal = sqlite3_value_int(apVal[iLangid]); /* If the user specified a negative value for the languageid, use zero ** instead. This works, as the "languageid=?" constraint will also ** be tested by the VDBE layer. The test will always be false (since ** this module will not return a row with a negative languageid), and ** so the overall query will return zero rows. */ if( iLangVal<0 ) iLangVal = 0; } pCsr->iLangid = iLangVal; rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL, pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr ); if( rc==SQLITE_OK ){ rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); } if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor); |
︙ | ︙ | |||
127406 127407 127408 127409 127410 127411 127412 | } /* ** xColumn - Return a column value. */ static int fts3auxColumnMethod( sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ | | | > | > | > | | | | | > | > | > | > | > > > > > > | 128189 128190 128191 128192 128193 128194 128195 128196 128197 128198 128199 128200 128201 128202 128203 128204 128205 128206 128207 128208 128209 128210 128211 128212 128213 128214 128215 128216 128217 128218 128219 128220 128221 128222 128223 128224 128225 128226 128227 128228 128229 128230 128231 128232 128233 | } /* ** xColumn - Return a column value. */ static int fts3auxColumnMethod( sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ int iCol /* Index of column to read value from */ ){ Fts3auxCursor *p = (Fts3auxCursor *)pCursor; assert( p->isEof==0 ); switch( iCol ){ case 0: /* term */ sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); break; case 1: /* col */ if( p->iCol ){ sqlite3_result_int(pCtx, p->iCol-1); }else{ sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC); } break; case 2: /* documents */ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc); break; case 3: /* occurrences */ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc); break; default: /* languageid */ assert( iCol==4 ); sqlite3_result_int(pCtx, p->iLangid); break; } return SQLITE_OK; } /* ** xRowid - Return the current rowid for the cursor. |
︙ | ︙ | |||
135754 135755 135756 135757 135758 135759 135760 | p->bAutoincrmerge = fts3Getint(&zParam)!=0; if( !p->bHasStat ){ assert( p->bFts4==0 ); sqlite3Fts3CreateStatTable(&rc, p); if( rc ) return rc; } rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); | | | 136550 136551 136552 136553 136554 136555 136556 136557 136558 136559 136560 136561 136562 136563 136564 | p->bAutoincrmerge = fts3Getint(&zParam)!=0; if( !p->bHasStat ){ assert( p->bFts4==0 ); sqlite3Fts3CreateStatTable(&rc, p); if( rc ) return rc; } rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); if( rc ) return rc; sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); return rc; } |
︙ | ︙ | |||
136023 136024 136025 136026 136027 136028 136029 136030 136031 136032 136033 136034 136035 136036 | rc = fts3DoAutoincrmerge(p, &zVal[10]); #ifdef SQLITE_TEST }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ p->nNodeSize = atoi(&zVal[9]); rc = SQLITE_OK; }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ p->nMaxPendingData = atoi(&zVal[11]); rc = SQLITE_OK; #endif }else{ rc = SQLITE_ERROR; } return rc; | > > > | 136819 136820 136821 136822 136823 136824 136825 136826 136827 136828 136829 136830 136831 136832 136833 136834 136835 | rc = fts3DoAutoincrmerge(p, &zVal[10]); #ifdef SQLITE_TEST }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ p->nNodeSize = atoi(&zVal[9]); rc = SQLITE_OK; }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ p->nMaxPendingData = atoi(&zVal[11]); rc = SQLITE_OK; }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){ p->bNoIncrDoclist = atoi(&zVal[21]); rc = SQLITE_OK; #endif }else{ rc = SQLITE_ERROR; } return rc; |
︙ | ︙ |
Changes to src/sqlite3.h.
︙ | ︙ | |||
105 106 107 108 109 110 111 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.1" #define SQLITE_VERSION_NUMBER 3008001 | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.1" #define SQLITE_VERSION_NUMBER 3008001 #define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
1613 1614 1615 1616 1617 1618 1619 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI | | | | | | | | | | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 | ** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(This option takes a single argument of type int. If non-zero, then ** URI handling is globally enabled. If the parameter is zero, then URI handling ** is globally disabled.)^ ^If URI handling is globally enabled, all filenames ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined.)^ ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd>^This option takes a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. ^The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | ** the connection being passed as the second parameter is being closed. The ** third parameter is passed NULL In this case. An example of using this ** configuration option can be seen in the "test_sqllog.c" source file in ** the canonical SQLite source tree.</dd> ** ** [[SQLITE_CONFIG_MMAP_SIZE]] ** <dt>SQLITE_CONFIG_MMAP_SIZE | | | | | | | 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | ** the connection being passed as the second parameter is being closed. The ** third parameter is passed NULL In this case. An example of using this ** configuration option can be seen in the "test_sqllog.c" source file in ** the canonical SQLite source tree.</dd> ** ** [[SQLITE_CONFIG_MMAP_SIZE]] ** <dt>SQLITE_CONFIG_MMAP_SIZE ** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values ** that are the default mmap size limit (the default setting for ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. ** ^The default setting can be overridden by each database connection using ** either the [PRAGMA mmap_size] command, or by using the ** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size ** cannot be changed at run-time. Nor may the maximum allowed mmap size ** exceed the compile-time maximum mmap size set by the ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ |
︙ | ︙ |
Changes to src/stat.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to implement the stat web page ** */ | < > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to implement the stat web page ** */ #include "config.h" #include <string.h> #include "stat.h" /* ** For a sufficiently large integer, provide an alternative ** representation as MB or GB or TB. */ static void bigSizeName(int nOut, char *zOut, sqlite3_int64 v){ |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
684 685 686 687 688 689 690 691 692 693 694 695 696 697 | "the format for the timeline version display(no history permission!)", @ font-weight: bold; }, { "td.timelineTime", "the format for the timeline time display", @ vertical-align: top; @ text-align: right; }, { "td.timelineGraph", "the format for the grap placeholder cells in timelines", @ width: 20px; @ text-align: left; @ vertical-align: top; }, | > | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | "the format for the timeline version display(no history permission!)", @ font-weight: bold; }, { "td.timelineTime", "the format for the timeline time display", @ vertical-align: top; @ text-align: right; @ white-space: nowrap; }, { "td.timelineGraph", "the format for the grap placeholder cells in timelines", @ width: 20px; @ text-align: left; @ vertical-align: top; }, |
︙ | ︙ | |||
1223 1224 1225 1226 1227 1228 1229 | /* ** This page is a honeypot for spiders and bots. ** ** WEBPAGE: honeypot */ void honeypot_page(void){ cgi_set_status(403, "Forbidden"); | | | 1224 1225 1226 1227 1228 1229 1230 1231 1232 | /* ** This page is a honeypot for spiders and bots. ** ** WEBPAGE: honeypot */ void honeypot_page(void){ cgi_set_status(403, "Forbidden"); @ <p>Please enable javascript or log in to see this content</p> } |
Changes to src/sync.c.
︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | }else{ /* Autosync defaults on. To make it default off, "return" here. */ } url_parse(0, URL_REMEMBER); if( g.urlProtocol==0 ) return 0; if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = unobscure(db_get("last-sync-pw", 0)); } #if 0 /* Disabled for now */ if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){ /* When doing an automatic pull, also automatically pull shuns from ** the server if pull_shuns is enabled. ** ** TODO: What happens if the shun list gets really big? | > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | }else{ /* Autosync defaults on. To make it default off, "return" here. */ } url_parse(0, URL_REMEMBER); if( g.urlProtocol==0 ) return 0; if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = unobscure(db_get("last-sync-pw", 0)); g.urlFlags |= URL_PROMPT_PW; url_prompt_for_password(); } #if 0 /* Disabled for now */ if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){ /* When doing an automatic pull, also automatically pull shuns from ** the server if pull_shuns is enabled. ** ** TODO: What happens if the shun list gets really big? |
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | /* The --verily option to sync, push, and pull forces extra igot cards ** to be exchanged. This can overcome malfunctions in the sync protocol. */ if( find_option("verily",0,0)!=0 ){ *pSyncFlags |= SYNC_RESYNC; } url_proxy_options(); db_find_and_open_repository(0, 0); db_open_config(0); if( g.argc==2 ){ if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN; }else if( g.argc==3 ){ zUrl = g.argv[2]; } url_parse(zUrl, urlFlags); if( g.urlProtocol==0 ){ if( urlOptional ) fossil_exit(0); usage("URL"); } user_select(); | > > > > | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | /* The --verily option to sync, push, and pull forces extra igot cards ** to be exchanged. This can overcome malfunctions in the sync protocol. */ if( find_option("verily",0,0)!=0 ){ *pSyncFlags |= SYNC_RESYNC; } url_proxy_options(); clone_ssh_find_options(); db_find_and_open_repository(0, 0); db_open_config(0); if( g.argc==2 ){ if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN; }else if( g.argc==3 ){ zUrl = g.argv[2]; } if( urlFlags & URL_REMEMBER ){ clone_ssh_db_set_options(); } url_parse(zUrl, urlFlags); if( g.urlProtocol==0 ){ if( urlOptional ) fossil_exit(0); usage("URL"); } user_select(); |
︙ | ︙ |
Changes to src/tag.c.
︙ | ︙ | |||
387 388 389 390 391 392 393 | */ void tag_cmd(void){ int n; int fRaw = find_option("raw","",0)!=0; int fPropagate = find_option("propagate","",0)!=0; const char *zPrefix = fRaw ? "" : "sym-"; char const * zFindLimit = find_option("limit","n",1); | | | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | */ void tag_cmd(void){ int n; int fRaw = find_option("raw","",0)!=0; int fPropagate = find_option("propagate","",0)!=0; const char *zPrefix = fRaw ? "" : "sym-"; char const * zFindLimit = find_option("limit","n",1); int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000; db_find_and_open_repository(0, 0); if( g.argc<3 ){ goto tag_cmd_usage; } n = strlen(g.argv[2]); if( n==0 ){ |
︙ | ︙ | |||
442 443 444 445 446 447 448 | blob_appendf(&sql, "SELECT blob.uuid FROM tagxref, blob" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " AND tagxref.tagtype>0" " AND blob.rid=tagxref.rid", g.argv[3] ); | | | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | blob_appendf(&sql, "SELECT blob.uuid FROM tagxref, blob" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " AND tagxref.tagtype>0" " AND blob.rid=tagxref.rid", g.argv[3] ); if( nFindLimit>0 ){ blob_appendf(&sql, " LIMIT %d", nFindLimit); } db_prepare(&q, "%s", blob_str(&sql)); blob_reset(&sql); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%s\n", db_column_text(&q, 0)); } |
︙ | ︙ | |||
465 466 467 468 469 470 471 | " AND blob.rid IN (" " SELECT rid FROM tagxref" " WHERE tagtype>0 AND tagid=%d" ")" " ORDER BY event.mtime DESC", timeline_query_for_tty(), zType, tagid ); | < < < | | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | " AND blob.rid IN (" " SELECT rid FROM tagxref" " WHERE tagtype>0 AND tagid=%d" ")" " ORDER BY event.mtime DESC", timeline_query_for_tty(), zType, tagid ); db_prepare(&q, "%s", blob_str(&sql)); blob_reset(&sql); print_timeline(&q, nFindLimit, 79, 0); db_finalize(&q); } } }else if( strncmp(g.argv[2],"list",n)==0 ){ Stmt q; |
︙ | ︙ |
Changes to src/tar.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to generate tarballs. */ #include <assert.h> #include <zlib.h> | > < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to generate tarballs. */ #include "config.h" #include <assert.h> #include <zlib.h> #include "tar.h" /* ** State information for the tarball builder. */ static struct tarball_t { unsigned char *aHdr; /* Space for building headers */ |
︙ | ︙ | |||
477 478 479 480 481 482 483 | blob_zero(&filename); if( zDir && zDir[0] ){ blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); | | | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | blob_zero(&filename); if( zDir && zDir[0] ){ blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ mTime = (pManifest->rDate - 2440587.5)*86400.0; tar_begin(mTime); if( db_get_boolean("manifest", 0) ){ blob_append(&filename, "manifest", -1); zName = blob_str(&filename); tar_add_file(zName, &mfile, 0, mTime); |
︙ | ︙ |
Changes to src/th.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** The implementation of the TH core. This file contains the parser, and ** the implementation of the interface in th.h. */ #include "th.h" #include <string.h> #include <assert.h> typedef struct Th_Command Th_Command; typedef struct Th_Frame Th_Frame; typedef struct Th_Variable Th_Variable; | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ** The implementation of the TH core. This file contains the parser, and ** the implementation of the interface in th.h. */ #include "config.h" #include "th.h" #include <string.h> #include <assert.h> typedef struct Th_Command Th_Command; typedef struct Th_Frame Th_Frame; typedef struct Th_Variable Th_Variable; |
︙ | ︙ | |||
2352 2353 2354 2355 2356 2357 2358 | int th_isalnum(char c){ return (aCharProp[(unsigned char)c] & 0x0A); } #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif | < | 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 | int th_isalnum(char c){ return (aCharProp[(unsigned char)c] & 0x0A); } #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif /* ** Return TRUE if z is a pure numeric string. Return FALSE if the ** string contains any character which is not part of a number. If ** the string is numeric and contains the '.' character, set *realnum ** to TRUE (otherwise FALSE). |
︙ | ︙ |
Changes to src/th_main.c.
︙ | ︙ | |||
527 528 529 530 531 532 533 | static int repositoryCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ | < < > | 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | static int repositoryCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ if( argc!=1 && argc!=2 ){ return Th_WrongNumArgs(interp, "repository ?BOOLEAN?"); } if( argc==2 ){ int openRepository = 0; if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){ return TH_ERROR; } if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0); } Th_SetResult(interp, g.zRepositoryName, -1); return TH_OK; |
︙ | ︙ |
Changes to src/th_tcl.c.
︙ | ︙ | |||
28 29 30 31 32 33 34 | /* ** These macros are designed to reduce the redundant code required to marshal ** arguments from TH1 to Tcl. */ #define USE_ARGV_TO_OBJV() \ int objc; \ Tcl_Obj **objv; \ | | | | | | | | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | /* ** These macros are designed to reduce the redundant code required to marshal ** arguments from TH1 to Tcl. */ #define USE_ARGV_TO_OBJV() \ int objc; \ Tcl_Obj **objv; \ int obji; #define COPY_ARGV_TO_OBJV() \ objc = argc-1; \ objv = (Tcl_Obj **)ckalloc((unsigned)(objc * sizeof(Tcl_Obj *))); \ for(obji=1; obji<argc; obji++){ \ objv[obji-1] = Tcl_NewStringObj(argv[obji], argl[obji]); \ Tcl_IncrRefCount(objv[obji-1]); \ } #define FREE_ARGV_TO_OBJV() \ for(obji=1; obji<argc; obji++){ \ Tcl_DecrRefCount(objv[obji-1]); \ } \ ckfree((char *)objv); /* ** Fetch the Tcl interpreter from the specified void pointer, cast to a Tcl ** context. */ #define GET_CTX_TCL_INTERP(ctx) \ |
︙ | ︙ | |||
107 108 109 110 111 112 113 | # endif # ifndef TCL_MINOR_OFFSET # define TCL_MINOR_OFFSET (8) # endif # endif /* defined(__CYGWIN__) */ # endif /* defined(_WIN32) */ # ifndef TCL_FINDEXECUTABLE_NAME | | | | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | # endif # ifndef TCL_MINOR_OFFSET # define TCL_MINOR_OFFSET (8) # endif # endif /* defined(__CYGWIN__) */ # endif /* defined(_WIN32) */ # ifndef TCL_FINDEXECUTABLE_NAME # define TCL_FINDEXECUTABLE_NAME "_Tcl_FindExecutable\0" # endif # ifndef TCL_CREATEINTERP_NAME # define TCL_CREATEINTERP_NAME "_Tcl_CreateInterp\0" # endif # ifndef TCL_DELETEINTERP_NAME # define TCL_DELETEINTERP_NAME "_Tcl_DeleteInterp\0" # endif # ifndef TCL_FINALIZE_NAME # define TCL_FINALIZE_NAME "_Tcl_Finalize\0" # endif #endif /* defined(USE_TCL_STUBS) */ /* ** The function types for Tcl_FindExecutable and Tcl_CreateInterp are needed ** when the Tcl library is being loaded dynamically by a stubs-enabled ** application (i.e. the inverse of using a stubs-enabled package). These are |
︙ | ︙ | |||
309 310 311 312 313 314 315 | const char **argv, int *argl, int rc ){ struct TclContext *tclContext = (struct TclContext *)ctx; tcl_NotifyProc *xNotifyProc; | | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | const char **argv, int *argl, int rc ){ struct TclContext *tclContext = (struct TclContext *)ctx; tcl_NotifyProc *xNotifyProc; if( !tclContext ){ Th_ErrorMessage(interp, "invalid Tcl context", (const char *)"", 0); return TH_ERROR; } xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval; if( xNotifyProc ){ rc = xNotifyProc(bIsPost ? tclContext->pPostContext : tclContext->pPreContext, interp, ctx, argc, argv, argl, rc); } return rc; } |
︙ | ︙ | |||
781 782 783 784 785 786 787 | struct TclContext *tclContext = (struct TclContext *)pContext; int argc; char **argv; char *argv0 = 0; Tcl_Interp *tclInterp; char *setup; | | | | 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | struct TclContext *tclContext = (struct TclContext *)pContext; int argc; char **argv; char *argv0 = 0; Tcl_Interp *tclInterp; char *setup; if( !tclContext ){ Th_ErrorMessage(interp, "invalid Tcl context", (const char *)"", 0); return TH_ERROR; } if( tclContext->interp ){ return TH_OK; } if( loadTcl(interp, &tclContext->library, &tclContext->xFindExecutable, &tclContext->xCreateInterp, &tclContext->xDeleteInterp, &tclContext->xFinalize)!=TH_OK ){ return TH_ERROR; } |
︙ | ︙ | |||
880 881 882 883 884 885 886 | struct TclContext *tclContext = (struct TclContext *)pContext; Tcl_Interp *tclInterp; tcl_FinalizeProc *xFinalize; #if defined(USE_TCL_STUBS) void *library; #endif /* defined(USE_TCL_STUBS) */ | | | | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 | struct TclContext *tclContext = (struct TclContext *)pContext; Tcl_Interp *tclInterp; tcl_FinalizeProc *xFinalize; #if defined(USE_TCL_STUBS) void *library; #endif /* defined(USE_TCL_STUBS) */ if( !tclContext ){ Th_ErrorMessage(interp, "invalid Tcl context", (const char *)"", 0); return TH_ERROR; } /* ** Grab the Tcl_Finalize function pointer prior to deleting the Tcl ** interpreter because the memory backing the Tcl stubs table will ** be going away. */ xFinalize = tclContext->xFinalize; /* ** If the Tcl interpreter has been created, formally delete it now. */ tclInterp = tclContext->interp; if( tclInterp ){ Tcl_DeleteInterp(tclInterp); tclContext->interp = tclInterp = 0; } /* ** If the Tcl library is not finalized prior to unloading it, a deadlock ** can occur in some circumstances (i.e. the [clock] thread is running). */ |
︙ | ︙ | |||
937 938 939 940 941 942 943 | void *pContext ){ int i; /* Add the Tcl integration commands to TH1. */ for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ void *ctx; | | | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 | void *pContext ){ int i; /* Add the Tcl integration commands to TH1. */ for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ void *ctx; if( !aCommand[i].zName || !aCommand[i].xProc ) continue; ctx = aCommand[i].pContext; /* Use Tcl interpreter for context? */ if( !ctx ) ctx = pContext; Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0); } return TH_OK; } #endif /* FOSSIL_ENABLE_TCL */ |
Changes to src/timeline.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to implement the timeline web page ** */ #include <string.h> #include <time.h> | > < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to implement the timeline web page ** */ #include "config.h" #include <string.h> #include <time.h> #include "timeline.h" /* ** Shorten a UUID so that is the minimum length needed to contain ** at least one digit in the range 'a'..'f'. The minimum length is 10. */ static void shorten_uuid(char *zDest, const char *zSrc){ |
︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | GraphContext *pGraph = 0; int prevWasDivider = 0; /* True if previous output row was <hr> */ int fchngQueryInit = 0; /* True if fchngQuery is initialized */ Stmt fchngQuery; /* Query for file changes on check-ins */ static Stmt qbranch; int pendingEndTr = 0; /* True if a </td></tr> is needed */ int vid = 0; /* Current checkout version */ if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){ vid = db_lget_int("checkout", 0); } zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); if( tmFlags & TIMELINE_GRAPH ){ pGraph = graph_init(); /* style is not moved to css, because this is ** a technical div for the timeline graph */ @ <div id="canvas" style="position:relative;height:0px;width:0px;" @ onclick="clickOnGraph(event)"></div> | > > > > | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | GraphContext *pGraph = 0; int prevWasDivider = 0; /* True if previous output row was <hr> */ int fchngQueryInit = 0; /* True if fchngQuery is initialized */ Stmt fchngQuery; /* Query for file changes on check-ins */ static Stmt qbranch; int pendingEndTr = 0; /* True if a </td></tr> is needed */ int vid = 0; /* Current checkout version */ int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS 2: YYYY-MM-DD HH:MM 3: YYMMDD HH:MM */ if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){ vid = db_lget_int("checkout", 0); } zPrevDate[0] = 0; mxWikiLen = db_get_int("timeline-max-comment", 0); dateFormat = db_get_int("timeline-date-format", 0); if( tmFlags & TIMELINE_GRAPH ){ pGraph = graph_init(); /* style is not moved to css, because this is ** a technical div for the timeline graph */ @ <div id="canvas" style="position:relative;height:0px;width:0px;" @ onclick="clickOnGraph(event)"></div> |
︙ | ︙ | |||
280 281 282 283 284 285 286 | const char *zUser = db_column_text(pQuery, 4); const char *zTagList = db_column_text(pQuery, 8); int tagid = db_column_int(pQuery, 9); const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous"; const char *zBr = 0; /* Branch */ int commentColumn = 3; /* Column containing comment text */ int modPending; /* Pending moderation */ | | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | const char *zUser = db_column_text(pQuery, 4); const char *zTagList = db_column_text(pQuery, 8); int tagid = db_column_int(pQuery, 9); const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous"; const char *zBr = 0; /* Branch */ int commentColumn = 3; /* Column containing comment text */ int modPending; /* Pending moderation */ char zTime[20]; modPending = moderation_pending(rid); if( tagid ){ if( modPending ) tagid = -tagid; if( tagid==prevTagid ){ if( tmFlags & TIMELINE_BRIEF ){ suppressCnt++; |
︙ | ︙ | |||
312 313 314 315 316 317 318 | if( !prevWasDivider ){ @ <tr><td colspan="3"><hr /></td></tr> } prevWasDivider = 1; continue; } prevWasDivider = 0; | > | | | | | | | | > > > > > > > > > > > > > > > | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | if( !prevWasDivider ){ @ <tr><td colspan="3"><hr /></td></tr> } prevWasDivider = 1; continue; } prevWasDivider = 0; if( dateFormat<2 ){ if( memcmp(zDate, zPrevDate, 10) ){ sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); @ <tr><td> @ <div class="divider timelineDate">%s(zPrevDate)</div> @ </td><td></td><td></td></tr> } memcpy(zTime, &zDate[11], 5+dateFormat*3); zTime[5+dateFormat*3] = 0; }else if(3==dateFormat){ /* YYMMDD HH:MM */ int pos = 0; zTime[pos++] = zDate[2]; zTime[pos++] = zDate[3]; /* YY */ zTime[pos++] = zDate[5]; zTime[pos++] = zDate[6]; /* MM */ zTime[pos++] = zDate[8]; zTime[pos++] = zDate[9]; /* DD */ zTime[pos++] = ' '; zTime[pos++] = zDate[11]; zTime[pos++] = zDate[12]; /* HH */ zTime[pos++] = ':'; zTime[pos++] = zDate[14]; zTime[pos++] = zDate[15]; /* MM */ zTime[pos++] = 0; }else{ /* YYYY-MM-DD HH:MM */ sqlite3_snprintf(sizeof(zTime), zTime, "%.16s", zDate); } if( rid == vid ){ @ <tr class="timelineCurrent"> }else { @ <tr> } @ <td class="timelineTime">%s(zTime)</td> @ <td class="timelineGraph"> |
︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 | style_footer(); } /* ** The input query q selects various records. Print a human-readable ** summary of those records. ** | > > > | > > > | > > | > > > > > > > > > | | 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | style_footer(); } /* ** The input query q selects various records. Print a human-readable ** summary of those records. ** ** Limit number of lines or entries printed to nLimit. If nLimit is zero ** there is no limit. If nLimit is greater than zero, limit the number of ** complete entries printed. If nLimit is less than zero, attempt to limit ** the number of lines printed (this is basically the legacy behavior). ** The line limit, if used, is approximate because it is only checked on a ** per-entry basis. If verbose mode, the file name details are considered ** to be part of the entry. ** ** The query should return these columns: ** ** 0. rid ** 1. uuid ** 2. Date/Time ** 3. Comment string and user ** 4. Number of non-merge children ** 5. Number of parents ** 6. mtime ** 7. branch */ void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){ int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit; int nLine = 0; int nEntry = 0; char zPrevDate[20]; const char *zCurrentUuid=0; int fchngQueryInit = 0; /* True if fchngQuery is initialized */ Stmt fchngQuery; /* Query for file changes on check-ins */ zPrevDate[0] = 0; if( g.localOpen ){ int rid = db_lget_int("checkout", 0); zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); } while( db_step(q)==SQLITE_ROW ){ int rid = db_column_int(q, 0); const char *zId = db_column_text(q, 1); const char *zDate = db_column_text(q, 2); const char *zCom = db_column_text(q, 3); int nChild = db_column_int(q, 4); int nParent = db_column_int(q, 5); char *zFree = 0; int n = 0; char zPrefix[80]; char zUuid[UUID_SIZE+1]; if( nAbsLimit!=0 ){ if( nLimit<0 && nLine>=nAbsLimit ){ fossil_print("=== line limit (%d) reached ===\n", nAbsLimit); break; /* line count limit hit, stop. */ }else if( nEntry>=nAbsLimit ){ fossil_print("=== entry limit (%d) reached ===\n", nAbsLimit); break; /* entry count limit hit, stop. */ } } sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId); if( memcmp(zDate, zPrevDate, 10) ){ fossil_print("=== %.10s ===\n", zDate); memcpy(zPrevDate, zDate, 10); nLine++; /* record another line */ } if( zCom==0 ) zCom = ""; fossil_print("%.8s ", &zDate[11]); zPrefix[0] = 0; if( nParent>1 ){ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* "); n = strlen(zPrefix); |
︙ | ︙ | |||
1538 1539 1540 1541 1542 1543 1544 | n = strlen(zPrefix); } if( fossil_strcmp(zCurrentUuid,zId)==0 ){ sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* "); n += strlen(zPrefix); } zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom); | | | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | n = strlen(zPrefix); } if( fossil_strcmp(zCurrentUuid,zId)==0 ){ sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* "); n += strlen(zPrefix); } zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom); nLine += comment_print(zFree, 9, width); /* record another X lines */ sqlite3_free(zFree); if(verboseFlag){ if( !fchngQueryInit ){ db_prepare(&fchngQuery, "SELECT (pid==0) AS isnew," " (fid==0) AS isdel," |
︙ | ︙ | |||
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 | if( isNew ){ fossil_print(" ADDED %s\n",zFilename); }else if( isDel ){ fossil_print(" DELETED %s\n",zFilename); }else{ fossil_print(" EDITED %s\n", zFilename); } } db_reset(&fchngQuery); } } if( fchngQueryInit ) db_finalize(&fchngQuery); } /* ** Return a pointer to a static string that forms the basis for ** a timeline query for display on a TTY. | > > | 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 | if( isNew ){ fossil_print(" ADDED %s\n",zFilename); }else if( isDel ){ fossil_print(" DELETED %s\n",zFilename); }else{ fossil_print(" EDITED %s\n", zFilename); } nLine++; /* record another line */ } db_reset(&fchngQuery); } nEntry++; /* record another complete entry */ } if( fchngQueryInit ) db_finalize(&fchngQuery); } /* ** Return a pointer to a static string that forms the basis for ** a timeline query for display on a TTY. |
︙ | ︙ | |||
1640 1641 1642 1643 1644 1645 1646 | ** ** The BASELINE can be any unique prefix of 4 characters or more. ** The DATETIME should be in the ISO8601 format. For ** examples: "2007-08-18 07:21:21". You can also say "current" ** for the current version or "now" for the current time. ** ** Options: | | > > | > > | > > > > > > > > | | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 | ** ** The BASELINE can be any unique prefix of 4 characters or more. ** The DATETIME should be in the ISO8601 format. For ** examples: "2007-08-18 07:21:21". You can also say "current" ** for the current version or "now" for the current time. ** ** Options: ** -n|--limit N Output the first N entries (default 20 lines). ** N=0 means no limit. ** -t|--type TYPE Output items from the given types only, such as: ** ci = file commits only ** e = events only ** t = tickets only ** w = wiki commits only ** -v|--verbose Output the list of files changed by each commit ** and the type of each change (edited, deleted, ** etc.) after the checkin comment. ** -W|--width <num> With of lines (default 79). Must be >20 or 0. */ void timeline_cmd(void){ Stmt q; int n, k, width; const char *zLimit; const char *zWidth; const char *zType; char *zOrigin; char *zDate; Blob sql; int objid = 0; Blob uuid; int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */ int verboseFlag = 0 ; verboseFlag = find_option("verbose","v", 0)!=0; if( !verboseFlag){ verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */ } db_find_and_open_repository(0, 0); zLimit = find_option("limit","n",1); zWidth = find_option("width","W",1); zType = find_option("type","t",1); if ( !zLimit ){ zLimit = find_option("count",0,1); } if( zLimit ){ n = atoi(zLimit); }else{ n = -20; } if( zWidth ){ width = atoi(zWidth); if( (width!=0) && (width<=20) ){ fossil_fatal("--width|-W value must be >20 or 0"); } }else{ width = 79; } if( g.argc>=4 ){ k = strlen(g.argv[2]); if( strncmp(g.argv[2],"before",k)==0 ){ mode = 1; }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){ mode = 2; }else if( strncmp(g.argv[2],"descendants",k)==0 ){ mode = 3; }else if( strncmp(g.argv[2],"children",k)==0 ){ mode = 3; }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){ mode = 4; }else if( strncmp(g.argv[2],"parents",k)==0 ){ mode = 4; }else if(!zType && !zLimit){ usage("?WHEN? ?BASELINE|DATETIME? ?-n|--limit #? ?-t|--type TYPE? ?-W|--width WIDTH?"); } if( '-' != *g.argv[3] ){ zOrigin = g.argv[3]; }else{ zOrigin = "now"; } }else if( g.argc==3 ){ |
︙ | ︙ | |||
1754 1755 1756 1757 1758 1759 1760 | } if( zType && (zType[0]!='a') ){ blob_appendf(&sql, " AND event.type=%Q ", zType); } blob_appendf(&sql, " ORDER BY event.mtime DESC"); db_prepare(&q, blob_str(&sql)); blob_reset(&sql); | | | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 | } if( zType && (zType[0]!='a') ){ blob_appendf(&sql, " AND event.type=%Q ", zType); } blob_appendf(&sql, " ORDER BY event.mtime DESC"); db_prepare(&q, blob_str(&sql)); blob_reset(&sql); print_timeline(&q, n, width, verboseFlag); db_finalize(&q); } /* ** This is a version of the "localtime()" function from the standard ** C library. It converts a unix timestamp (seconds since 1970) into ** a broken-out local time structure. |
︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 | const char *zUuid = db_column_text(&q, 0); @ <li> @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> } db_finalize(&q); style_footer(); } /* ** Helper for stats_report_by_month_year(), which generates a list of ** week numbers. zTimeframe should be either a timeframe in the form YYYY ** or YYYY-MM. */ static void stats_report_output_week_links(const char * zTimeframe){ Stmt stWeek = empty_Stmt; char yearPart[5] = {0,0,0,0,0}; memcpy(yearPart, zTimeframe, 4); db_prepare(&stWeek, "SELECT DISTINCT strftime('%%W',mtime) AS wk, " "count(*) AS n, " "substr(date(mtime),1,%d) AS ym " | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 | const char *zUuid = db_column_text(&q, 0); @ <li> @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> } db_finalize(&q); style_footer(); } /* ** Used by stats_report_xxxxx() to remember which type of events ** to show. Populated by stats_report_init_view() and holds the ** return value of that function. */ static int statsReportType = 0; /* ** Set by stats_report_init_view() to one of the y=XXXX values ** accepted by /timeline?y=XXXX. */ static char const * statsReportTimelineYFlag = NULL; /* ** Creates a TEMP VIEW named v_reports which is a wrapper around the ** EVENT table filtered on event.type. It looks for the request ** parameter 'type' (reminder: we "should" use 'y' for consistency ** with /timeline, but /reports uses 'y' for the year) and expects it ** to contain one of the conventional values from event.type or the ** value "all", which is treated as equivalent to "*". By default (if ** no 'y' is specified), "*" is assumed (that is also the default for ** invalid/unknown filter values). That 'y' filter is the one used for ** the event list. Note that a filter of "*" or "all" is equivalent to ** querying against the full event table. The view, however, adds an ** abstraction level to simplify the implementation code for the ** various /reports pages. ** ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of ** filter it applies, or '*' if no filter is applied (i.e. if "all" is ** used). */ static int stats_report_init_view(){ char const * zType = PD("type","*"); /* analog to /timeline?y=... */ char const * zRealType = NULL; /* normalized form of zType */ int rc = 0; /* result code */ assert( !statsReportType && "Must not be called more than once." ); switch( (zType && *zType) ? *zType : 0 ){ case 'c': case 'C': zRealType = "ci"; rc = *zRealType; break; case 'e': case 'E': zRealType = "e"; rc = *zRealType; break; case 'g': case 'G': zRealType = "g"; rc = *zRealType; break; case 't': case 'T': zRealType = "t"; rc = *zRealType; break; case 'w': case 'W': zRealType = "w"; rc = *zRealType; break; default: rc = '*'; break; } assert(0 != rc); if(zRealType){ statsReportTimelineYFlag = zRealType; db_multi_exec("CREATE TEMP VIEW v_reports AS " "SELECT * FROM event WHERE type GLOB %Q", zRealType); }else{ statsReportTimelineYFlag = "a"; db_multi_exec("CREATE TEMP VIEW v_reports AS " "SELECT * FROM event"); } return statsReportType = rc; } /* ** Returns a string suitable (for a given value of suitable) for ** use in a label with the header of the /reports pages, dependent ** on the 'type' flag. See stats_report_init_view(). ** The returned bytes are static. */ static char const * stats_report_label_for_type(){ assert( statsReportType && "Must call stats_report_init_view() first." ); switch( statsReportType ){ case 'c': return "checkins"; case 'w': return "wiki changes"; case 't': return "ticket changes"; case 'g': return "tag changes"; default: return "all types"; } } /* ** A helper for the /reports family of pages which prints out a menu ** of links for the various type=XXX flags. zCurrentViewName must be ** the name/value of the 'view' parameter which is in effect at ** the time this is called. e.g. if called from the 'byuser' view ** then zCurrentViewName must be "byuser". */ static void stats_report_event_types_menu(char const * zCurrentViewName){ char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName); cgi_printf("<div>"); cgi_printf("<span>Event types:</span> "); if('*' == statsReportType){ cgi_printf(" <strong>all</strong>", zTop); }else{ cgi_printf(" <a href='%s'>all</a>", zTop); } if('c' == statsReportType){ cgi_printf(" <strong>checkins</strong>", zTop); }else{ cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop); } if( 't' == statsReportType ){ cgi_printf(" <strong>tickets</strong>", zTop); }else{ cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop); } if( 'g' == statsReportType ){ cgi_printf(" <strong>tags</strong>", zTop); }else{ cgi_printf(" <a href='%s&type=g'>tags</a>", zTop); } if( 'w' == statsReportType ){ cgi_printf(" <strong>wiki</strong>", zTop); }else{ cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop); } fossil_free(zTop); cgi_printf("</div>"); } /* ** Helper for stats_report_by_month_year(), which generates a list of ** week numbers. zTimeframe should be either a timeframe in the form YYYY ** or YYYY-MM. */ static void stats_report_output_week_links(const char * zTimeframe){ Stmt stWeek = empty_Stmt; char yearPart[5] = {0,0,0,0,0}; memcpy(yearPart, zTimeframe, 4); db_prepare(&stWeek, "SELECT DISTINCT strftime('%%W',mtime) AS wk, " "count(*) AS n, " "substr(date(mtime),1,%d) AS ym " "FROM v_reports " "WHERE ym=%Q AND mtime < current_timestamp " "GROUP BY wk ORDER BY wk", strlen(zTimeframe), zTimeframe); while( SQLITE_ROW == db_step(&stWeek) ){ const char * zWeek = db_column_text(&stWeek,0); const int nCount = db_column_int(&stWeek,1); cgi_printf("<a href='%s/timeline?" "yw=%t-%t&n=%d&y=%s'>%s</a>", g.zTop, yearPart, zWeek, nCount, statsReportTimelineYFlag, zWeek); } db_finalize(&stWeek); } /* ** Implements the "byyear" and "bymonth" reports for /reports. ** If includeMonth is true then it generates the "bymonth" report, |
︙ | ︙ | |||
1906 1907 1908 1909 1910 1911 1912 | char showYearTotal = 0; /* Flag telling us when to show the per-year event totals */ Blob header = empty_blob; /* Page header text */ int nMaxEvents = 1; /* for calculating length of graph bars. */ int iterations = 0; /* number of weeks/months we iterate over */ | > > | > | | 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 | char showYearTotal = 0; /* Flag telling us when to show the per-year event totals */ Blob header = empty_blob; /* Page header text */ int nMaxEvents = 1; /* for calculating length of graph bars. */ int iterations = 0; /* number of weeks/months we iterate over */ stats_report_init_view(); stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" ); blob_appendf(&header, "Timeline Events (%s) by year%s", stats_report_label_for_type(), (includeMonth ? "/month" : "")); blob_appendf(&sql, "SELECT substr(date(mtime),1,%d) AS timeframe, " "count(*) AS eventCount " "FROM v_reports ", includeMonth ? 7 : 4); if(zUserName&&*zUserName){ blob_appendf(&sql, " WHERE user=%Q ", zUserName); blob_appendf(&header," for user %q", zUserName); } blob_append(&sql, " GROUP BY timeframe" |
︙ | ︙ | |||
1948 1949 1950 1951 1952 1953 1954 | } ++iterations; } db_reset(&query); while( SQLITE_ROW == db_step(&query) ){ const char * zTimeframe = db_column_text(&query, 0); const int nCount = db_column_int(&query, 1); | | > | 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 | } ++iterations; } db_reset(&query); while( SQLITE_ROW == db_step(&query) ){ const char * zTimeframe = db_column_text(&query, 0); const int nCount = db_column_int(&query, 1); int nSize = nCount ? (int)(100 * nCount / nMaxEvents) : 1; showYearTotal = 0; if(!nSize) nSize = 1; if(includeMonth){ /* For Month/year view, add a separator for each distinct year. */ if(!*zPrevYear || (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ showYearTotal = *zPrevYear; if(showYearTotal){ rowClass = ++nRowNumber % 2; |
︙ | ︙ | |||
1979 1980 1981 1982 1983 1984 1985 | rowClass = ++nRowNumber % 2; nEventTotal += nCount; nEventsPerYear += nCount; @<tr class='row%d(rowClass)'> @ <td> if(includeMonth){ cgi_printf("<a href='%s/timeline?" | | | > | > | 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 | rowClass = ++nRowNumber % 2; nEventTotal += nCount; nEventsPerYear += nCount; @<tr class='row%d(rowClass)'> @ <td> if(includeMonth){ cgi_printf("<a href='%s/timeline?" "ym=%t&n=%d&y=%s", g.zTop, zTimeframe, nCount, statsReportTimelineYFlag ); /* Reminder: n=nCount is not actually correct for bymonth unless that was the only user who caused events. */ if( zUserName && *zUserName ){ cgi_printf("&u=%t", zUserName); } cgi_printf("' target='_new'>%s</a>",zTimeframe); }else { cgi_printf("<a href='?view=byweek&y=%s&type=%c", zTimeframe, (char)statsReportType); if(zUserName && *zUserName){ cgi_printf("&u=%t", zUserName); } cgi_printf("'>%s</a>", zTimeframe); } @ </td><td>%d(nCount)</td> @ <td> |
︙ | ︙ | |||
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 | int nRowNumber = 0; /* current TR number */ int nEventTotal = 0; /* Total event count */ int rowClass = 0; /* counter for alternating row colors */ Blob sql = empty_blob; /* SQL */ int nMaxEvents = 1; /* max number of events for all rows. */ blob_append(&sql, "SELECT user, " "COUNT(*) AS eventCount " | > > | | > | > | | 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 | int nRowNumber = 0; /* current TR number */ int nEventTotal = 0; /* Total event count */ int rowClass = 0; /* counter for alternating row colors */ Blob sql = empty_blob; /* SQL */ int nMaxEvents = 1; /* max number of events for all rows. */ stats_report_init_view(); stats_report_event_types_menu("byuser"); blob_append(&sql, "SELECT user, " "COUNT(*) AS eventCount " "FROM v_reports " "GROUP BY user ORDER BY eventCount DESC", -1); db_prepare(&query, blob_str(&sql)); blob_reset(&sql); @ <h1>Timeline Events @ (%s(stats_report_label_for_type())) by User</h1> @ <table class='statistics-report-table-events' border='0' @ cellpadding='2' cellspacing='0' id='statsTable'> @ <thead><tr> @ <th>User</th> @ <th>Events</th> @ <th width='90%%'><!-- relative commits graph --></th> @ </tr></thead><tbody> while( SQLITE_ROW == db_step(&query) ){ const int nCount = db_column_int(&query, 1); if(nCount>nMaxEvents){ nMaxEvents = nCount; } } db_reset(&query); while( SQLITE_ROW == db_step(&query) ){ const char * zUser = db_column_text(&query, 0); const int nCount = db_column_int(&query, 1); int nSize = nCount ? (int)(100 * nCount / nMaxEvents) : 0; if(!nCount) continue /* arguable! Possible? */; else if(!nSize) nSize = 1; rowClass = ++nRowNumber % 2; nEventTotal += nCount; @<tr class='row%d(rowClass)'> @ <td> @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> @ </td><td>%d(nCount)</td> @ <td> @ <div class='statistics-report-graph-line' @ style='height:16px;width:%d(nSize)%%;'> @ </div></td> @</tr> /* |
︙ | ︙ | |||
2118 2119 2120 2121 2122 2123 2124 | int i = 0; Stmt qYears = empty_Stmt; char * zDefaultYear = NULL; Blob sql = empty_blob; int nMaxEvents = 1; /* max number of events for all rows. */ int iterations = 0; /* # of active time periods. */ | | > | | > | > | | | 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | int i = 0; Stmt qYears = empty_Stmt; char * zDefaultYear = NULL; Blob sql = empty_blob; int nMaxEvents = 1; /* max number of events for all rows. */ int iterations = 0; /* # of active time periods. */ stats_report_init_view(); stats_report_event_types_menu("byweek"); cgi_printf("Select year: "); blob_append(&sql, "SELECT DISTINCT substr(date(mtime),1,4) AS y " "FROM v_reports WHERE 1 ", -1); if(zUserName&&*zUserName){ blob_appendf(&sql,"AND user=%Q ", zUserName); } blob_append(&sql,"GROUP BY y ORDER BY y", -1); db_prepare(&qYears, blob_str(&sql)); blob_reset(&sql); while( SQLITE_ROW == db_step(&qYears) ){ const char * zT = db_column_text(&qYears, 0); if( i++ ){ cgi_printf(" "); } cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT, (char)statsReportType); if(zUserName && *zUserName){ cgi_printf("&user=%t",zUserName); } cgi_printf("'>%s</a>",zT); } db_finalize(&qYears); cgi_printf("<br/>"); if(!zYear || !*zYear){ zDefaultYear = db_text("????", "SELECT strftime('%%Y')"); zYear = zDefaultYear; nYear = 4; } if(4 == nYear){ Stmt stWeek = empty_Stmt; int rowCount = 0; int total = 0; Blob header = empty_blob; blob_appendf(&header, "Timeline events (%s) for the calendar weeks " "of %h", stats_report_label_for_type(), zYear); blob_appendf(&sql, "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, " "count(*) AS n " "FROM v_reports " "WHERE %Q=substr(date(mtime),1,4) " "AND mtime < current_timestamp ", zYear); if(zUserName&&*zUserName){ blob_appendf(&sql, " AND user=%Q ", zUserName); blob_appendf(&header," for user %h", zUserName); } |
︙ | ︙ | |||
2190 2191 2192 2193 2194 2195 2196 | } ++iterations; } db_reset(&stWeek); while( SQLITE_ROW == db_step(&stWeek) ){ const char * zWeek = db_column_text(&stWeek,0); const int nCount = db_column_int(&stWeek,1); | | > | | > | 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 | } ++iterations; } db_reset(&stWeek); while( SQLITE_ROW == db_step(&stWeek) ){ const char * zWeek = db_column_text(&stWeek,0); const int nCount = db_column_int(&stWeek,1); int nSize = nCount ? (int)(100 * nCount / nMaxEvents) : 0; if(!nSize) nSize = 1; total += nCount; cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d&y=%s", g.zTop, zYear, zWeek, nCount, statsReportTimelineYFlag); if(zUserName && *zUserName){ cgi_printf("&u=%t",zUserName); } cgi_printf("'>%s</a></td>",zWeek); cgi_printf("<td>%d</td>",nCount); cgi_printf("<td>"); |
︙ | ︙ | |||
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 | ** ** Shows activity reports for the repository. ** ** Query Parameters: ** ** view=REPORT_NAME Valid values: bymonth, byyear, byuser ** user=NAME Restricts statistics to the given user */ void stats_report_page(){ HQuery url; /* URL for various branch links */ const char * zView = P("view"); /* Which view/report to show. */ const char *zUserName = P("user"); if(!zUserName) zUserName = P("u"); url_initialize(&url, "reports"); | > > > > > > > > > > | 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 | ** ** Shows activity reports for the repository. ** ** Query Parameters: ** ** view=REPORT_NAME Valid values: bymonth, byyear, byuser ** user=NAME Restricts statistics to the given user ** type=TYPE Restricts the report to a specific event type: ** ci (checkin), w (wiki), t (ticket), g (tag) ** Defaulting to all event types. ** ** The view-specific query parameters include: ** ** view=byweek: ** ** y=YYYY The year to report (default is the server's ** current year). */ void stats_report_page(){ HQuery url; /* URL for various branch links */ const char * zView = P("view"); /* Which view/report to show. */ const char *zUserName = P("user"); if(!zUserName) zUserName = P("u"); url_initialize(&url, "reports"); |
︙ | ︙ |
Changes to src/tkt.c.
︙ | ︙ | |||
294 295 296 297 298 299 300 | db_multi_exec("DELETE FROM ticketchng WHERE tkt_id=%d;", tktid); } db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid); tktid = 0; db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); | | | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | db_multi_exec("DELETE FROM ticketchng WHERE tkt_id=%d;", tktid); } db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid); tktid = 0; db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ tktid = ticket_insert(pTicket, rid, tktid); manifest_ticket_event(rid, pTicket, createFlag, tagid); manifest_destroy(pTicket); } createFlag = 0; } |
︙ | ︙ | |||
619 620 621 622 623 624 625 | if( g.zPath[0]=='d' ){ /* If called from /debug_tktnew or /debug_tktedit... */ @ <font color="blue"> @ <p>Ticket artifact that would have been submitted:</p> @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote> @ <hr /></font> return TH_OK; | > | | | | < > | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | if( g.zPath[0]=='d' ){ /* If called from /debug_tktnew or /debug_tktedit... */ @ <font color="blue"> @ <p>Ticket artifact that would have been submitted:</p> @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote> @ <hr /></font> return TH_OK; }else{ if( g.thTrace ){ Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n" "}<br />\n", blob_str(&tktchng)); } ticket_put(&tktchng, zUuid, (g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1)); } return ticket_change(); } |
︙ | ︙ | |||
941 942 943 944 945 946 947 | @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>" } @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] @ (rid %d(rid)) by hyperlink_to_user(zUser,zDate," on"); hyperlink_to_date(zDate, ".</p>"); }else{ | | | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 | @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>" } @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] @ (rid %d(rid)) by hyperlink_to_user(zUser,zDate," on"); hyperlink_to_date(zDate, ".</p>"); }else{ pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ @ @ <li><p>Ticket change @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] @ (rid %d(rid)) by hyperlink_to_user(pTicket->zUser,zDate," on"); hyperlink_to_date(zDate, ":"); |
︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 | if( zSrc==0 || zSrc[0]==0 ){ fossil_print("Delete attachment %s\n", zFile); }else{ fossil_print("Add attachment %s\n", zFile); } fossil_print(" by %s on %s\n", zUser, zDate); }else{ | | | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 | if( zSrc==0 || zSrc[0]==0 ){ fossil_print("Delete attachment %s\n", zFile); }else{ fossil_print("Add attachment %s\n", zFile); } fossil_print(" by %s on %s\n", zUser, zDate); }else{ pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ int i; fossil_print("Ticket Change by %s on %s:\n", pTicket->zUser, zDate); for(i=0; i<pTicket->nField; i++){ Blob val; |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
123 124 125 126 127 128 129 | } verboseFlag = find_option("verbose","v",0)!=0; debugFlag = find_option("debug",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; capture_case_sensitive_option(); db_must_be_within_tree(); vid = db_lget_int("checkout", 0); | < < < | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | } verboseFlag = find_option("verbose","v",0)!=0; debugFlag = find_option("debug",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; capture_case_sensitive_option(); db_must_be_within_tree(); vid = db_lget_int("checkout", 0); user_select(); if( !dryRunFlag && !internalUpdate ){ autosync(SYNC_PULL + SYNC_VERBOSE*verboseFlag); } /* Create any empty directories now, as well as after the update, ** so changes in settings are reflected now */ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | compute_leaves(vid, closeCode); db_prepare(&q, "%s " " AND event.objid IN leaves" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); | | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | compute_leaves(vid, closeCode); db_prepare(&q, "%s " " AND event.objid IN leaves" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); print_timeline(&q, -100, 79, 0); db_finalize(&q); fossil_fatal("Multiple descendants"); } } tid = db_int(0, "SELECT rid FROM leaves, event" " WHERE event.objid=leaves.rid" " ORDER BY event.mtime DESC"); if( tid==0 ) tid = vid; } if( tid==0 ){ return; } db_begin_transaction(); vfile_check_signature(vid, CKSIG_ENOTFILE); if( !dryRunFlag && !internalUpdate ) undo_begin(); load_vfile_from_rid(tid); |
︙ | ︙ | |||
633 634 635 636 637 638 639 | }else{ rid = db_lget_int("checkout", 0); } if( !is_a_version(rid) ){ if( errCode>0 ) return errCode; fossil_fatal("no such checkin: %s", revision); } | | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | }else{ rid = db_lget_int("checkout", 0); } if( !is_a_version(rid) ){ if( errCode>0 ) return errCode; fossil_fatal("no such checkin: %s", revision); } pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ pFile = manifest_file_find(pManifest, file); if( pFile ){ int rc; rid = uuid_to_rid(pFile->zUuid, 0); if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE ); |
︙ | ︙ |
Changes to src/url.c.
︙ | ︙ | |||
98 99 100 101 102 103 104 | g.urlDfltPort = 443; iStart = 8; }else if( zUrl[0]=='s' ){ g.urlIsSsh = 1; g.urlProtocol = "ssh"; g.urlDfltPort = 22; g.urlFossil = "fossil"; | < | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | g.urlDfltPort = 443; iStart = 8; }else if( zUrl[0]=='s' ){ g.urlIsSsh = 1; g.urlProtocol = "ssh"; g.urlDfltPort = 22; g.urlFossil = "fossil"; iStart = 6; }else{ g.urlIsHttps = 0; g.urlProtocol = "http"; g.urlDfltPort = 80; iStart = 7; } |
︙ | ︙ | |||
171 172 173 174 175 176 177 | } if( fossil_strcmp(zName,"fossil")==0 ){ g.urlFossil = zValue; dehttpize(g.urlFossil); zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil); cQuerySep = '&'; } | < < < < < < | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | } if( fossil_strcmp(zName,"fossil")==0 ){ g.urlFossil = zValue; dehttpize(g.urlFossil); zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil); cQuerySep = '&'; } } dehttpize(g.urlPath); if( g.urlDfltPort==g.urlPort ){ g.urlCanonical = mprintf( "%s://%s%T%T%s", g.urlProtocol, zLogin, g.urlName, g.urlPath, zExe |
︙ | ︙ | |||
442 443 444 445 446 447 448 | */ void url_prompt_for_password(void){ if( g.urlIsSsh || g.urlIsFile ) return; if( isatty(fileno(stdin)) && (g.urlFlags & URL_PROMPT_PW)!=0 && (g.urlFlags & URL_PROMPTED)==0 ){ | < < < < < < < > < | < < < | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | */ void url_prompt_for_password(void){ if( g.urlIsSsh || g.urlIsFile ) return; if( isatty(fileno(stdin)) && (g.urlFlags & URL_PROMPT_PW)!=0 && (g.urlFlags & URL_PROMPTED)==0 ){ g.urlFlags |= URL_PROMPTED; g.urlPasswd = prompt_for_user_password(g.urlUser); if( g.urlPasswd[0] && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0 ){ if( save_password_prompt() ){ g.urlFlags |= URL_REMEMBER_PW; if( g.urlFlags & URL_REMEMBER ){ db_set("last-sync-pw", obscure(g.urlPasswd), 0); } } } }else{ |
︙ | ︙ | |||
488 489 490 491 492 493 494 | /* Preemptively prompt for a password if a username is given in the ** URL but no password. */ void url_get_password_if_needed(void){ if( (g.urlUser && g.urlUser[0]) && (g.urlPasswd==0 || g.urlPasswd[0]==0) && isatty(fileno(stdin)) | < | 471 472 473 474 475 476 477 478 479 480 481 | /* Preemptively prompt for a password if a username is given in the ** URL but no password. */ void url_get_password_if_needed(void){ if( (g.urlUser && g.urlUser[0]) && (g.urlPasswd==0 || g.urlPasswd[0]==0) && isatty(fileno(stdin)) ){ url_prompt_for_password(); } } |
Changes to src/user.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | while( fossil_isspace(*z) ){ z++; } for(i=0; z[i]; i++){ if( z[i]=='\r' || z[i]=='\n' ){ while( i>0 && fossil_isspace(z[i-1]) ){ i--; } z[i] = 0; break; } | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | while( fossil_isspace(*z) ){ z++; } for(i=0; z[i]; i++){ if( z[i]=='\r' || z[i]=='\n' ){ while( i>0 && fossil_isspace(z[i-1]) ){ i--; } z[i] = 0; break; } if( z[i]>0 && z[i]<' ' ) z[i] = ' '; } blob_append(pBlob, z, -1); } #if defined(_WIN32) || defined(__BIONIC__) #ifdef __MINGW32__ #include <conio.h> |
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 | fossil_print("Passphrases do not match. Try again...\n"); }else{ break; } } blob_reset(&secondTry); } /* ** Prompt the user to enter a single line of text. */ void prompt_user(const char *zPrompt, Blob *pIn){ char *z; char zLine[1000]; | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | fossil_print("Passphrases do not match. Try again...\n"); }else{ break; } } blob_reset(&secondTry); } /* ** Prompt to save Fossil user password */ int save_password_prompt(){ Blob x; char c; prompt_user("remember password (Y/n)? ", &x); c = blob_str(&x)[0]; blob_reset(&x); return ( c!='n' && c!='N' ); } /* ** Prompt for Fossil user password */ char *prompt_for_user_password(const char *zUser){ char *zPrompt = mprintf("\rpassword for %s: ", zUser); char *zPw; Blob x; fossil_force_newline(); prompt_for_password(zPrompt, &x, 0); free(zPrompt); zPw = mprintf("%b", &x); blob_reset(&x); return zPw; } /* ** Prompt the user to enter a single line of text. */ void prompt_user(const char *zPrompt, Blob *pIn){ char *z; char zLine[1000]; |
︙ | ︙ |
Changes to src/utf8.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | */ #include "config.h" #include "utf8.h" #include <sqlite3.h> #ifdef _WIN32 # include <windows.h> #endif | < | < < < < < < | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | */ #include "config.h" #include "utf8.h" #include <sqlite3.h> #ifdef _WIN32 # include <windows.h> #endif #include "cygsup.h" #ifdef _WIN32 /* ** Translate MBCS to UTF-8. Return a pointer to the translated text. ** Call fossil_mbcs_free() to deallocate any memory used to store the ** returned pointer when done. */ |
︙ | ︙ |
Changes to src/vfile.c.
︙ | ︙ | |||
79 80 81 82 83 84 85 | ManifestFile *pFile; if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){ return; } db_begin_transaction(); | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | ManifestFile *pFile; if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){ return; } db_begin_transaction(); p = manifest_get(vid, CFTYPE_MANIFEST, 0); if( p==0 ) { db_end_transaction(1); return; } db_prepare(&ins, "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) " " VALUES(:vid,:isexe,:islink,:id,:id,:name)"); |
︙ | ︙ | |||
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | ** ** In a well-formed manifest, the two checksums computed here, pOut and ** pManOut, should be identical. */ void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){ int fid; Blob file; Manifest *pManifest; ManifestFile *pFile; char zBuf[100]; blob_zero(pOut); if( pManOut ){ blob_zero(pManOut); } db_must_be_within_tree(); | > > | | > | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | ** ** In a well-formed manifest, the two checksums computed here, pOut and ** pManOut, should be identical. */ void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){ int fid; Blob file; Blob err; Manifest *pManifest; ManifestFile *pFile; char zBuf[100]; blob_zero(pOut); blob_zero(&err); if( pManOut ){ blob_zero(pManOut); } db_must_be_within_tree(); pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); if( pManifest==0 ){ fossil_fatal("manifest file (%d) is malformed:\n%s\n", vid, blob_str(&err)); } manifest_file_rewind(pManifest); while( (pFile = manifest_file_next(pManifest,0))!=0 ){ if( pFile->zUuid==0 ) continue; fid = uuid_to_rid(pFile->zUuid, 0); md5sum_step_text(pFile->zName, -1); content_get(fid, &file); |
︙ | ︙ |
Changes to src/wiki.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to do formatting of wiki text. */ #include <assert.h> #include <ctype.h> | > < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to do formatting of wiki text. */ #include "config.h" #include <assert.h> #include <ctype.h> #include "wiki.h" /* ** Return true if the input string is a well-formed wiki page name. ** ** Well-formed wiki page names do not begin or end with whitespace, ** and do not contain tabs or other control characters and do not |
︙ | ︙ | |||
226 227 228 229 230 231 232 | zTag = mprintf("wiki-%s", zPageName); rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | zTag = mprintf("wiki-%s", zPageName); rid = db_int(0, "SELECT rid FROM tagxref" " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" " ORDER BY mtime DESC", zTag ); free(zTag); pWiki = manifest_get(rid, CFTYPE_WIKI, 0); if( pWiki ){ zBody = pWiki->zWiki; zMimetype = pWiki->zMimetype; } } zMimetype = wiki_filter_mimetypes(zMimetype); if( !g.isHome ){ |
︙ | ︙ | |||
389 390 391 392 393 394 395 | " ORDER BY mtime DESC", zTag ); free(zTag); if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){ login_needed(); return; } | | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | " ORDER BY mtime DESC", zTag ); free(zTag); if( (rid && !g.perm.WrWiki) || (!rid && !g.perm.NewWiki) ){ login_needed(); return; } if( zBody==0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){ zBody = pWiki->zWiki; zMimetype = pWiki->zMimetype; } } if( P("submit")!=0 && zBody!=0 && (goodCaptcha = captcha_is_correct()) ){ |
︙ | ︙ | |||
630 631 632 633 634 635 636 | blob_zero(&body); if( isSandbox ){ blob_appendf(&body, db_get("sandbox","")); appendRemark(&body, zMimetype); db_set("sandbox", blob_str(&body), 0); }else{ login_verify_csrf_secret(); | | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | blob_zero(&body); if( isSandbox ){ blob_appendf(&body, db_get("sandbox","")); appendRemark(&body, zMimetype); db_set("sandbox", blob_str(&body), 0); }else{ login_verify_csrf_secret(); pWiki = manifest_get(rid, CFTYPE_WIKI, 0); if( pWiki ){ blob_append(&body, pWiki->zWiki, -1); manifest_destroy(pWiki); } blob_zero(&wiki); db_begin_transaction(); zDate = date_in_standard_format("now"); |
︙ | ︙ | |||
780 781 782 783 784 785 786 | "SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid=" "(SELECT tagid FROM tag WHERE tagname='wiki-%q')" " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)" " ORDER BY event.mtime DESC LIMIT 1", zPageName, rid1 ); } | | | | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | "SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid=" "(SELECT tagid FROM tag WHERE tagname='wiki-%q')" " WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)" " ORDER BY event.mtime DESC LIMIT 1", zPageName, rid1 ); } pW1 = manifest_get(rid1, CFTYPE_WIKI, 0); if( pW1==0 ) fossil_redirect_home(); blob_init(&w1, pW1->zWiki, -1); blob_zero(&w2); if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI, 0))!=0 ){ blob_init(&w2, pW2->zWiki, -1); } blob_zero(&d); diffFlags = construct_diff_flags(1,0); text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); @ <pre class="udiff"> @ %s(blob_str(&d)) |
︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 | } zPageName = g.argv[3]; rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" " ORDER BY x.mtime DESC LIMIT 1", zPageName ); | | | 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 | } zPageName = g.argv[3]; rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" " ORDER BY x.mtime DESC LIMIT 1", zPageName ); if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){ zBody = pWiki->zWiki; } if( zBody==0 ){ fossil_fatal("wiki page [%s] not found",zPageName); } for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){} zBody[i] = 0; |
︙ | ︙ |
Changes to src/wikiformat.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to do formatting of wiki text. */ | < > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to do formatting of wiki text. */ #include "config.h" #include <assert.h> #include "wikiformat.h" #if INTERFACE /* ** Allowed wiki transformation operations */ #define WIKI_HTMLONLY 0x001 /* HTML markup only. No wiki */ |
︙ | ︙ |
Changes to src/wysiwyg.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code that generates WYSIWYG text editors on ** web pages. */ #include <assert.h> #include <ctype.h> | > < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code that generates WYSIWYG text editors on ** web pages. */ #include "config.h" #include <assert.h> #include <ctype.h> #include "wysiwyg.h" /* ** Output code for a WYSIWYG editor. The caller must have already generated ** the <form> that will contain the editor, and the call must generate the ** corresponding </form> after this routine returns. The caller must include |
︙ | ︙ |
Changes to src/xfer.c.
︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 | /* Unknown message */ { cgi_reset_content(); @ error bad\scommand:\s%F(blob_str(&xfer.line)) } blobarray_reset(xfer.aToken, xfer.nToken); } if( isPush ){ if( run_push_script()==TH_ERROR ){ cgi_reset_content(); @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0)) nErr++; } | > | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 | /* Unknown message */ { cgi_reset_content(); @ error bad\scommand:\s%F(blob_str(&xfer.line)) } blobarray_reset(xfer.aToken, xfer.nToken); blob_reset(&xfer.line); } if( isPush ){ if( run_push_script()==TH_ERROR ){ cgi_reset_content(); @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0)) nErr++; } |
︙ | ︙ | |||
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 | create_cluster(); send_unclustered(&xfer); if( xfer.syncPrivate ) send_private(&xfer); } if( recvConfig ){ configure_finalize_receive(); } manifest_crosslink_end(); /* Send the server timestamp last, in case prior processing happened ** to use up a significant fraction of our time window. */ zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); @ # timestamp %s(zNow) | > | 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 | create_cluster(); send_unclustered(&xfer); if( xfer.syncPrivate ) send_private(&xfer); } if( recvConfig ){ configure_finalize_receive(); } db_multi_exec("DROP TABLE onremote"); manifest_crosslink_end(); /* Send the server timestamp last, in case prior processing happened ** to use up a significant fraction of our time window. */ zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); @ # timestamp %s(zNow) |
︙ | ︙ | |||
1423 1424 1425 1426 1427 1428 1429 | if( syncFlags & SYNC_PUSH ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push"; if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff; } manifest_crosslink_begin(); | < | 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 | if( syncFlags & SYNC_PUSH ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push"; if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff; } manifest_crosslink_begin(); if( syncFlags & SYNC_VERBOSE ){ fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas"); } while( go ){ int newPhantom = 0; char *zRandomness; |
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 | ** messages unique so that that the login-card nonce will always ** be unique. */ zRandomness = db_text(0, "SELECT hex(randomblob(20))"); blob_appendf(&send, "# %s\n", zRandomness); free(zRandomness); /* Exchange messages with the server */ if( syncFlags & SYNC_VERBOSE ){ fossil_print(zValueFormat, "Sent:", blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); }else{ nRoundtrip++; nArtifactSent += xfer.nFileSent + xfer.nDeltaSent; fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); } nCardSent = 0; nCardRcvd = 0; xfer.nFileSent = 0; xfer.nDeltaSent = 0; xfer.nGimmeSent = 0; xfer.nIGotSent = 0; | > > > > > > > > > > > < < | < < < < < < | 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | ** messages unique so that that the login-card nonce will always ** be unique. */ zRandomness = db_text(0, "SELECT hex(randomblob(20))"); blob_appendf(&send, "# %s\n", zRandomness); free(zRandomness); if( syncFlags & SYNC_VERBOSE ){ fossil_print("waiting for server..."); } fflush(stdout); /* Exchange messages with the server */ if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0, MAX_REDIRECTS) ){ nErr++; break; } /* Output current stats */ if( syncFlags & SYNC_VERBOSE ){ fossil_print(zValueFormat, "Sent:", blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); }else{ nRoundtrip++; nArtifactSent += xfer.nFileSent + xfer.nDeltaSent; fossil_print(zBriefFormat, nRoundtrip, nArtifactSent, nArtifactRcvd); } nCardSent = 0; nCardRcvd = 0; xfer.nFileSent = 0; xfer.nDeltaSent = 0; xfer.nGimmeSent = 0; xfer.nIGotSent = 0; lastPctDone = -1; blob_reset(&send); rArrivalTime = db_double(0.0, "SELECT julianday('now')"); /* Send the send-private pragma if we are trying to sync private data */ if( syncFlags & SYNC_PRIVATE ){ blob_append(&send, "pragma send-private\n", -1); |
︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | defossilize(zMsg); fossil_force_newline(); fossil_print("Error: %s\n", zMsg); if( fossil_strcmp(zMsg, "login failed")==0 ){ if( nCycle<2 ){ g.urlPasswd = 0; go = 1; | | > > > | 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 | defossilize(zMsg); fossil_force_newline(); fossil_print("Error: %s\n", zMsg); if( fossil_strcmp(zMsg, "login failed")==0 ){ if( nCycle<2 ){ g.urlPasswd = 0; go = 1; if( g.cgiOutput==0 ){ g.urlFlags |= URL_PROMPT_PW; url_prompt_for_password(); } } }else{ blob_appendf(&xfer.err, "server says: %s\n", zMsg); nErr++; } break; } |
︙ | ︙ |
Changes to src/zip.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to generate ZIP archives. */ #include <assert.h> #include <zlib.h> | > < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to generate ZIP archives. */ #include "config.h" #include <assert.h> #include <zlib.h> #include "zip.h" /* ** Write a 16- or 32-bit integer as little-endian into the given buffer. */ static void put16(char *z, int v){ z[0] = v & 0xff; |
︙ | ︙ | |||
335 336 337 338 339 340 341 | zip_open(); if( zDir && zDir[0] ){ blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); | | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | zip_open(); if( zDir && zDir[0] ){ blob_appendf(&filename, "%s/", zDir); } nPrefix = blob_size(&filename); pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ char *zName; zip_set_timedate(pManifest->rDate); if( db_get_boolean("manifest", 0) ){ blob_append(&filename, "manifest", -1); zName = blob_str(&filename); zip_add_folders(zName); |
︙ | ︙ |
Changes to win/Makefile.mingw.
︙ | ︙ | |||
161 162 163 164 165 166 167 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY | | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -DFOSSIL_ENABLE_SSL=1 RCC += -DFOSSIL_ENABLE_SSL=1 endif |
︙ | ︙ | |||
1683 1684 1685 1686 1687 1688 1689 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c | | | 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_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 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
︙ | ︙ |
Changes to win/Makefile.mingw.mistachkin.
︙ | ︙ | |||
161 162 163 164 165 166 167 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY | | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -DFOSSIL_ENABLE_SSL=1 RCC += -DFOSSIL_ENABLE_SSL=1 endif |
︙ | ︙ | |||
1683 1684 1685 1686 1687 1688 1689 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c | | | 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 | $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_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 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
︙ | ︙ |
Changes to win/Makefile.msc.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # B = .. SRCDIR = $B\src OBJDIR = . OX = . O = .obj E = .exe # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable SSL support # FOSSIL_ENABLE_SSL = 1 !ifdef FOSSIL_ENABLE_SSL SSLINCDIR = $(B)\compat\openssl-1.0.1e\include SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !endif # zlib options | > > > | | | | | | > > > > > > > | | | | | | | | | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # B = .. SRCDIR = $B\src OBJDIR = . OX = . O = .obj E = .exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable SSL support # FOSSIL_ENABLE_SSL = 1 !ifdef FOSSIL_ENABLE_SSL SSLINCDIR = $(B)\compat\openssl-1.0.1e\include SSLLIBDIR = $(B)\compat\openssl-1.0.1e\out32 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !endif # zlib options ZINCDIR = $(B)\compat\zlib ZLIBDIR = $(B)\compat\zlib ZLIB = zlib.lib INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(ZINCDIR) !ifdef FOSSIL_ENABLE_SSL INCL = $(INCL) -I$(SSLINCDIR) !endif CFLAGS = -nologo -MT -O2 LDFLAGS = /NODEFAULTLIB:msvcrt !ifdef DEBUG CFLAGS = $(CFLAGS) -Zi LDFLAGS = $(LDFLAGS) /DEBUG !endif BCC = $(CC) $(CFLAGS) TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(INCL) RCC = rc -D_WIN32 -D_MSC_VER $(MSCDEF) $(INCL) LIBS = $(ZLIB) ws2_32.lib advapi32.lib LIBDIR = -LIBPATH:$(ZLIBDIR) !ifdef FOSSIL_ENABLE_JSON TCC = $(TCC) -DFOSSIL_ENABLE_JSON=1 RCC = $(RCC) -DFOSSIL_ENABLE_JSON=1 !endif !ifdef FOSSIL_ENABLE_SSL TCC = $(TCC) -DFOSSIL_ENABLE_SSL=1 RCC = $(RCC) -DFOSSIL_ENABLE_SSL=1 LIBS = $(LIBS) $(SSLLIB) LIBDIR = $(LIBDIR) -LIBPATH:$(SSLLIBDIR) !endif SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 \ /DSQLITE_THREADSAFE=0 \ /DSQLITE_DEFAULT_FILE_FORMAT=4 \ /DSQLITE_ENABLE_STAT3 \ /Dlocaltime=fossil_localtime \ |
︙ | ︙ | |||
292 293 294 295 296 297 298 | zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib cd $(OX) | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib cd $(OX) link $(LDFLAGS) -OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts $(OX)\linkopts: $B\win\Makefile.msc echo $(OX)\add.obj > $@ echo $(OX)\allrepo.obj >> $@ echo $(OX)\attach.obj >> $@ echo $(OX)\bag.obj >> $@ echo $(OX)\bisect.obj >> $@ |
︙ | ︙ |
Changes to www/adding_code.wiki.
︙ | ︙ | |||
8 9 10 11 12 13 14 | <h2>2.0 Programming Language</h2> Fossil is written in C-89. There are specific [./style.wiki | style guidelines] that are required for any new code that will be accepted into the Fossil core. But, of course, if you are writing an extension just for yourself, you can use any programming style you want. | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <h2>2.0 Programming Language</h2> Fossil is written in C-89. There are specific [./style.wiki | style guidelines] that are required for any new code that will be accepted into the Fossil core. But, of course, if you are writing an extension just for yourself, you can use any programming style you want. The source code for Fossil is not sent directly into the C compiler. There are three separate code [./makefile.wiki#preprocessing|preprocessors] that run over the code first. 1. The <b>mkindex</b> preprocessor scans all regular source files looking for special comments that contain "help" text and which identify routines that implement specific commands or which generate particular web pages. |
︙ | ︙ |
Changes to www/build.wiki.
︙ | ︙ | |||
134 135 136 137 138 139 140 | <li><p> To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile generated by configure to add the following lines: <blockquote><pre> TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int | > | | 134 135 136 137 138 139 140 141 142 143 | <li><p> To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile generated by configure to add the following lines: <blockquote><pre> TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int TCC += -DSQLITE_MAX_MMAP_SIZE=0 </pre></blockquote> </ul> |
Changes to www/changes.wiki.
1 2 3 4 5 6 7 8 | <title>Change Log</title> <h2>Changes For Version 1.27 (2013-09-11)</h2> * Enhance the [/help?cmd=changes | fossil changes], [/help?cmd=clean | fossil clean], [/help?cmd=extras | fossil extras], [/help?cmd=ls | fossil ls] and [/help?cmd=status | fossil status] commands to restrict operation to files and directories named on the command-line. * New --integrate option to [/help?cmd=merge | fossil merge], which | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <title>Change Log</title> <h2>Changes For Version 1.28 (as yet unreleased)</h2> * Enhance [/help?cmd=/reports | /reports] to support event type filtering. * When cloning a repository, the user name passed via the URL (if any) is now used as the default local admin user's name. * Enhance the SSH transport mechanism so that it runs a single instance of the "fossil" executable on the remote side, obviating the need for a shell on the remote side. Some users may need to add the "?fossil=/path/to/fossil" query parameter to "ssh:" URIs if their fossil binary is not in a standard place. * Add the "[/help?cmd=blame | fossil blame]" command that works just like "fossil annotate" but uses a different output format that includes the user who made each changes and omits line numbers. * Add the "Tarball and ZIP-archive Prefix" configuration parameter under Admin/Configuration. * Fix CGI processing so that it works on web servers that do not supply REQUEST_URI. * Add options --dirsonly, --emptydirs, and --allckouts to the "[/help?cmd=clean | fossil clean]" command. * Ten-fold performance improvement in large "fossil blame" or "fossil annotate" commands. * Add option -W|--width to the "[/help?cmd=timeline | fossil timeline]" and "[/help?cmd=finfo | fossil finfo]" commands. * Option -n|--limit of "[/help?cmd=timeline | fossil timeline]" now specifies the number of entries, just like all other commands which have the -n|--limit option. The various timeline-related functions now output "=== ?? limit (??) reached ===" at the end whenever appropriate. Use "-n 0" if no limit is desired. <h2>Changes For Version 1.27 (2013-09-11)</h2> * Enhance the [/help?cmd=changes | fossil changes], [/help?cmd=clean | fossil clean], [/help?cmd=extras | fossil extras], [/help?cmd=ls | fossil ls] and [/help?cmd=status | fossil status] commands to restrict operation to files and directories named on the command-line. * New --integrate option to [/help?cmd=merge | fossil merge], which |
︙ | ︙ |
Changes to www/concepts.wiki.
︙ | ︙ | |||
77 78 79 80 81 82 83 | at a repository and get human-readable status, history, and tracking information about the project. <h3>2.1 Identification Of Artifacts</h3> A particular version of a particular file is called an "artifact". Each artifact has a universally unique name which is the | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | at a repository and get human-readable status, history, and tracking information about the project. <h3>2.1 Identification Of Artifacts</h3> A particular version of a particular file is called an "artifact". Each artifact has a universally unique name which is the <a href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> hash of the content of that file expressed as 40 characters of lower-case hexadecimal. Such a hash is referred to as the Artifact Identifier or Artifact ID for the artifact. The SHA1 algorithm is created with the purpose of providing a highly forgery-resistant identifier for a file. Given any file it is simple to find the artifact ID for that file. But given a artifact ID it is computationally intractable to generate a file that will have that Artifact ID. |
︙ | ︙ |
Changes to www/quickstart.wiki.
︙ | ︙ | |||
53 54 55 56 57 58 59 | <blockquote> <b>fossil clone</b> <i>URL repository-filename</i> </blockquote> <p>The <i>URL</i> above is the http URL for the fossil repository you want to clone, and it may include a "user:password" part, e.g. | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <blockquote> <b>fossil clone</b> <i>URL repository-filename</i> </blockquote> <p>The <i>URL</i> above is the http URL for the fossil repository you want to clone, and it may include a "user:password" part, e.g. <tt>http://user:password@www.fossil-scm.org/fossil</tt>. You can call the new repository anything you want - there are no naming restrictions. As an example, you can clone the fossil repository this way:</p> <blockquote> <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> </blockquote> |
︙ | ︙ | |||
218 219 220 221 222 223 224 | abbreviation to the 40-character artifact identifier for a particular check-in, or it can be a date/time stamp. ([./checkin_names.wiki | more info]) If you omit the <i>VERSION</i>, then fossil moves you to the latest version of the branch your are currently on.</p> | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | abbreviation to the 40-character artifact identifier for a particular check-in, or it can be a date/time stamp. ([./checkin_names.wiki | more info]) If you omit the <i>VERSION</i>, then fossil moves you to the latest version of the branch your are currently on.</p> <p>The default behavior is for [./concepts.wiki#workflow|autosync] to be turned on. That means that a [/help/pull|pull] automatically occurs when you run [/help/update|update] and a [/help/push|push] happens automatically after you [/help/commit|commit]. So in normal practice, the push, pull, and sync commands are rarely used. But it is important to know about them, all the same.</p> <h2>Branching And Merging</h2> |
︙ | ︙ |
Changes to www/selfhost.wiki.
︙ | ︙ | |||
36 37 38 39 40 41 42 | </pre></blockquote> Server (3) runs as a CGI script on a shared hosting account at <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. This server demonstrates the ability of Fossil to run on an economical shared-host web account with no privileges beyond port 80 HTTP access and CGI. It is not necessary | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | </pre></blockquote> Server (3) runs as a CGI script on a shared hosting account at <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. This server demonstrates the ability of Fossil to run on an economical shared-host web account with no privileges beyond port 80 HTTP access and CGI. It is not necessary to have a dedicated computer with administrator privileges to run Fossil. As far as we are aware, Fossil is the only full-featured configuration management system that can run in such a restricted environment. The CGI script that runs on the Hurricane Electric server is the same as the CGI script shown above, except that the pathnames are modified to suit the environment: |
︙ | ︙ |
Changes to www/server.wiki.
︙ | ︙ | |||
100 101 102 103 104 105 106 | </p> <p> [http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that accepts and decodes SSL-encrypted connections. Fossil can be run directly from stunnel in a mannar similar to inetd and xinetd. This can be used to provide a secure link to a Fossil project. The configuration needed to get stunnel4 to invoke Fossil is very similar to the inetd and xinetd examples shown above. | > > > > > > > > > | > > > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | </p> <p> [http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that accepts and decodes SSL-encrypted connections. Fossil can be run directly from stunnel in a mannar similar to inetd and xinetd. This can be used to provide a secure link to a Fossil project. The configuration needed to get stunnel4 to invoke Fossil is very similar to the inetd and xinetd examples shown above. The relevant parts of an stunnel configuration might look something like the following: <blockquote><pre><nowiki> [https] accept = www.ubercool-project.org:443 TIMEOUTclose = 0 exec = /usr/bin/fossil execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https </nowiki></pre></blockquote> See the stunnel4 documentation for further details bout the /etc/stunnel/stunnel.conf configuration file. Note that the [/help/http|fossil http] command should include the --https option to let Fossil know to use "https" instead of "http" as the scheme on generated hyperlinks. <p> Using inetd or xinetd or stunnel is a more complex setup than the "standalone" server, but it has the advantage of only using system resources when an actual connection is attempted. If no-one ever connects to that port, a Fossil server will not (automatically) run. It has the disadvantage of requiring "root" access and therefore may not normally be available to lower-priced "shared" servers |
︙ | ︙ | |||
156 157 158 159 160 161 162 | Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance). </p> <p> | | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance). </p> <p> To serve multiple repositories from a directory using CGI, use the "directory:" tag in the CGI script rather than "repository:". You might also want to add a "notfound:" tag to tell where to redirect if the particular repository requested by the URL is not found: <blockquote><pre> #!/usr/bin/fossil directory: /home/fossil/repos notfound: http://url-to-go-to-if-repo-not-found/ </pre></blockquote> </p> <p> Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b> will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists). </p> </blockquote> <a name="scgi"></a> <h2>Fossil as SCGI</h2><blockquote> <p> |
︙ | ︙ |