Fossil SCM
Merge from trunk.
Commit
50b56eec70a93150649ef763b10858f87bb4be289b2b466711ce70e549e1cc9f
Parent
0ffacb525a925ba…
28 files changed
+126
-67
+378
-38
+23
-9
+16
-4
+2
-2
+3
-2
+1
-1
+1
-1
+1
-2
+2
-1
+8
-5
+1
-1
+7
-3
+4
-2
+7
-5
+5
-3
+2
-1
+3
-1
+1
+4
-3
+4
-2
+5
-2
+12
-8
+2
-2
+1
-1
+9
-5
+31
-7
+2
-3
~
extsrc/shell.c
~
extsrc/sqlite3.c
~
extsrc/sqlite3.h
~
src/branch.c
~
src/browse.c
~
src/checkin.c
~
src/checkout.c
~
src/db.c
~
src/descendants.c
~
src/diff.c
~
src/export.c
~
src/fileedit.c
~
src/finfo.c
~
src/graph.c
~
src/import.c
~
src/info.c
~
src/json_branch.c
~
src/leaf.c
~
src/path.c
~
src/rebuild.c
~
src/search.c
~
src/setup.c
~
src/tar.c
~
src/timeline.c
~
src/update.c
~
src/zip.c
~
tools/email-sender.tcl
~
www/alerts.md
+126
-67
| --- extsrc/shell.c | ||
| +++ extsrc/shell.c | ||
| @@ -7182,10 +7182,19 @@ | ||
| 7182 | 7182 | sqlite3_free(pRe->aOp); |
| 7183 | 7183 | sqlite3_free(pRe->aArg); |
| 7184 | 7184 | sqlite3_free(pRe); |
| 7185 | 7185 | } |
| 7186 | 7186 | } |
| 7187 | + | |
| 7188 | +/* | |
| 7189 | +** Version of re_free() that accepts a pointer of type (void*). Required | |
| 7190 | +** to satisfy sanitizers when the re_free() function is called via a | |
| 7191 | +** function pointer. | |
| 7192 | +*/ | |
| 7193 | +static void re_free_voidptr(void *p){ | |
| 7194 | + re_free((ReCompiled*)p); | |
| 7195 | +} | |
| 7187 | 7196 | |
| 7188 | 7197 | /* |
| 7189 | 7198 | ** Compile a textual regular expression in zIn[] into a compiled regular |
| 7190 | 7199 | ** expression suitable for us by re_match() and return a pointer to the |
| 7191 | 7200 | ** compiled regular expression in *ppRe. Return NULL on success or an |
| @@ -7314,11 +7323,11 @@ | ||
| 7314 | 7323 | zStr = (const unsigned char*)sqlite3_value_text(argv[1]); |
| 7315 | 7324 | if( zStr!=0 ){ |
| 7316 | 7325 | sqlite3_result_int(context, re_match(pRe, zStr, -1)); |
| 7317 | 7326 | } |
| 7318 | 7327 | if( setAux ){ |
| 7319 | - sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free); | |
| 7328 | + sqlite3_set_auxdata(context, 0, pRe, re_free_voidptr); | |
| 7320 | 7329 | } |
| 7321 | 7330 | } |
| 7322 | 7331 | |
| 7323 | 7332 | #if defined(SQLITE_DEBUG) |
| 7324 | 7333 | /* |
| @@ -8202,11 +8211,11 @@ | ||
| 8202 | 8211 | |
| 8203 | 8212 | pLvl->zDir = pCur->zPath; |
| 8204 | 8213 | pCur->zPath = 0; |
| 8205 | 8214 | pLvl->pDir = opendir(pLvl->zDir); |
| 8206 | 8215 | if( pLvl->pDir==0 ){ |
| 8207 | - fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); | |
| 8216 | + fsdirSetErrmsg(pCur, "cannot read directory: %s", pLvl->zDir); | |
| 8208 | 8217 | return SQLITE_ERROR; |
| 8209 | 8218 | } |
| 8210 | 8219 | } |
| 8211 | 8220 | |
| 8212 | 8221 | while( pCur->iLvl>=0 ){ |
| @@ -12531,15 +12540,15 @@ | ||
| 12531 | 12540 | |
| 12532 | 12541 | /* |
| 12533 | 12542 | ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). |
| 12534 | 12543 | ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. |
| 12535 | 12544 | */ |
| 12536 | -static void *idxMalloc(int *pRc, int nByte){ | |
| 12545 | +static void *idxMalloc(int *pRc, i64 nByte){ | |
| 12537 | 12546 | void *pRet; |
| 12538 | 12547 | assert( *pRc==SQLITE_OK ); |
| 12539 | 12548 | assert( nByte>0 ); |
| 12540 | - pRet = sqlite3_malloc(nByte); | |
| 12549 | + pRet = sqlite3_malloc64(nByte); | |
| 12541 | 12550 | if( pRet ){ |
| 12542 | 12551 | memset(pRet, 0, nByte); |
| 12543 | 12552 | }else{ |
| 12544 | 12553 | *pRc = SQLITE_NOMEM; |
| 12545 | 12554 | } |
| @@ -12602,11 +12611,11 @@ | ||
| 12602 | 12611 | for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ |
| 12603 | 12612 | if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ |
| 12604 | 12613 | return 1; |
| 12605 | 12614 | } |
| 12606 | 12615 | } |
| 12607 | - pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); | |
| 12616 | + pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1); | |
| 12608 | 12617 | if( pEntry ){ |
| 12609 | 12618 | pEntry->zKey = (char*)&pEntry[1]; |
| 12610 | 12619 | memcpy(pEntry->zKey, zKey, nKey); |
| 12611 | 12620 | if( zVal ){ |
| 12612 | 12621 | pEntry->zVal = &pEntry->zKey[nKey+1]; |
| @@ -12737,19 +12746,19 @@ | ||
| 12737 | 12746 | sqlite3_vtab_cursor base; |
| 12738 | 12747 | sqlite3_stmt *pData; |
| 12739 | 12748 | }; |
| 12740 | 12749 | |
| 12741 | 12750 | static char *expertDequote(const char *zIn){ |
| 12742 | - int n = STRLEN(zIn); | |
| 12743 | - char *zRet = sqlite3_malloc(n); | |
| 12751 | + i64 n = STRLEN(zIn); | |
| 12752 | + char *zRet = sqlite3_malloc64(n); | |
| 12744 | 12753 | |
| 12745 | 12754 | assert( zIn[0]=='\'' ); |
| 12746 | 12755 | assert( zIn[n-1]=='\'' ); |
| 12747 | 12756 | |
| 12748 | 12757 | if( zRet ){ |
| 12749 | - int iOut = 0; | |
| 12750 | - int iIn = 0; | |
| 12758 | + i64 iOut = 0; | |
| 12759 | + i64 iIn = 0; | |
| 12751 | 12760 | for(iIn=1; iIn<(n-1); iIn++){ |
| 12752 | 12761 | if( zIn[iIn]=='\'' ){ |
| 12753 | 12762 | assert( zIn[iIn+1]=='\'' ); |
| 12754 | 12763 | iIn++; |
| 12755 | 12764 | } |
| @@ -13058,11 +13067,11 @@ | ||
| 13058 | 13067 | char **pzErrmsg /* OUT: Error message (if not) */ |
| 13059 | 13068 | ){ |
| 13060 | 13069 | sqlite3_stmt *p1 = 0; |
| 13061 | 13070 | int nCol = 0; |
| 13062 | 13071 | int nTab; |
| 13063 | - int nByte; | |
| 13072 | + i64 nByte; | |
| 13064 | 13073 | IdxTable *pNew = 0; |
| 13065 | 13074 | int rc, rc2; |
| 13066 | 13075 | char *pCsr = 0; |
| 13067 | 13076 | int nPk = 0; |
| 13068 | 13077 | |
| @@ -13150,18 +13159,18 @@ | ||
| 13150 | 13159 | */ |
| 13151 | 13160 | static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ |
| 13152 | 13161 | va_list ap; |
| 13153 | 13162 | char *zAppend = 0; |
| 13154 | 13163 | char *zRet = 0; |
| 13155 | - int nIn = zIn ? STRLEN(zIn) : 0; | |
| 13156 | - int nAppend = 0; | |
| 13164 | + i64 nIn = zIn ? STRLEN(zIn) : 0; | |
| 13165 | + i64 nAppend = 0; | |
| 13157 | 13166 | va_start(ap, zFmt); |
| 13158 | 13167 | if( *pRc==SQLITE_OK ){ |
| 13159 | 13168 | zAppend = sqlite3_vmprintf(zFmt, ap); |
| 13160 | 13169 | if( zAppend ){ |
| 13161 | 13170 | nAppend = STRLEN(zAppend); |
| 13162 | - zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); | |
| 13171 | + zRet = (char*)sqlite3_malloc64(nIn + nAppend + 1); | |
| 13163 | 13172 | } |
| 13164 | 13173 | if( zAppend && zRet ){ |
| 13165 | 13174 | if( nIn ) memcpy(zRet, zIn, nIn); |
| 13166 | 13175 | memcpy(&zRet[nIn], zAppend, nAppend+1); |
| 13167 | 13176 | }else{ |
| @@ -13921,12 +13930,12 @@ | ||
| 13921 | 13930 | int nSlot; |
| 13922 | 13931 | struct IdxRemSlot { |
| 13923 | 13932 | int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ |
| 13924 | 13933 | i64 iVal; /* SQLITE_INTEGER value */ |
| 13925 | 13934 | double rVal; /* SQLITE_FLOAT value */ |
| 13926 | - int nByte; /* Bytes of space allocated at z */ | |
| 13927 | - int n; /* Size of buffer z */ | |
| 13935 | + i64 nByte; /* Bytes of space allocated at z */ | |
| 13936 | + i64 n; /* Size of buffer z */ | |
| 13928 | 13937 | char *z; /* SQLITE_TEXT/BLOB value */ |
| 13929 | 13938 | } aSlot[1]; |
| 13930 | 13939 | }; |
| 13931 | 13940 | |
| 13932 | 13941 | /* |
| @@ -13958,15 +13967,17 @@ | ||
| 13958 | 13967 | case SQLITE_FLOAT: |
| 13959 | 13968 | sqlite3_result_double(pCtx, pSlot->rVal); |
| 13960 | 13969 | break; |
| 13961 | 13970 | |
| 13962 | 13971 | case SQLITE_BLOB: |
| 13963 | - sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); | |
| 13972 | + assert( pSlot->n <= 0x7fffffff ); | |
| 13973 | + sqlite3_result_blob(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT); | |
| 13964 | 13974 | break; |
| 13965 | 13975 | |
| 13966 | 13976 | case SQLITE_TEXT: |
| 13967 | - sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); | |
| 13977 | + assert( pSlot->n <= 0x7fffffff ); | |
| 13978 | + sqlite3_result_text(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT); | |
| 13968 | 13979 | break; |
| 13969 | 13980 | } |
| 13970 | 13981 | |
| 13971 | 13982 | pSlot->eType = sqlite3_value_type(argv[1]); |
| 13972 | 13983 | switch( pSlot->eType ){ |
| @@ -13982,14 +13993,14 @@ | ||
| 13982 | 13993 | pSlot->rVal = sqlite3_value_double(argv[1]); |
| 13983 | 13994 | break; |
| 13984 | 13995 | |
| 13985 | 13996 | case SQLITE_BLOB: |
| 13986 | 13997 | case SQLITE_TEXT: { |
| 13987 | - int nByte = sqlite3_value_bytes(argv[1]); | |
| 13998 | + i64 nByte = sqlite3_value_bytes(argv[1]); | |
| 13988 | 13999 | const void *pData = 0; |
| 13989 | 14000 | if( nByte>pSlot->nByte ){ |
| 13990 | - char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); | |
| 14001 | + char *zNew = (char*)sqlite3_realloc64(pSlot->z, nByte*2); | |
| 13991 | 14002 | if( zNew==0 ){ |
| 13992 | 14003 | sqlite3_result_error_nomem(pCtx); |
| 13993 | 14004 | return; |
| 13994 | 14005 | } |
| 13995 | 14006 | pSlot->nByte = nByte*2; |
| @@ -14040,11 +14051,11 @@ | ||
| 14040 | 14051 | char *zOrder = 0; |
| 14041 | 14052 | char *zQuery = 0; |
| 14042 | 14053 | int nCol = 0; |
| 14043 | 14054 | int i; |
| 14044 | 14055 | sqlite3_stmt *pQuery = 0; |
| 14045 | - int *aStat = 0; | |
| 14056 | + i64 *aStat = 0; | |
| 14046 | 14057 | int rc = SQLITE_OK; |
| 14047 | 14058 | |
| 14048 | 14059 | assert( p->iSample>0 ); |
| 14049 | 14060 | |
| 14050 | 14061 | /* Formulate the query text */ |
| @@ -14086,11 +14097,11 @@ | ||
| 14086 | 14097 | rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); |
| 14087 | 14098 | } |
| 14088 | 14099 | sqlite3_free(zQuery); |
| 14089 | 14100 | |
| 14090 | 14101 | if( rc==SQLITE_OK ){ |
| 14091 | - aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); | |
| 14102 | + aStat = (i64*)idxMalloc(&rc, sizeof(i64)*(nCol+1)); | |
| 14092 | 14103 | } |
| 14093 | 14104 | if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ |
| 14094 | 14105 | IdxHashEntry *pEntry; |
| 14095 | 14106 | char *zStat = 0; |
| 14096 | 14107 | for(i=0; i<=nCol; i++) aStat[i] = 1; |
| @@ -14103,15 +14114,15 @@ | ||
| 14103 | 14114 | aStat[i+1]++; |
| 14104 | 14115 | } |
| 14105 | 14116 | } |
| 14106 | 14117 | |
| 14107 | 14118 | if( rc==SQLITE_OK ){ |
| 14108 | - int s0 = aStat[0]; | |
| 14109 | - zStat = sqlite3_mprintf("%d", s0); | |
| 14119 | + i64 s0 = aStat[0]; | |
| 14120 | + zStat = sqlite3_mprintf("%lld", s0); | |
| 14110 | 14121 | if( zStat==0 ) rc = SQLITE_NOMEM; |
| 14111 | 14122 | for(i=1; rc==SQLITE_OK && i<=nCol; i++){ |
| 14112 | - zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]); | |
| 14123 | + zStat = idxAppendText(&rc, zStat, " %lld", (s0+aStat[i]/2) / aStat[i]); | |
| 14113 | 14124 | } |
| 14114 | 14125 | } |
| 14115 | 14126 | |
| 14116 | 14127 | if( rc==SQLITE_OK ){ |
| 14117 | 14128 | sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); |
| @@ -14186,11 +14197,11 @@ | ||
| 14186 | 14197 | if( nMax<=0 || rc!=SQLITE_OK ) return rc; |
| 14187 | 14198 | |
| 14188 | 14199 | rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); |
| 14189 | 14200 | |
| 14190 | 14201 | if( rc==SQLITE_OK ){ |
| 14191 | - int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); | |
| 14202 | + i64 nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); | |
| 14192 | 14203 | pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); |
| 14193 | 14204 | } |
| 14194 | 14205 | |
| 14195 | 14206 | if( rc==SQLITE_OK ){ |
| 14196 | 14207 | sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); |
| @@ -14203,11 +14214,11 @@ | ||
| 14203 | 14214 | 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 |
| 14204 | 14215 | ); |
| 14205 | 14216 | } |
| 14206 | 14217 | |
| 14207 | 14218 | if( rc==SQLITE_OK ){ |
| 14208 | - pCtx->nSlot = nMax+1; | |
| 14219 | + pCtx->nSlot = (i64)nMax+1; | |
| 14209 | 14220 | rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); |
| 14210 | 14221 | } |
| 14211 | 14222 | if( rc==SQLITE_OK ){ |
| 14212 | 14223 | rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); |
| 14213 | 14224 | } |
| @@ -14470,11 +14481,11 @@ | ||
| 14470 | 14481 | rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); |
| 14471 | 14482 | if( rc==SQLITE_OK ){ |
| 14472 | 14483 | if( pStmt ){ |
| 14473 | 14484 | IdxStatement *pNew; |
| 14474 | 14485 | const char *z = sqlite3_sql(pStmt); |
| 14475 | - int n = STRLEN(z); | |
| 14486 | + i64 n = STRLEN(z); | |
| 14476 | 14487 | pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); |
| 14477 | 14488 | if( rc==SQLITE_OK ){ |
| 14478 | 14489 | pNew->zSql = (char*)&pNew[1]; |
| 14479 | 14490 | memcpy(pNew->zSql, z, n+1); |
| 14480 | 14491 | pNew->pNext = p->pStatement; |
| @@ -21295,11 +21306,11 @@ | ||
| 21295 | 21306 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 21296 | 21307 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 21297 | 21308 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 21298 | 21309 | int outCount; /* Revert to stdout when reaching zero */ |
| 21299 | 21310 | int cnt; /* Number of records displayed so far */ |
| 21300 | - int lineno; /* Line number of last line read from in */ | |
| 21311 | + i64 lineno; /* Line number of last line read from in */ | |
| 21301 | 21312 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 21302 | 21313 | FILE *in; /* Read commands from this stream */ |
| 21303 | 21314 | FILE *out; /* Write results here */ |
| 21304 | 21315 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 21305 | 21316 | int nErr; /* Number of errors seen */ |
| @@ -21531,11 +21542,11 @@ | ||
| 21531 | 21542 | va_list ap; |
| 21532 | 21543 | char *zMsg; |
| 21533 | 21544 | va_start(ap, zErrMsg); |
| 21534 | 21545 | zMsg = sqlite3_vmprintf(zErrMsg, ap); |
| 21535 | 21546 | va_end(ap); |
| 21536 | - sqlite3_fprintf(stderr, "line %d: %s\n", p->lineno, zMsg); | |
| 21547 | + sqlite3_fprintf(stderr, "line %lld: %s\n", p->lineno, zMsg); | |
| 21537 | 21548 | exit(1); |
| 21538 | 21549 | } |
| 21539 | 21550 | } |
| 21540 | 21551 | |
| 21541 | 21552 | /* |
| @@ -25087,10 +25098,11 @@ | ||
| 25087 | 25098 | " --ifexist Only open if FILE already exists", |
| 25088 | 25099 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25089 | 25100 | " --maxsize N Maximum size for --hexdb or --deserialized database", |
| 25090 | 25101 | #endif |
| 25091 | 25102 | " --new Initialize FILE to an empty database", |
| 25103 | + " --normal FILE is an ordinary SQLite database", | |
| 25092 | 25104 | " --nofollow Do not follow symbolic links", |
| 25093 | 25105 | " --readonly Open FILE readonly", |
| 25094 | 25106 | " --zip FILE is a ZIP archive", |
| 25095 | 25107 | #ifndef SQLITE_SHELL_FIDDLE |
| 25096 | 25108 | ".output ?FILE? Send output to FILE or stdout if FILE is omitted", |
| @@ -25321,11 +25333,11 @@ | ||
| 25321 | 25333 | sqlite3_free(zPat); |
| 25322 | 25334 | return n; |
| 25323 | 25335 | } |
| 25324 | 25336 | |
| 25325 | 25337 | /* Forward reference */ |
| 25326 | -static int process_input(ShellState *p); | |
| 25338 | +static int process_input(ShellState *p, const char*); | |
| 25327 | 25339 | |
| 25328 | 25340 | /* |
| 25329 | 25341 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 25330 | 25342 | ** and return a pointer to the buffer. The caller is responsible for freeing |
| 25331 | 25343 | ** the memory. |
| @@ -25428,22 +25440,30 @@ | ||
| 25428 | 25440 | ** If the file does not exist or is empty but its name looks like a ZIP |
| 25429 | 25441 | ** archive and the dfltZip flag is true, then assume it is a ZIP archive. |
| 25430 | 25442 | ** Otherwise, assume an ordinary database regardless of the filename if |
| 25431 | 25443 | ** the type cannot be determined from content. |
| 25432 | 25444 | */ |
| 25433 | -int deduceDatabaseType(const char *zName, int dfltZip){ | |
| 25434 | - FILE *f = sqlite3_fopen(zName, "rb"); | |
| 25445 | +int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){ | |
| 25446 | + FILE *f; | |
| 25435 | 25447 | size_t n; |
| 25448 | + sqlite3 *db = 0; | |
| 25449 | + sqlite3_stmt *pStmt = 0; | |
| 25436 | 25450 | int rc = SHELL_OPEN_UNSPEC; |
| 25437 | 25451 | char zBuf[100]; |
| 25438 | - if( f==0 ){ | |
| 25439 | - if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ | |
| 25440 | - return SHELL_OPEN_ZIPFILE; | |
| 25441 | - }else{ | |
| 25442 | - return SHELL_OPEN_NORMAL; | |
| 25443 | - } | |
| 25452 | + if( access(zName,0)!=0 ) goto database_type_by_name; | |
| 25453 | + if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK | |
| 25454 | + && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) | |
| 25455 | + ==SQLITE_OK | |
| 25456 | + && sqlite3_step(pStmt)==SQLITE_ROW | |
| 25457 | + ){ | |
| 25458 | + rc = SHELL_OPEN_NORMAL; | |
| 25444 | 25459 | } |
| 25460 | + sqlite3_finalize(pStmt); | |
| 25461 | + sqlite3_close(db); | |
| 25462 | + if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL; | |
| 25463 | + f = sqlite3_fopen(zName, "rb"); | |
| 25464 | + if( f==0 ) goto database_type_by_name; | |
| 25445 | 25465 | n = fread(zBuf, 16, 1, f); |
| 25446 | 25466 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| 25447 | 25467 | fclose(f); |
| 25448 | 25468 | return SHELL_OPEN_NORMAL; |
| 25449 | 25469 | } |
| @@ -25461,10 +25481,18 @@ | ||
| 25461 | 25481 | rc = SHELL_OPEN_ZIPFILE; |
| 25462 | 25482 | } |
| 25463 | 25483 | } |
| 25464 | 25484 | fclose(f); |
| 25465 | 25485 | return rc; |
| 25486 | + | |
| 25487 | +database_type_by_name: | |
| 25488 | + if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ | |
| 25489 | + rc = SHELL_OPEN_ZIPFILE; | |
| 25490 | + }else{ | |
| 25491 | + rc = SHELL_OPEN_NORMAL; | |
| 25492 | + } | |
| 25493 | + return rc; | |
| 25466 | 25494 | } |
| 25467 | 25495 | |
| 25468 | 25496 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25469 | 25497 | /* |
| 25470 | 25498 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| @@ -25471,11 +25499,11 @@ | ||
| 25471 | 25499 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| 25472 | 25500 | ** If p->aAuxDb[].zDbFilename is 0, then read from standard input. |
| 25473 | 25501 | */ |
| 25474 | 25502 | static unsigned char *readHexDb(ShellState *p, int *pnData){ |
| 25475 | 25503 | unsigned char *a = 0; |
| 25476 | - int nLine; | |
| 25504 | + i64 nLine; | |
| 25477 | 25505 | int n = 0; /* Size of db per first line of hex dump */ |
| 25478 | 25506 | i64 sz = 0; /* n rounded up to nearest page boundary */ |
| 25479 | 25507 | int pgsz = 0; |
| 25480 | 25508 | i64 iOffset = 0; |
| 25481 | 25509 | int rc; |
| @@ -25510,10 +25538,14 @@ | ||
| 25510 | 25538 | shell_check_oom(a); |
| 25511 | 25539 | memset(a, 0, sz); |
| 25512 | 25540 | for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){ |
| 25513 | 25541 | int j = 0; /* Page number from "| page" line */ |
| 25514 | 25542 | int k = 0; /* Offset from "| page" line */ |
| 25543 | + if( nLine>=2000000000 ){ | |
| 25544 | + sqlite3_fprintf(stderr, "input too big\n"); | |
| 25545 | + goto readHexDb_error; | |
| 25546 | + } | |
| 25515 | 25547 | rc = sscanf(zLine, "| page %d offset %d", &j, &k); |
| 25516 | 25548 | if( rc==2 ){ |
| 25517 | 25549 | iOffset = k; |
| 25518 | 25550 | continue; |
| 25519 | 25551 | } |
| @@ -25548,11 +25580,11 @@ | ||
| 25548 | 25580 | if(cli_strncmp(zLine, "| end ", 6)==0 ) break; |
| 25549 | 25581 | } |
| 25550 | 25582 | p->lineno = nLine; |
| 25551 | 25583 | } |
| 25552 | 25584 | sqlite3_free(a); |
| 25553 | - sqlite3_fprintf(stderr,"Error on line %d of --hexdb input\n", nLine); | |
| 25585 | + sqlite3_fprintf(stderr,"Error on line %lld of --hexdb input\n", nLine); | |
| 25554 | 25586 | return 0; |
| 25555 | 25587 | } |
| 25556 | 25588 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 25557 | 25589 | |
| 25558 | 25590 | /* |
| @@ -25625,11 +25657,11 @@ | ||
| 25625 | 25657 | if( p->openMode==SHELL_OPEN_UNSPEC ){ |
| 25626 | 25658 | if( zDbFilename==0 || zDbFilename[0]==0 ){ |
| 25627 | 25659 | p->openMode = SHELL_OPEN_NORMAL; |
| 25628 | 25660 | }else{ |
| 25629 | 25661 | p->openMode = (u8)deduceDatabaseType(zDbFilename, |
| 25630 | - (openFlags & OPEN_DB_ZIPFILE)!=0); | |
| 25662 | + (openFlags & OPEN_DB_ZIPFILE)!=0, p->openFlags); | |
| 25631 | 25663 | } |
| 25632 | 25664 | } |
| 25633 | 25665 | if( (p->openFlags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE))==0 ){ |
| 25634 | 25666 | if( p->openFlags==0 ) p->openFlags = SQLITE_OPEN_CREATE; |
| 25635 | 25667 | p->openFlags |= SQLITE_OPEN_READWRITE; |
| @@ -27652,29 +27684,45 @@ | ||
| 27652 | 27684 | int *pRc, |
| 27653 | 27685 | ArCommand *pAr, |
| 27654 | 27686 | char **pzWhere /* OUT: New WHERE clause */ |
| 27655 | 27687 | ){ |
| 27656 | 27688 | char *zWhere = 0; |
| 27657 | - const char *zSameOp = (pAr->bGlob)? "GLOB" : "="; | |
| 27658 | 27689 | if( *pRc==SQLITE_OK ){ |
| 27659 | 27690 | if( pAr->nArg==0 ){ |
| 27660 | 27691 | zWhere = sqlite3_mprintf("1"); |
| 27661 | 27692 | }else{ |
| 27693 | + char *z1 = sqlite3_mprintf(pAr->bGlob ? "" : "name IN("); | |
| 27694 | + char *z2 = sqlite3_mprintf(""); | |
| 27695 | + const char *zSep1 = ""; | |
| 27696 | + const char *zSep2 = ""; | |
| 27697 | + | |
| 27662 | 27698 | int i; |
| 27663 | - const char *zSep = ""; | |
| 27664 | - for(i=0; i<pAr->nArg; i++){ | |
| 27699 | + for(i=0; i<pAr->nArg && z1 && z2; i++){ | |
| 27665 | 27700 | const char *z = pAr->azArg[i]; |
| 27666 | - zWhere = sqlite3_mprintf( | |
| 27667 | - "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'", | |
| 27668 | - zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z | |
| 27701 | + int n = strlen30(z); | |
| 27702 | + | |
| 27703 | + if( pAr->bGlob ){ | |
| 27704 | + z1 = sqlite3_mprintf("%z%sname GLOB '%q'", z1, zSep2, z); | |
| 27705 | + z2 = sqlite3_mprintf( | |
| 27706 | + "%z%ssubstr(name,1,%d) GLOB '%q/'", z2, zSep2, n+1,z | |
| 27707 | + ); | |
| 27708 | + }else{ | |
| 27709 | + z1 = sqlite3_mprintf("%z%s'%q'", z1, zSep1, z); | |
| 27710 | + z2 = sqlite3_mprintf("%z%ssubstr(name,1,%d) = '%q/'",z2,zSep2,n+1,z); | |
| 27711 | + } | |
| 27712 | + zSep1 = ", "; | |
| 27713 | + zSep2 = " OR "; | |
| 27714 | + } | |
| 27715 | + if( z1==0 || z2==0 ){ | |
| 27716 | + *pRc = SQLITE_NOMEM; | |
| 27717 | + }else{ | |
| 27718 | + zWhere = sqlite3_mprintf("(%s%s OR (name GLOB '*/*' AND (%s))) ", | |
| 27719 | + z1, pAr->bGlob==0 ? ")" : "", z2 | |
| 27669 | 27720 | ); |
| 27670 | - if( zWhere==0 ){ | |
| 27671 | - *pRc = SQLITE_NOMEM; | |
| 27672 | - break; | |
| 27673 | - } | |
| 27674 | - zSep = " OR "; | |
| 27675 | 27721 | } |
| 27722 | + sqlite3_free(z1); | |
| 27723 | + sqlite3_free(z2); | |
| 27676 | 27724 | } |
| 27677 | 27725 | } |
| 27678 | 27726 | *pzWhere = zWhere; |
| 27679 | 27727 | } |
| 27680 | 27728 | |
| @@ -27990,11 +28038,11 @@ | ||
| 27990 | 28038 | int eDbType = SHELL_OPEN_UNSPEC; |
| 27991 | 28039 | cmd.p = pState; |
| 27992 | 28040 | cmd.out = pState->out; |
| 27993 | 28041 | cmd.db = pState->db; |
| 27994 | 28042 | if( cmd.zFile ){ |
| 27995 | - eDbType = deduceDatabaseType(cmd.zFile, 1); | |
| 28043 | + eDbType = deduceDatabaseType(cmd.zFile, 1, 0); | |
| 27996 | 28044 | }else{ |
| 27997 | 28045 | eDbType = pState->openMode; |
| 27998 | 28046 | } |
| 27999 | 28047 | if( eDbType==SHELL_OPEN_ZIPFILE ){ |
| 28000 | 28048 | if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ |
| @@ -29312,11 +29360,11 @@ | ||
| 29312 | 29360 | int nSep; /* Number of bytes in p->colSeparator[] */ |
| 29313 | 29361 | char *zSql = 0; /* An SQL statement */ |
| 29314 | 29362 | ImportCtx sCtx; /* Reader context */ |
| 29315 | 29363 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 29316 | 29364 | int eVerbose = 0; /* Larger for more console output */ |
| 29317 | - int nSkip = 0; /* Initial lines to skip */ | |
| 29365 | + i64 nSkip = 0; /* Initial lines to skip */ | |
| 29318 | 29366 | int useOutputMode = 1; /* Use output mode to determine separators */ |
| 29319 | 29367 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 29320 | 29368 | |
| 29321 | 29369 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 29322 | 29370 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30037,11 +30085,11 @@ | ||
| 30037 | 30085 | if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){ |
| 30038 | 30086 | if( nArg!=2 ){ |
| 30039 | 30087 | eputz("Usage: .nonce NONCE\n"); |
| 30040 | 30088 | rc = 1; |
| 30041 | 30089 | }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){ |
| 30042 | - sqlite3_fprintf(stderr,"line %d: incorrect nonce: \"%s\"\n", | |
| 30090 | + sqlite3_fprintf(stderr,"line %lld: incorrect nonce: \"%s\"\n", | |
| 30043 | 30091 | p->lineno, azArg[1]); |
| 30044 | 30092 | exit(1); |
| 30045 | 30093 | }else{ |
| 30046 | 30094 | p->bSafeMode = 0; |
| 30047 | 30095 | return 0; /* Return immediately to bypass the safe mode reset |
| @@ -30092,10 +30140,12 @@ | ||
| 30092 | 30140 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 30093 | 30141 | }else if( optionMatch(z, "deserialize") ){ |
| 30094 | 30142 | openMode = SHELL_OPEN_DESERIALIZE; |
| 30095 | 30143 | }else if( optionMatch(z, "hexdb") ){ |
| 30096 | 30144 | openMode = SHELL_OPEN_HEXDB; |
| 30145 | + }else if( optionMatch(z, "normal") ){ | |
| 30146 | + openMode = SHELL_OPEN_NORMAL; | |
| 30097 | 30147 | }else if( optionMatch(z, "maxsize") && iName+1<nArg ){ |
| 30098 | 30148 | p->szMax = integerValue(azArg[++iName]); |
| 30099 | 30149 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 30100 | 30150 | }else |
| 30101 | 30151 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -30210,10 +30260,11 @@ | ||
| 30210 | 30260 | }else{ |
| 30211 | 30261 | sqlite3_fprintf(p->out, |
| 30212 | 30262 | "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); |
| 30213 | 30263 | showHelp(p->out, azArg[0]); |
| 30214 | 30264 | rc = 1; |
| 30265 | + sqlite3_free(zFile); | |
| 30215 | 30266 | goto meta_command_exit; |
| 30216 | 30267 | } |
| 30217 | 30268 | }else if( zFile==0 && eMode==0 ){ |
| 30218 | 30269 | if( cli_strcmp(z, "off")==0 ){ |
| 30219 | 30270 | #ifdef _WIN32 |
| @@ -30493,11 +30544,11 @@ | ||
| 30493 | 30544 | #endif |
| 30494 | 30545 | |
| 30495 | 30546 | #ifndef SQLITE_SHELL_FIDDLE |
| 30496 | 30547 | if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){ |
| 30497 | 30548 | FILE *inSaved = p->in; |
| 30498 | - int savedLineno = p->lineno; | |
| 30549 | + i64 savedLineno = p->lineno; | |
| 30499 | 30550 | failIfSafeMode(p, "cannot run .read in safe mode"); |
| 30500 | 30551 | if( nArg!=2 ){ |
| 30501 | 30552 | eputz("Usage: .read FILE\n"); |
| 30502 | 30553 | rc = 1; |
| 30503 | 30554 | goto meta_command_exit; |
| @@ -30510,19 +30561,19 @@ | ||
| 30510 | 30561 | p->in = sqlite3_popen(azArg[1]+1, "r"); |
| 30511 | 30562 | if( p->in==0 ){ |
| 30512 | 30563 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30513 | 30564 | rc = 1; |
| 30514 | 30565 | }else{ |
| 30515 | - rc = process_input(p); | |
| 30566 | + rc = process_input(p, "<pipe>"); | |
| 30516 | 30567 | pclose(p->in); |
| 30517 | 30568 | } |
| 30518 | 30569 | #endif |
| 30519 | 30570 | }else if( (p->in = openChrSource(azArg[1]))==0 ){ |
| 30520 | 30571 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30521 | 30572 | rc = 1; |
| 30522 | 30573 | }else{ |
| 30523 | - rc = process_input(p); | |
| 30574 | + rc = process_input(p, azArg[1]); | |
| 30524 | 30575 | fclose(p->in); |
| 30525 | 30576 | } |
| 30526 | 30577 | p->in = inSaved; |
| 30527 | 30578 | p->lineno = savedLineno; |
| 30528 | 30579 | }else |
| @@ -32509,11 +32560,11 @@ | ||
| 32509 | 32560 | ** is saved only if input is interactive. An interrupt signal will |
| 32510 | 32561 | ** cause this routine to exit immediately, unless input is interactive. |
| 32511 | 32562 | ** |
| 32512 | 32563 | ** Return the number of errors. |
| 32513 | 32564 | */ |
| 32514 | -static int process_input(ShellState *p){ | |
| 32565 | +static int process_input(ShellState *p, const char *zSrc){ | |
| 32515 | 32566 | char *zLine = 0; /* A single input line */ |
| 32516 | 32567 | char *zSql = 0; /* Accumulated SQL text */ |
| 32517 | 32568 | i64 nLine; /* Length of current line */ |
| 32518 | 32569 | i64 nSql = 0; /* Bytes of zSql[] used */ |
| 32519 | 32570 | i64 nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -32522,12 +32573,12 @@ | ||
| 32522 | 32573 | i64 startline = 0; /* Line number for start of current input */ |
| 32523 | 32574 | QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ |
| 32524 | 32575 | |
| 32525 | 32576 | if( p->inputNesting==MAX_INPUT_NESTING ){ |
| 32526 | 32577 | /* This will be more informative in a later version. */ |
| 32527 | - sqlite3_fprintf(stderr,"Input nesting limit (%d) reached at line %d." | |
| 32528 | - " Check recursion.\n", MAX_INPUT_NESTING, p->lineno); | |
| 32578 | + sqlite3_fprintf(stderr,"%s: Input nesting limit (%d) reached at line %lld." | |
| 32579 | + " Check recursion.\n", zSrc, MAX_INPUT_NESTING, p->lineno); | |
| 32529 | 32580 | return 1; |
| 32530 | 32581 | } |
| 32531 | 32582 | ++p->inputNesting; |
| 32532 | 32583 | p->lineno = 0; |
| 32533 | 32584 | CONTINUE_PROMPT_RESET; |
| @@ -32588,11 +32639,19 @@ | ||
| 32588 | 32639 | }else{ |
| 32589 | 32640 | zSql[nSql++] = '\n'; |
| 32590 | 32641 | memcpy(zSql+nSql, zLine, nLine+1); |
| 32591 | 32642 | nSql += nLine; |
| 32592 | 32643 | } |
| 32593 | - if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ | |
| 32644 | + if( nSql>0x7fff0000 ){ | |
| 32645 | + char zSize[100]; | |
| 32646 | + sqlite3_snprintf(sizeof(zSize),zSize,"%,lld",nSql); | |
| 32647 | + sqlite3_fprintf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n", | |
| 32648 | + zSrc, startline, zSize); | |
| 32649 | + nSql = 0; | |
| 32650 | + errCnt++; | |
| 32651 | + break; | |
| 32652 | + }else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ | |
| 32594 | 32653 | echo_group_input(p, zSql); |
| 32595 | 32654 | errCnt += runOneSqlLine(p, zSql, p->in, startline); |
| 32596 | 32655 | CONTINUE_PROMPT_RESET; |
| 32597 | 32656 | nSql = 0; |
| 32598 | 32657 | if( p->outCount ){ |
| @@ -32756,11 +32815,11 @@ | ||
| 32756 | 32815 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 32757 | 32816 | ){ |
| 32758 | 32817 | char *home_dir = NULL; |
| 32759 | 32818 | char *sqliterc = (char*)sqliterc_override; |
| 32760 | 32819 | FILE *inSaved = p->in; |
| 32761 | - int savedLineno = p->lineno; | |
| 32820 | + i64 savedLineno = p->lineno; | |
| 32762 | 32821 | |
| 32763 | 32822 | if( sqliterc == NULL ){ |
| 32764 | 32823 | sqliterc = find_xdg_file("XDG_CONFIG_HOME", |
| 32765 | 32824 | ".config", |
| 32766 | 32825 | "sqlite3/sqliterc"); |
| @@ -32778,11 +32837,11 @@ | ||
| 32778 | 32837 | p->in = sqliterc ? sqlite3_fopen(sqliterc,"rb") : 0; |
| 32779 | 32838 | if( p->in ){ |
| 32780 | 32839 | if( stdin_is_interactive ){ |
| 32781 | 32840 | sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc); |
| 32782 | 32841 | } |
| 32783 | - if( process_input(p) && bail_on_error ) exit(1); | |
| 32842 | + if( process_input(p, sqliterc) && bail_on_error ) exit(1); | |
| 32784 | 32843 | fclose(p->in); |
| 32785 | 32844 | }else if( sqliterc_override!=0 ){ |
| 32786 | 32845 | sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc); |
| 32787 | 32846 | if( bail_on_error ) exit(1); |
| 32788 | 32847 | } |
| @@ -33609,19 +33668,19 @@ | ||
| 33609 | 33668 | linenoiseSetCompletionCallback(linenoise_completion); |
| 33610 | 33669 | #elif HAVE_LINENOISE==2 |
| 33611 | 33670 | linenoiseSetCompletionCallback(linenoise_completion, NULL); |
| 33612 | 33671 | #endif |
| 33613 | 33672 | data.in = 0; |
| 33614 | - rc = process_input(&data); | |
| 33673 | + rc = process_input(&data, "<stdin>"); | |
| 33615 | 33674 | if( zHistory ){ |
| 33616 | 33675 | shell_stifle_history(2000); |
| 33617 | 33676 | shell_write_history(zHistory); |
| 33618 | 33677 | sqlite3_free(zHistory); |
| 33619 | 33678 | } |
| 33620 | 33679 | }else{ |
| 33621 | 33680 | data.in = stdin; |
| 33622 | - rc = process_input(&data); | |
| 33681 | + rc = process_input(&data, "<stdin>"); | |
| 33623 | 33682 | } |
| 33624 | 33683 | } |
| 33625 | 33684 | #ifndef SQLITE_SHELL_FIDDLE |
| 33626 | 33685 | /* In WASM mode we have to leave the db state in place so that |
| 33627 | 33686 | ** client code can "push" SQL into it after this call returns. */ |
| @@ -33799,10 +33858,10 @@ | ||
| 33799 | 33858 | void fiddle_exec(const char * zSql){ |
| 33800 | 33859 | if(zSql && *zSql){ |
| 33801 | 33860 | if('.'==*zSql) puts(zSql); |
| 33802 | 33861 | shellState.wasm.zInput = zSql; |
| 33803 | 33862 | shellState.wasm.zPos = zSql; |
| 33804 | - process_input(&shellState); | |
| 33863 | + process_input(&shellState, "<stdin>"); | |
| 33805 | 33864 | shellState.wasm.zInput = shellState.wasm.zPos = 0; |
| 33806 | 33865 | } |
| 33807 | 33866 | } |
| 33808 | 33867 | #endif /* SQLITE_SHELL_FIDDLE */ |
| 33809 | 33868 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -7182,10 +7182,19 @@ | |
| 7182 | sqlite3_free(pRe->aOp); |
| 7183 | sqlite3_free(pRe->aArg); |
| 7184 | sqlite3_free(pRe); |
| 7185 | } |
| 7186 | } |
| 7187 | |
| 7188 | /* |
| 7189 | ** Compile a textual regular expression in zIn[] into a compiled regular |
| 7190 | ** expression suitable for us by re_match() and return a pointer to the |
| 7191 | ** compiled regular expression in *ppRe. Return NULL on success or an |
| @@ -7314,11 +7323,11 @@ | |
| 7314 | zStr = (const unsigned char*)sqlite3_value_text(argv[1]); |
| 7315 | if( zStr!=0 ){ |
| 7316 | sqlite3_result_int(context, re_match(pRe, zStr, -1)); |
| 7317 | } |
| 7318 | if( setAux ){ |
| 7319 | sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free); |
| 7320 | } |
| 7321 | } |
| 7322 | |
| 7323 | #if defined(SQLITE_DEBUG) |
| 7324 | /* |
| @@ -8202,11 +8211,11 @@ | |
| 8202 | |
| 8203 | pLvl->zDir = pCur->zPath; |
| 8204 | pCur->zPath = 0; |
| 8205 | pLvl->pDir = opendir(pLvl->zDir); |
| 8206 | if( pLvl->pDir==0 ){ |
| 8207 | fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); |
| 8208 | return SQLITE_ERROR; |
| 8209 | } |
| 8210 | } |
| 8211 | |
| 8212 | while( pCur->iLvl>=0 ){ |
| @@ -12531,15 +12540,15 @@ | |
| 12531 | |
| 12532 | /* |
| 12533 | ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). |
| 12534 | ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. |
| 12535 | */ |
| 12536 | static void *idxMalloc(int *pRc, int nByte){ |
| 12537 | void *pRet; |
| 12538 | assert( *pRc==SQLITE_OK ); |
| 12539 | assert( nByte>0 ); |
| 12540 | pRet = sqlite3_malloc(nByte); |
| 12541 | if( pRet ){ |
| 12542 | memset(pRet, 0, nByte); |
| 12543 | }else{ |
| 12544 | *pRc = SQLITE_NOMEM; |
| 12545 | } |
| @@ -12602,11 +12611,11 @@ | |
| 12602 | for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ |
| 12603 | if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ |
| 12604 | return 1; |
| 12605 | } |
| 12606 | } |
| 12607 | pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); |
| 12608 | if( pEntry ){ |
| 12609 | pEntry->zKey = (char*)&pEntry[1]; |
| 12610 | memcpy(pEntry->zKey, zKey, nKey); |
| 12611 | if( zVal ){ |
| 12612 | pEntry->zVal = &pEntry->zKey[nKey+1]; |
| @@ -12737,19 +12746,19 @@ | |
| 12737 | sqlite3_vtab_cursor base; |
| 12738 | sqlite3_stmt *pData; |
| 12739 | }; |
| 12740 | |
| 12741 | static char *expertDequote(const char *zIn){ |
| 12742 | int n = STRLEN(zIn); |
| 12743 | char *zRet = sqlite3_malloc(n); |
| 12744 | |
| 12745 | assert( zIn[0]=='\'' ); |
| 12746 | assert( zIn[n-1]=='\'' ); |
| 12747 | |
| 12748 | if( zRet ){ |
| 12749 | int iOut = 0; |
| 12750 | int iIn = 0; |
| 12751 | for(iIn=1; iIn<(n-1); iIn++){ |
| 12752 | if( zIn[iIn]=='\'' ){ |
| 12753 | assert( zIn[iIn+1]=='\'' ); |
| 12754 | iIn++; |
| 12755 | } |
| @@ -13058,11 +13067,11 @@ | |
| 13058 | char **pzErrmsg /* OUT: Error message (if not) */ |
| 13059 | ){ |
| 13060 | sqlite3_stmt *p1 = 0; |
| 13061 | int nCol = 0; |
| 13062 | int nTab; |
| 13063 | int nByte; |
| 13064 | IdxTable *pNew = 0; |
| 13065 | int rc, rc2; |
| 13066 | char *pCsr = 0; |
| 13067 | int nPk = 0; |
| 13068 | |
| @@ -13150,18 +13159,18 @@ | |
| 13150 | */ |
| 13151 | static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ |
| 13152 | va_list ap; |
| 13153 | char *zAppend = 0; |
| 13154 | char *zRet = 0; |
| 13155 | int nIn = zIn ? STRLEN(zIn) : 0; |
| 13156 | int nAppend = 0; |
| 13157 | va_start(ap, zFmt); |
| 13158 | if( *pRc==SQLITE_OK ){ |
| 13159 | zAppend = sqlite3_vmprintf(zFmt, ap); |
| 13160 | if( zAppend ){ |
| 13161 | nAppend = STRLEN(zAppend); |
| 13162 | zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); |
| 13163 | } |
| 13164 | if( zAppend && zRet ){ |
| 13165 | if( nIn ) memcpy(zRet, zIn, nIn); |
| 13166 | memcpy(&zRet[nIn], zAppend, nAppend+1); |
| 13167 | }else{ |
| @@ -13921,12 +13930,12 @@ | |
| 13921 | int nSlot; |
| 13922 | struct IdxRemSlot { |
| 13923 | int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ |
| 13924 | i64 iVal; /* SQLITE_INTEGER value */ |
| 13925 | double rVal; /* SQLITE_FLOAT value */ |
| 13926 | int nByte; /* Bytes of space allocated at z */ |
| 13927 | int n; /* Size of buffer z */ |
| 13928 | char *z; /* SQLITE_TEXT/BLOB value */ |
| 13929 | } aSlot[1]; |
| 13930 | }; |
| 13931 | |
| 13932 | /* |
| @@ -13958,15 +13967,17 @@ | |
| 13958 | case SQLITE_FLOAT: |
| 13959 | sqlite3_result_double(pCtx, pSlot->rVal); |
| 13960 | break; |
| 13961 | |
| 13962 | case SQLITE_BLOB: |
| 13963 | sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); |
| 13964 | break; |
| 13965 | |
| 13966 | case SQLITE_TEXT: |
| 13967 | sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); |
| 13968 | break; |
| 13969 | } |
| 13970 | |
| 13971 | pSlot->eType = sqlite3_value_type(argv[1]); |
| 13972 | switch( pSlot->eType ){ |
| @@ -13982,14 +13993,14 @@ | |
| 13982 | pSlot->rVal = sqlite3_value_double(argv[1]); |
| 13983 | break; |
| 13984 | |
| 13985 | case SQLITE_BLOB: |
| 13986 | case SQLITE_TEXT: { |
| 13987 | int nByte = sqlite3_value_bytes(argv[1]); |
| 13988 | const void *pData = 0; |
| 13989 | if( nByte>pSlot->nByte ){ |
| 13990 | char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); |
| 13991 | if( zNew==0 ){ |
| 13992 | sqlite3_result_error_nomem(pCtx); |
| 13993 | return; |
| 13994 | } |
| 13995 | pSlot->nByte = nByte*2; |
| @@ -14040,11 +14051,11 @@ | |
| 14040 | char *zOrder = 0; |
| 14041 | char *zQuery = 0; |
| 14042 | int nCol = 0; |
| 14043 | int i; |
| 14044 | sqlite3_stmt *pQuery = 0; |
| 14045 | int *aStat = 0; |
| 14046 | int rc = SQLITE_OK; |
| 14047 | |
| 14048 | assert( p->iSample>0 ); |
| 14049 | |
| 14050 | /* Formulate the query text */ |
| @@ -14086,11 +14097,11 @@ | |
| 14086 | rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); |
| 14087 | } |
| 14088 | sqlite3_free(zQuery); |
| 14089 | |
| 14090 | if( rc==SQLITE_OK ){ |
| 14091 | aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); |
| 14092 | } |
| 14093 | if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ |
| 14094 | IdxHashEntry *pEntry; |
| 14095 | char *zStat = 0; |
| 14096 | for(i=0; i<=nCol; i++) aStat[i] = 1; |
| @@ -14103,15 +14114,15 @@ | |
| 14103 | aStat[i+1]++; |
| 14104 | } |
| 14105 | } |
| 14106 | |
| 14107 | if( rc==SQLITE_OK ){ |
| 14108 | int s0 = aStat[0]; |
| 14109 | zStat = sqlite3_mprintf("%d", s0); |
| 14110 | if( zStat==0 ) rc = SQLITE_NOMEM; |
| 14111 | for(i=1; rc==SQLITE_OK && i<=nCol; i++){ |
| 14112 | zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]); |
| 14113 | } |
| 14114 | } |
| 14115 | |
| 14116 | if( rc==SQLITE_OK ){ |
| 14117 | sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); |
| @@ -14186,11 +14197,11 @@ | |
| 14186 | if( nMax<=0 || rc!=SQLITE_OK ) return rc; |
| 14187 | |
| 14188 | rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); |
| 14189 | |
| 14190 | if( rc==SQLITE_OK ){ |
| 14191 | int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); |
| 14192 | pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); |
| 14193 | } |
| 14194 | |
| 14195 | if( rc==SQLITE_OK ){ |
| 14196 | sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); |
| @@ -14203,11 +14214,11 @@ | |
| 14203 | 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 |
| 14204 | ); |
| 14205 | } |
| 14206 | |
| 14207 | if( rc==SQLITE_OK ){ |
| 14208 | pCtx->nSlot = nMax+1; |
| 14209 | rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); |
| 14210 | } |
| 14211 | if( rc==SQLITE_OK ){ |
| 14212 | rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); |
| 14213 | } |
| @@ -14470,11 +14481,11 @@ | |
| 14470 | rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); |
| 14471 | if( rc==SQLITE_OK ){ |
| 14472 | if( pStmt ){ |
| 14473 | IdxStatement *pNew; |
| 14474 | const char *z = sqlite3_sql(pStmt); |
| 14475 | int n = STRLEN(z); |
| 14476 | pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); |
| 14477 | if( rc==SQLITE_OK ){ |
| 14478 | pNew->zSql = (char*)&pNew[1]; |
| 14479 | memcpy(pNew->zSql, z, n+1); |
| 14480 | pNew->pNext = p->pStatement; |
| @@ -21295,11 +21306,11 @@ | |
| 21295 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 21296 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 21297 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 21298 | int outCount; /* Revert to stdout when reaching zero */ |
| 21299 | int cnt; /* Number of records displayed so far */ |
| 21300 | int lineno; /* Line number of last line read from in */ |
| 21301 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 21302 | FILE *in; /* Read commands from this stream */ |
| 21303 | FILE *out; /* Write results here */ |
| 21304 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 21305 | int nErr; /* Number of errors seen */ |
| @@ -21531,11 +21542,11 @@ | |
| 21531 | va_list ap; |
| 21532 | char *zMsg; |
| 21533 | va_start(ap, zErrMsg); |
| 21534 | zMsg = sqlite3_vmprintf(zErrMsg, ap); |
| 21535 | va_end(ap); |
| 21536 | sqlite3_fprintf(stderr, "line %d: %s\n", p->lineno, zMsg); |
| 21537 | exit(1); |
| 21538 | } |
| 21539 | } |
| 21540 | |
| 21541 | /* |
| @@ -25087,10 +25098,11 @@ | |
| 25087 | " --ifexist Only open if FILE already exists", |
| 25088 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25089 | " --maxsize N Maximum size for --hexdb or --deserialized database", |
| 25090 | #endif |
| 25091 | " --new Initialize FILE to an empty database", |
| 25092 | " --nofollow Do not follow symbolic links", |
| 25093 | " --readonly Open FILE readonly", |
| 25094 | " --zip FILE is a ZIP archive", |
| 25095 | #ifndef SQLITE_SHELL_FIDDLE |
| 25096 | ".output ?FILE? Send output to FILE or stdout if FILE is omitted", |
| @@ -25321,11 +25333,11 @@ | |
| 25321 | sqlite3_free(zPat); |
| 25322 | return n; |
| 25323 | } |
| 25324 | |
| 25325 | /* Forward reference */ |
| 25326 | static int process_input(ShellState *p); |
| 25327 | |
| 25328 | /* |
| 25329 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 25330 | ** and return a pointer to the buffer. The caller is responsible for freeing |
| 25331 | ** the memory. |
| @@ -25428,22 +25440,30 @@ | |
| 25428 | ** If the file does not exist or is empty but its name looks like a ZIP |
| 25429 | ** archive and the dfltZip flag is true, then assume it is a ZIP archive. |
| 25430 | ** Otherwise, assume an ordinary database regardless of the filename if |
| 25431 | ** the type cannot be determined from content. |
| 25432 | */ |
| 25433 | int deduceDatabaseType(const char *zName, int dfltZip){ |
| 25434 | FILE *f = sqlite3_fopen(zName, "rb"); |
| 25435 | size_t n; |
| 25436 | int rc = SHELL_OPEN_UNSPEC; |
| 25437 | char zBuf[100]; |
| 25438 | if( f==0 ){ |
| 25439 | if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ |
| 25440 | return SHELL_OPEN_ZIPFILE; |
| 25441 | }else{ |
| 25442 | return SHELL_OPEN_NORMAL; |
| 25443 | } |
| 25444 | } |
| 25445 | n = fread(zBuf, 16, 1, f); |
| 25446 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| 25447 | fclose(f); |
| 25448 | return SHELL_OPEN_NORMAL; |
| 25449 | } |
| @@ -25461,10 +25481,18 @@ | |
| 25461 | rc = SHELL_OPEN_ZIPFILE; |
| 25462 | } |
| 25463 | } |
| 25464 | fclose(f); |
| 25465 | return rc; |
| 25466 | } |
| 25467 | |
| 25468 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25469 | /* |
| 25470 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| @@ -25471,11 +25499,11 @@ | |
| 25471 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| 25472 | ** If p->aAuxDb[].zDbFilename is 0, then read from standard input. |
| 25473 | */ |
| 25474 | static unsigned char *readHexDb(ShellState *p, int *pnData){ |
| 25475 | unsigned char *a = 0; |
| 25476 | int nLine; |
| 25477 | int n = 0; /* Size of db per first line of hex dump */ |
| 25478 | i64 sz = 0; /* n rounded up to nearest page boundary */ |
| 25479 | int pgsz = 0; |
| 25480 | i64 iOffset = 0; |
| 25481 | int rc; |
| @@ -25510,10 +25538,14 @@ | |
| 25510 | shell_check_oom(a); |
| 25511 | memset(a, 0, sz); |
| 25512 | for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){ |
| 25513 | int j = 0; /* Page number from "| page" line */ |
| 25514 | int k = 0; /* Offset from "| page" line */ |
| 25515 | rc = sscanf(zLine, "| page %d offset %d", &j, &k); |
| 25516 | if( rc==2 ){ |
| 25517 | iOffset = k; |
| 25518 | continue; |
| 25519 | } |
| @@ -25548,11 +25580,11 @@ | |
| 25548 | if(cli_strncmp(zLine, "| end ", 6)==0 ) break; |
| 25549 | } |
| 25550 | p->lineno = nLine; |
| 25551 | } |
| 25552 | sqlite3_free(a); |
| 25553 | sqlite3_fprintf(stderr,"Error on line %d of --hexdb input\n", nLine); |
| 25554 | return 0; |
| 25555 | } |
| 25556 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 25557 | |
| 25558 | /* |
| @@ -25625,11 +25657,11 @@ | |
| 25625 | if( p->openMode==SHELL_OPEN_UNSPEC ){ |
| 25626 | if( zDbFilename==0 || zDbFilename[0]==0 ){ |
| 25627 | p->openMode = SHELL_OPEN_NORMAL; |
| 25628 | }else{ |
| 25629 | p->openMode = (u8)deduceDatabaseType(zDbFilename, |
| 25630 | (openFlags & OPEN_DB_ZIPFILE)!=0); |
| 25631 | } |
| 25632 | } |
| 25633 | if( (p->openFlags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE))==0 ){ |
| 25634 | if( p->openFlags==0 ) p->openFlags = SQLITE_OPEN_CREATE; |
| 25635 | p->openFlags |= SQLITE_OPEN_READWRITE; |
| @@ -27652,29 +27684,45 @@ | |
| 27652 | int *pRc, |
| 27653 | ArCommand *pAr, |
| 27654 | char **pzWhere /* OUT: New WHERE clause */ |
| 27655 | ){ |
| 27656 | char *zWhere = 0; |
| 27657 | const char *zSameOp = (pAr->bGlob)? "GLOB" : "="; |
| 27658 | if( *pRc==SQLITE_OK ){ |
| 27659 | if( pAr->nArg==0 ){ |
| 27660 | zWhere = sqlite3_mprintf("1"); |
| 27661 | }else{ |
| 27662 | int i; |
| 27663 | const char *zSep = ""; |
| 27664 | for(i=0; i<pAr->nArg; i++){ |
| 27665 | const char *z = pAr->azArg[i]; |
| 27666 | zWhere = sqlite3_mprintf( |
| 27667 | "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'", |
| 27668 | zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z |
| 27669 | ); |
| 27670 | if( zWhere==0 ){ |
| 27671 | *pRc = SQLITE_NOMEM; |
| 27672 | break; |
| 27673 | } |
| 27674 | zSep = " OR "; |
| 27675 | } |
| 27676 | } |
| 27677 | } |
| 27678 | *pzWhere = zWhere; |
| 27679 | } |
| 27680 | |
| @@ -27990,11 +28038,11 @@ | |
| 27990 | int eDbType = SHELL_OPEN_UNSPEC; |
| 27991 | cmd.p = pState; |
| 27992 | cmd.out = pState->out; |
| 27993 | cmd.db = pState->db; |
| 27994 | if( cmd.zFile ){ |
| 27995 | eDbType = deduceDatabaseType(cmd.zFile, 1); |
| 27996 | }else{ |
| 27997 | eDbType = pState->openMode; |
| 27998 | } |
| 27999 | if( eDbType==SHELL_OPEN_ZIPFILE ){ |
| 28000 | if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ |
| @@ -29312,11 +29360,11 @@ | |
| 29312 | int nSep; /* Number of bytes in p->colSeparator[] */ |
| 29313 | char *zSql = 0; /* An SQL statement */ |
| 29314 | ImportCtx sCtx; /* Reader context */ |
| 29315 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 29316 | int eVerbose = 0; /* Larger for more console output */ |
| 29317 | int nSkip = 0; /* Initial lines to skip */ |
| 29318 | int useOutputMode = 1; /* Use output mode to determine separators */ |
| 29319 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 29320 | |
| 29321 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 29322 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30037,11 +30085,11 @@ | |
| 30037 | if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){ |
| 30038 | if( nArg!=2 ){ |
| 30039 | eputz("Usage: .nonce NONCE\n"); |
| 30040 | rc = 1; |
| 30041 | }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){ |
| 30042 | sqlite3_fprintf(stderr,"line %d: incorrect nonce: \"%s\"\n", |
| 30043 | p->lineno, azArg[1]); |
| 30044 | exit(1); |
| 30045 | }else{ |
| 30046 | p->bSafeMode = 0; |
| 30047 | return 0; /* Return immediately to bypass the safe mode reset |
| @@ -30092,10 +30140,12 @@ | |
| 30092 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 30093 | }else if( optionMatch(z, "deserialize") ){ |
| 30094 | openMode = SHELL_OPEN_DESERIALIZE; |
| 30095 | }else if( optionMatch(z, "hexdb") ){ |
| 30096 | openMode = SHELL_OPEN_HEXDB; |
| 30097 | }else if( optionMatch(z, "maxsize") && iName+1<nArg ){ |
| 30098 | p->szMax = integerValue(azArg[++iName]); |
| 30099 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 30100 | }else |
| 30101 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -30210,10 +30260,11 @@ | |
| 30210 | }else{ |
| 30211 | sqlite3_fprintf(p->out, |
| 30212 | "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); |
| 30213 | showHelp(p->out, azArg[0]); |
| 30214 | rc = 1; |
| 30215 | goto meta_command_exit; |
| 30216 | } |
| 30217 | }else if( zFile==0 && eMode==0 ){ |
| 30218 | if( cli_strcmp(z, "off")==0 ){ |
| 30219 | #ifdef _WIN32 |
| @@ -30493,11 +30544,11 @@ | |
| 30493 | #endif |
| 30494 | |
| 30495 | #ifndef SQLITE_SHELL_FIDDLE |
| 30496 | if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){ |
| 30497 | FILE *inSaved = p->in; |
| 30498 | int savedLineno = p->lineno; |
| 30499 | failIfSafeMode(p, "cannot run .read in safe mode"); |
| 30500 | if( nArg!=2 ){ |
| 30501 | eputz("Usage: .read FILE\n"); |
| 30502 | rc = 1; |
| 30503 | goto meta_command_exit; |
| @@ -30510,19 +30561,19 @@ | |
| 30510 | p->in = sqlite3_popen(azArg[1]+1, "r"); |
| 30511 | if( p->in==0 ){ |
| 30512 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30513 | rc = 1; |
| 30514 | }else{ |
| 30515 | rc = process_input(p); |
| 30516 | pclose(p->in); |
| 30517 | } |
| 30518 | #endif |
| 30519 | }else if( (p->in = openChrSource(azArg[1]))==0 ){ |
| 30520 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30521 | rc = 1; |
| 30522 | }else{ |
| 30523 | rc = process_input(p); |
| 30524 | fclose(p->in); |
| 30525 | } |
| 30526 | p->in = inSaved; |
| 30527 | p->lineno = savedLineno; |
| 30528 | }else |
| @@ -32509,11 +32560,11 @@ | |
| 32509 | ** is saved only if input is interactive. An interrupt signal will |
| 32510 | ** cause this routine to exit immediately, unless input is interactive. |
| 32511 | ** |
| 32512 | ** Return the number of errors. |
| 32513 | */ |
| 32514 | static int process_input(ShellState *p){ |
| 32515 | char *zLine = 0; /* A single input line */ |
| 32516 | char *zSql = 0; /* Accumulated SQL text */ |
| 32517 | i64 nLine; /* Length of current line */ |
| 32518 | i64 nSql = 0; /* Bytes of zSql[] used */ |
| 32519 | i64 nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -32522,12 +32573,12 @@ | |
| 32522 | i64 startline = 0; /* Line number for start of current input */ |
| 32523 | QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ |
| 32524 | |
| 32525 | if( p->inputNesting==MAX_INPUT_NESTING ){ |
| 32526 | /* This will be more informative in a later version. */ |
| 32527 | sqlite3_fprintf(stderr,"Input nesting limit (%d) reached at line %d." |
| 32528 | " Check recursion.\n", MAX_INPUT_NESTING, p->lineno); |
| 32529 | return 1; |
| 32530 | } |
| 32531 | ++p->inputNesting; |
| 32532 | p->lineno = 0; |
| 32533 | CONTINUE_PROMPT_RESET; |
| @@ -32588,11 +32639,19 @@ | |
| 32588 | }else{ |
| 32589 | zSql[nSql++] = '\n'; |
| 32590 | memcpy(zSql+nSql, zLine, nLine+1); |
| 32591 | nSql += nLine; |
| 32592 | } |
| 32593 | if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ |
| 32594 | echo_group_input(p, zSql); |
| 32595 | errCnt += runOneSqlLine(p, zSql, p->in, startline); |
| 32596 | CONTINUE_PROMPT_RESET; |
| 32597 | nSql = 0; |
| 32598 | if( p->outCount ){ |
| @@ -32756,11 +32815,11 @@ | |
| 32756 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 32757 | ){ |
| 32758 | char *home_dir = NULL; |
| 32759 | char *sqliterc = (char*)sqliterc_override; |
| 32760 | FILE *inSaved = p->in; |
| 32761 | int savedLineno = p->lineno; |
| 32762 | |
| 32763 | if( sqliterc == NULL ){ |
| 32764 | sqliterc = find_xdg_file("XDG_CONFIG_HOME", |
| 32765 | ".config", |
| 32766 | "sqlite3/sqliterc"); |
| @@ -32778,11 +32837,11 @@ | |
| 32778 | p->in = sqliterc ? sqlite3_fopen(sqliterc,"rb") : 0; |
| 32779 | if( p->in ){ |
| 32780 | if( stdin_is_interactive ){ |
| 32781 | sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc); |
| 32782 | } |
| 32783 | if( process_input(p) && bail_on_error ) exit(1); |
| 32784 | fclose(p->in); |
| 32785 | }else if( sqliterc_override!=0 ){ |
| 32786 | sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc); |
| 32787 | if( bail_on_error ) exit(1); |
| 32788 | } |
| @@ -33609,19 +33668,19 @@ | |
| 33609 | linenoiseSetCompletionCallback(linenoise_completion); |
| 33610 | #elif HAVE_LINENOISE==2 |
| 33611 | linenoiseSetCompletionCallback(linenoise_completion, NULL); |
| 33612 | #endif |
| 33613 | data.in = 0; |
| 33614 | rc = process_input(&data); |
| 33615 | if( zHistory ){ |
| 33616 | shell_stifle_history(2000); |
| 33617 | shell_write_history(zHistory); |
| 33618 | sqlite3_free(zHistory); |
| 33619 | } |
| 33620 | }else{ |
| 33621 | data.in = stdin; |
| 33622 | rc = process_input(&data); |
| 33623 | } |
| 33624 | } |
| 33625 | #ifndef SQLITE_SHELL_FIDDLE |
| 33626 | /* In WASM mode we have to leave the db state in place so that |
| 33627 | ** client code can "push" SQL into it after this call returns. */ |
| @@ -33799,10 +33858,10 @@ | |
| 33799 | void fiddle_exec(const char * zSql){ |
| 33800 | if(zSql && *zSql){ |
| 33801 | if('.'==*zSql) puts(zSql); |
| 33802 | shellState.wasm.zInput = zSql; |
| 33803 | shellState.wasm.zPos = zSql; |
| 33804 | process_input(&shellState); |
| 33805 | shellState.wasm.zInput = shellState.wasm.zPos = 0; |
| 33806 | } |
| 33807 | } |
| 33808 | #endif /* SQLITE_SHELL_FIDDLE */ |
| 33809 |
| --- extsrc/shell.c | |
| +++ extsrc/shell.c | |
| @@ -7182,10 +7182,19 @@ | |
| 7182 | sqlite3_free(pRe->aOp); |
| 7183 | sqlite3_free(pRe->aArg); |
| 7184 | sqlite3_free(pRe); |
| 7185 | } |
| 7186 | } |
| 7187 | |
| 7188 | /* |
| 7189 | ** Version of re_free() that accepts a pointer of type (void*). Required |
| 7190 | ** to satisfy sanitizers when the re_free() function is called via a |
| 7191 | ** function pointer. |
| 7192 | */ |
| 7193 | static void re_free_voidptr(void *p){ |
| 7194 | re_free((ReCompiled*)p); |
| 7195 | } |
| 7196 | |
| 7197 | /* |
| 7198 | ** Compile a textual regular expression in zIn[] into a compiled regular |
| 7199 | ** expression suitable for us by re_match() and return a pointer to the |
| 7200 | ** compiled regular expression in *ppRe. Return NULL on success or an |
| @@ -7314,11 +7323,11 @@ | |
| 7323 | zStr = (const unsigned char*)sqlite3_value_text(argv[1]); |
| 7324 | if( zStr!=0 ){ |
| 7325 | sqlite3_result_int(context, re_match(pRe, zStr, -1)); |
| 7326 | } |
| 7327 | if( setAux ){ |
| 7328 | sqlite3_set_auxdata(context, 0, pRe, re_free_voidptr); |
| 7329 | } |
| 7330 | } |
| 7331 | |
| 7332 | #if defined(SQLITE_DEBUG) |
| 7333 | /* |
| @@ -8202,11 +8211,11 @@ | |
| 8211 | |
| 8212 | pLvl->zDir = pCur->zPath; |
| 8213 | pCur->zPath = 0; |
| 8214 | pLvl->pDir = opendir(pLvl->zDir); |
| 8215 | if( pLvl->pDir==0 ){ |
| 8216 | fsdirSetErrmsg(pCur, "cannot read directory: %s", pLvl->zDir); |
| 8217 | return SQLITE_ERROR; |
| 8218 | } |
| 8219 | } |
| 8220 | |
| 8221 | while( pCur->iLvl>=0 ){ |
| @@ -12531,15 +12540,15 @@ | |
| 12540 | |
| 12541 | /* |
| 12542 | ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). |
| 12543 | ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. |
| 12544 | */ |
| 12545 | static void *idxMalloc(int *pRc, i64 nByte){ |
| 12546 | void *pRet; |
| 12547 | assert( *pRc==SQLITE_OK ); |
| 12548 | assert( nByte>0 ); |
| 12549 | pRet = sqlite3_malloc64(nByte); |
| 12550 | if( pRet ){ |
| 12551 | memset(pRet, 0, nByte); |
| 12552 | }else{ |
| 12553 | *pRc = SQLITE_NOMEM; |
| 12554 | } |
| @@ -12602,11 +12611,11 @@ | |
| 12611 | for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ |
| 12612 | if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ |
| 12613 | return 1; |
| 12614 | } |
| 12615 | } |
| 12616 | pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1); |
| 12617 | if( pEntry ){ |
| 12618 | pEntry->zKey = (char*)&pEntry[1]; |
| 12619 | memcpy(pEntry->zKey, zKey, nKey); |
| 12620 | if( zVal ){ |
| 12621 | pEntry->zVal = &pEntry->zKey[nKey+1]; |
| @@ -12737,19 +12746,19 @@ | |
| 12746 | sqlite3_vtab_cursor base; |
| 12747 | sqlite3_stmt *pData; |
| 12748 | }; |
| 12749 | |
| 12750 | static char *expertDequote(const char *zIn){ |
| 12751 | i64 n = STRLEN(zIn); |
| 12752 | char *zRet = sqlite3_malloc64(n); |
| 12753 | |
| 12754 | assert( zIn[0]=='\'' ); |
| 12755 | assert( zIn[n-1]=='\'' ); |
| 12756 | |
| 12757 | if( zRet ){ |
| 12758 | i64 iOut = 0; |
| 12759 | i64 iIn = 0; |
| 12760 | for(iIn=1; iIn<(n-1); iIn++){ |
| 12761 | if( zIn[iIn]=='\'' ){ |
| 12762 | assert( zIn[iIn+1]=='\'' ); |
| 12763 | iIn++; |
| 12764 | } |
| @@ -13058,11 +13067,11 @@ | |
| 13067 | char **pzErrmsg /* OUT: Error message (if not) */ |
| 13068 | ){ |
| 13069 | sqlite3_stmt *p1 = 0; |
| 13070 | int nCol = 0; |
| 13071 | int nTab; |
| 13072 | i64 nByte; |
| 13073 | IdxTable *pNew = 0; |
| 13074 | int rc, rc2; |
| 13075 | char *pCsr = 0; |
| 13076 | int nPk = 0; |
| 13077 | |
| @@ -13150,18 +13159,18 @@ | |
| 13159 | */ |
| 13160 | static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ |
| 13161 | va_list ap; |
| 13162 | char *zAppend = 0; |
| 13163 | char *zRet = 0; |
| 13164 | i64 nIn = zIn ? STRLEN(zIn) : 0; |
| 13165 | i64 nAppend = 0; |
| 13166 | va_start(ap, zFmt); |
| 13167 | if( *pRc==SQLITE_OK ){ |
| 13168 | zAppend = sqlite3_vmprintf(zFmt, ap); |
| 13169 | if( zAppend ){ |
| 13170 | nAppend = STRLEN(zAppend); |
| 13171 | zRet = (char*)sqlite3_malloc64(nIn + nAppend + 1); |
| 13172 | } |
| 13173 | if( zAppend && zRet ){ |
| 13174 | if( nIn ) memcpy(zRet, zIn, nIn); |
| 13175 | memcpy(&zRet[nIn], zAppend, nAppend+1); |
| 13176 | }else{ |
| @@ -13921,12 +13930,12 @@ | |
| 13930 | int nSlot; |
| 13931 | struct IdxRemSlot { |
| 13932 | int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ |
| 13933 | i64 iVal; /* SQLITE_INTEGER value */ |
| 13934 | double rVal; /* SQLITE_FLOAT value */ |
| 13935 | i64 nByte; /* Bytes of space allocated at z */ |
| 13936 | i64 n; /* Size of buffer z */ |
| 13937 | char *z; /* SQLITE_TEXT/BLOB value */ |
| 13938 | } aSlot[1]; |
| 13939 | }; |
| 13940 | |
| 13941 | /* |
| @@ -13958,15 +13967,17 @@ | |
| 13967 | case SQLITE_FLOAT: |
| 13968 | sqlite3_result_double(pCtx, pSlot->rVal); |
| 13969 | break; |
| 13970 | |
| 13971 | case SQLITE_BLOB: |
| 13972 | assert( pSlot->n <= 0x7fffffff ); |
| 13973 | sqlite3_result_blob(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT); |
| 13974 | break; |
| 13975 | |
| 13976 | case SQLITE_TEXT: |
| 13977 | assert( pSlot->n <= 0x7fffffff ); |
| 13978 | sqlite3_result_text(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT); |
| 13979 | break; |
| 13980 | } |
| 13981 | |
| 13982 | pSlot->eType = sqlite3_value_type(argv[1]); |
| 13983 | switch( pSlot->eType ){ |
| @@ -13982,14 +13993,14 @@ | |
| 13993 | pSlot->rVal = sqlite3_value_double(argv[1]); |
| 13994 | break; |
| 13995 | |
| 13996 | case SQLITE_BLOB: |
| 13997 | case SQLITE_TEXT: { |
| 13998 | i64 nByte = sqlite3_value_bytes(argv[1]); |
| 13999 | const void *pData = 0; |
| 14000 | if( nByte>pSlot->nByte ){ |
| 14001 | char *zNew = (char*)sqlite3_realloc64(pSlot->z, nByte*2); |
| 14002 | if( zNew==0 ){ |
| 14003 | sqlite3_result_error_nomem(pCtx); |
| 14004 | return; |
| 14005 | } |
| 14006 | pSlot->nByte = nByte*2; |
| @@ -14040,11 +14051,11 @@ | |
| 14051 | char *zOrder = 0; |
| 14052 | char *zQuery = 0; |
| 14053 | int nCol = 0; |
| 14054 | int i; |
| 14055 | sqlite3_stmt *pQuery = 0; |
| 14056 | i64 *aStat = 0; |
| 14057 | int rc = SQLITE_OK; |
| 14058 | |
| 14059 | assert( p->iSample>0 ); |
| 14060 | |
| 14061 | /* Formulate the query text */ |
| @@ -14086,11 +14097,11 @@ | |
| 14097 | rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); |
| 14098 | } |
| 14099 | sqlite3_free(zQuery); |
| 14100 | |
| 14101 | if( rc==SQLITE_OK ){ |
| 14102 | aStat = (i64*)idxMalloc(&rc, sizeof(i64)*(nCol+1)); |
| 14103 | } |
| 14104 | if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ |
| 14105 | IdxHashEntry *pEntry; |
| 14106 | char *zStat = 0; |
| 14107 | for(i=0; i<=nCol; i++) aStat[i] = 1; |
| @@ -14103,15 +14114,15 @@ | |
| 14114 | aStat[i+1]++; |
| 14115 | } |
| 14116 | } |
| 14117 | |
| 14118 | if( rc==SQLITE_OK ){ |
| 14119 | i64 s0 = aStat[0]; |
| 14120 | zStat = sqlite3_mprintf("%lld", s0); |
| 14121 | if( zStat==0 ) rc = SQLITE_NOMEM; |
| 14122 | for(i=1; rc==SQLITE_OK && i<=nCol; i++){ |
| 14123 | zStat = idxAppendText(&rc, zStat, " %lld", (s0+aStat[i]/2) / aStat[i]); |
| 14124 | } |
| 14125 | } |
| 14126 | |
| 14127 | if( rc==SQLITE_OK ){ |
| 14128 | sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); |
| @@ -14186,11 +14197,11 @@ | |
| 14197 | if( nMax<=0 || rc!=SQLITE_OK ) return rc; |
| 14198 | |
| 14199 | rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); |
| 14200 | |
| 14201 | if( rc==SQLITE_OK ){ |
| 14202 | i64 nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); |
| 14203 | pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); |
| 14204 | } |
| 14205 | |
| 14206 | if( rc==SQLITE_OK ){ |
| 14207 | sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); |
| @@ -14203,11 +14214,11 @@ | |
| 14214 | 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 |
| 14215 | ); |
| 14216 | } |
| 14217 | |
| 14218 | if( rc==SQLITE_OK ){ |
| 14219 | pCtx->nSlot = (i64)nMax+1; |
| 14220 | rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); |
| 14221 | } |
| 14222 | if( rc==SQLITE_OK ){ |
| 14223 | rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); |
| 14224 | } |
| @@ -14470,11 +14481,11 @@ | |
| 14481 | rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); |
| 14482 | if( rc==SQLITE_OK ){ |
| 14483 | if( pStmt ){ |
| 14484 | IdxStatement *pNew; |
| 14485 | const char *z = sqlite3_sql(pStmt); |
| 14486 | i64 n = STRLEN(z); |
| 14487 | pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); |
| 14488 | if( rc==SQLITE_OK ){ |
| 14489 | pNew->zSql = (char*)&pNew[1]; |
| 14490 | memcpy(pNew->zSql, z, n+1); |
| 14491 | pNew->pNext = p->pStatement; |
| @@ -21295,11 +21306,11 @@ | |
| 21306 | unsigned statsOn; /* True to display memory stats before each finalize */ |
| 21307 | unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */ |
| 21308 | int inputNesting; /* Track nesting level of .read and other redirects */ |
| 21309 | int outCount; /* Revert to stdout when reaching zero */ |
| 21310 | int cnt; /* Number of records displayed so far */ |
| 21311 | i64 lineno; /* Line number of last line read from in */ |
| 21312 | int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ |
| 21313 | FILE *in; /* Read commands from this stream */ |
| 21314 | FILE *out; /* Write results here */ |
| 21315 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 21316 | int nErr; /* Number of errors seen */ |
| @@ -21531,11 +21542,11 @@ | |
| 21542 | va_list ap; |
| 21543 | char *zMsg; |
| 21544 | va_start(ap, zErrMsg); |
| 21545 | zMsg = sqlite3_vmprintf(zErrMsg, ap); |
| 21546 | va_end(ap); |
| 21547 | sqlite3_fprintf(stderr, "line %lld: %s\n", p->lineno, zMsg); |
| 21548 | exit(1); |
| 21549 | } |
| 21550 | } |
| 21551 | |
| 21552 | /* |
| @@ -25087,10 +25098,11 @@ | |
| 25098 | " --ifexist Only open if FILE already exists", |
| 25099 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25100 | " --maxsize N Maximum size for --hexdb or --deserialized database", |
| 25101 | #endif |
| 25102 | " --new Initialize FILE to an empty database", |
| 25103 | " --normal FILE is an ordinary SQLite database", |
| 25104 | " --nofollow Do not follow symbolic links", |
| 25105 | " --readonly Open FILE readonly", |
| 25106 | " --zip FILE is a ZIP archive", |
| 25107 | #ifndef SQLITE_SHELL_FIDDLE |
| 25108 | ".output ?FILE? Send output to FILE or stdout if FILE is omitted", |
| @@ -25321,11 +25333,11 @@ | |
| 25333 | sqlite3_free(zPat); |
| 25334 | return n; |
| 25335 | } |
| 25336 | |
| 25337 | /* Forward reference */ |
| 25338 | static int process_input(ShellState *p, const char*); |
| 25339 | |
| 25340 | /* |
| 25341 | ** Read the content of file zName into memory obtained from sqlite3_malloc64() |
| 25342 | ** and return a pointer to the buffer. The caller is responsible for freeing |
| 25343 | ** the memory. |
| @@ -25428,22 +25440,30 @@ | |
| 25440 | ** If the file does not exist or is empty but its name looks like a ZIP |
| 25441 | ** archive and the dfltZip flag is true, then assume it is a ZIP archive. |
| 25442 | ** Otherwise, assume an ordinary database regardless of the filename if |
| 25443 | ** the type cannot be determined from content. |
| 25444 | */ |
| 25445 | int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){ |
| 25446 | FILE *f; |
| 25447 | size_t n; |
| 25448 | sqlite3 *db = 0; |
| 25449 | sqlite3_stmt *pStmt = 0; |
| 25450 | int rc = SHELL_OPEN_UNSPEC; |
| 25451 | char zBuf[100]; |
| 25452 | if( access(zName,0)!=0 ) goto database_type_by_name; |
| 25453 | if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK |
| 25454 | && sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0) |
| 25455 | ==SQLITE_OK |
| 25456 | && sqlite3_step(pStmt)==SQLITE_ROW |
| 25457 | ){ |
| 25458 | rc = SHELL_OPEN_NORMAL; |
| 25459 | } |
| 25460 | sqlite3_finalize(pStmt); |
| 25461 | sqlite3_close(db); |
| 25462 | if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL; |
| 25463 | f = sqlite3_fopen(zName, "rb"); |
| 25464 | if( f==0 ) goto database_type_by_name; |
| 25465 | n = fread(zBuf, 16, 1, f); |
| 25466 | if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ |
| 25467 | fclose(f); |
| 25468 | return SHELL_OPEN_NORMAL; |
| 25469 | } |
| @@ -25461,10 +25481,18 @@ | |
| 25481 | rc = SHELL_OPEN_ZIPFILE; |
| 25482 | } |
| 25483 | } |
| 25484 | fclose(f); |
| 25485 | return rc; |
| 25486 | |
| 25487 | database_type_by_name: |
| 25488 | if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ |
| 25489 | rc = SHELL_OPEN_ZIPFILE; |
| 25490 | }else{ |
| 25491 | rc = SHELL_OPEN_NORMAL; |
| 25492 | } |
| 25493 | return rc; |
| 25494 | } |
| 25495 | |
| 25496 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 25497 | /* |
| 25498 | ** Reconstruct an in-memory database using the output from the "dbtotxt" |
| @@ -25471,11 +25499,11 @@ | |
| 25499 | ** program. Read content from the file in p->aAuxDb[].zDbFilename. |
| 25500 | ** If p->aAuxDb[].zDbFilename is 0, then read from standard input. |
| 25501 | */ |
| 25502 | static unsigned char *readHexDb(ShellState *p, int *pnData){ |
| 25503 | unsigned char *a = 0; |
| 25504 | i64 nLine; |
| 25505 | int n = 0; /* Size of db per first line of hex dump */ |
| 25506 | i64 sz = 0; /* n rounded up to nearest page boundary */ |
| 25507 | int pgsz = 0; |
| 25508 | i64 iOffset = 0; |
| 25509 | int rc; |
| @@ -25510,10 +25538,14 @@ | |
| 25538 | shell_check_oom(a); |
| 25539 | memset(a, 0, sz); |
| 25540 | for(nLine++; sqlite3_fgets(zLine, sizeof(zLine), in)!=0; nLine++){ |
| 25541 | int j = 0; /* Page number from "| page" line */ |
| 25542 | int k = 0; /* Offset from "| page" line */ |
| 25543 | if( nLine>=2000000000 ){ |
| 25544 | sqlite3_fprintf(stderr, "input too big\n"); |
| 25545 | goto readHexDb_error; |
| 25546 | } |
| 25547 | rc = sscanf(zLine, "| page %d offset %d", &j, &k); |
| 25548 | if( rc==2 ){ |
| 25549 | iOffset = k; |
| 25550 | continue; |
| 25551 | } |
| @@ -25548,11 +25580,11 @@ | |
| 25580 | if(cli_strncmp(zLine, "| end ", 6)==0 ) break; |
| 25581 | } |
| 25582 | p->lineno = nLine; |
| 25583 | } |
| 25584 | sqlite3_free(a); |
| 25585 | sqlite3_fprintf(stderr,"Error on line %lld of --hexdb input\n", nLine); |
| 25586 | return 0; |
| 25587 | } |
| 25588 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 25589 | |
| 25590 | /* |
| @@ -25625,11 +25657,11 @@ | |
| 25657 | if( p->openMode==SHELL_OPEN_UNSPEC ){ |
| 25658 | if( zDbFilename==0 || zDbFilename[0]==0 ){ |
| 25659 | p->openMode = SHELL_OPEN_NORMAL; |
| 25660 | }else{ |
| 25661 | p->openMode = (u8)deduceDatabaseType(zDbFilename, |
| 25662 | (openFlags & OPEN_DB_ZIPFILE)!=0, p->openFlags); |
| 25663 | } |
| 25664 | } |
| 25665 | if( (p->openFlags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE))==0 ){ |
| 25666 | if( p->openFlags==0 ) p->openFlags = SQLITE_OPEN_CREATE; |
| 25667 | p->openFlags |= SQLITE_OPEN_READWRITE; |
| @@ -27652,29 +27684,45 @@ | |
| 27684 | int *pRc, |
| 27685 | ArCommand *pAr, |
| 27686 | char **pzWhere /* OUT: New WHERE clause */ |
| 27687 | ){ |
| 27688 | char *zWhere = 0; |
| 27689 | if( *pRc==SQLITE_OK ){ |
| 27690 | if( pAr->nArg==0 ){ |
| 27691 | zWhere = sqlite3_mprintf("1"); |
| 27692 | }else{ |
| 27693 | char *z1 = sqlite3_mprintf(pAr->bGlob ? "" : "name IN("); |
| 27694 | char *z2 = sqlite3_mprintf(""); |
| 27695 | const char *zSep1 = ""; |
| 27696 | const char *zSep2 = ""; |
| 27697 | |
| 27698 | int i; |
| 27699 | for(i=0; i<pAr->nArg && z1 && z2; i++){ |
| 27700 | const char *z = pAr->azArg[i]; |
| 27701 | int n = strlen30(z); |
| 27702 | |
| 27703 | if( pAr->bGlob ){ |
| 27704 | z1 = sqlite3_mprintf("%z%sname GLOB '%q'", z1, zSep2, z); |
| 27705 | z2 = sqlite3_mprintf( |
| 27706 | "%z%ssubstr(name,1,%d) GLOB '%q/'", z2, zSep2, n+1,z |
| 27707 | ); |
| 27708 | }else{ |
| 27709 | z1 = sqlite3_mprintf("%z%s'%q'", z1, zSep1, z); |
| 27710 | z2 = sqlite3_mprintf("%z%ssubstr(name,1,%d) = '%q/'",z2,zSep2,n+1,z); |
| 27711 | } |
| 27712 | zSep1 = ", "; |
| 27713 | zSep2 = " OR "; |
| 27714 | } |
| 27715 | if( z1==0 || z2==0 ){ |
| 27716 | *pRc = SQLITE_NOMEM; |
| 27717 | }else{ |
| 27718 | zWhere = sqlite3_mprintf("(%s%s OR (name GLOB '*/*' AND (%s))) ", |
| 27719 | z1, pAr->bGlob==0 ? ")" : "", z2 |
| 27720 | ); |
| 27721 | } |
| 27722 | sqlite3_free(z1); |
| 27723 | sqlite3_free(z2); |
| 27724 | } |
| 27725 | } |
| 27726 | *pzWhere = zWhere; |
| 27727 | } |
| 27728 | |
| @@ -27990,11 +28038,11 @@ | |
| 28038 | int eDbType = SHELL_OPEN_UNSPEC; |
| 28039 | cmd.p = pState; |
| 28040 | cmd.out = pState->out; |
| 28041 | cmd.db = pState->db; |
| 28042 | if( cmd.zFile ){ |
| 28043 | eDbType = deduceDatabaseType(cmd.zFile, 1, 0); |
| 28044 | }else{ |
| 28045 | eDbType = pState->openMode; |
| 28046 | } |
| 28047 | if( eDbType==SHELL_OPEN_ZIPFILE ){ |
| 28048 | if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ |
| @@ -29312,11 +29360,11 @@ | |
| 29360 | int nSep; /* Number of bytes in p->colSeparator[] */ |
| 29361 | char *zSql = 0; /* An SQL statement */ |
| 29362 | ImportCtx sCtx; /* Reader context */ |
| 29363 | char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ |
| 29364 | int eVerbose = 0; /* Larger for more console output */ |
| 29365 | i64 nSkip = 0; /* Initial lines to skip */ |
| 29366 | int useOutputMode = 1; /* Use output mode to determine separators */ |
| 29367 | char *zCreate = 0; /* CREATE TABLE statement text */ |
| 29368 | |
| 29369 | failIfSafeMode(p, "cannot run .import in safe mode"); |
| 29370 | memset(&sCtx, 0, sizeof(sCtx)); |
| @@ -30037,11 +30085,11 @@ | |
| 30085 | if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){ |
| 30086 | if( nArg!=2 ){ |
| 30087 | eputz("Usage: .nonce NONCE\n"); |
| 30088 | rc = 1; |
| 30089 | }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){ |
| 30090 | sqlite3_fprintf(stderr,"line %lld: incorrect nonce: \"%s\"\n", |
| 30091 | p->lineno, azArg[1]); |
| 30092 | exit(1); |
| 30093 | }else{ |
| 30094 | p->bSafeMode = 0; |
| 30095 | return 0; /* Return immediately to bypass the safe mode reset |
| @@ -30092,10 +30140,12 @@ | |
| 30140 | #ifndef SQLITE_OMIT_DESERIALIZE |
| 30141 | }else if( optionMatch(z, "deserialize") ){ |
| 30142 | openMode = SHELL_OPEN_DESERIALIZE; |
| 30143 | }else if( optionMatch(z, "hexdb") ){ |
| 30144 | openMode = SHELL_OPEN_HEXDB; |
| 30145 | }else if( optionMatch(z, "normal") ){ |
| 30146 | openMode = SHELL_OPEN_NORMAL; |
| 30147 | }else if( optionMatch(z, "maxsize") && iName+1<nArg ){ |
| 30148 | p->szMax = integerValue(azArg[++iName]); |
| 30149 | #endif /* SQLITE_OMIT_DESERIALIZE */ |
| 30150 | }else |
| 30151 | #endif /* !SQLITE_SHELL_FIDDLE */ |
| @@ -30210,10 +30260,11 @@ | |
| 30260 | }else{ |
| 30261 | sqlite3_fprintf(p->out, |
| 30262 | "ERROR: unknown option: \"%s\". Usage:\n", azArg[i]); |
| 30263 | showHelp(p->out, azArg[0]); |
| 30264 | rc = 1; |
| 30265 | sqlite3_free(zFile); |
| 30266 | goto meta_command_exit; |
| 30267 | } |
| 30268 | }else if( zFile==0 && eMode==0 ){ |
| 30269 | if( cli_strcmp(z, "off")==0 ){ |
| 30270 | #ifdef _WIN32 |
| @@ -30493,11 +30544,11 @@ | |
| 30544 | #endif |
| 30545 | |
| 30546 | #ifndef SQLITE_SHELL_FIDDLE |
| 30547 | if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){ |
| 30548 | FILE *inSaved = p->in; |
| 30549 | i64 savedLineno = p->lineno; |
| 30550 | failIfSafeMode(p, "cannot run .read in safe mode"); |
| 30551 | if( nArg!=2 ){ |
| 30552 | eputz("Usage: .read FILE\n"); |
| 30553 | rc = 1; |
| 30554 | goto meta_command_exit; |
| @@ -30510,19 +30561,19 @@ | |
| 30561 | p->in = sqlite3_popen(azArg[1]+1, "r"); |
| 30562 | if( p->in==0 ){ |
| 30563 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30564 | rc = 1; |
| 30565 | }else{ |
| 30566 | rc = process_input(p, "<pipe>"); |
| 30567 | pclose(p->in); |
| 30568 | } |
| 30569 | #endif |
| 30570 | }else if( (p->in = openChrSource(azArg[1]))==0 ){ |
| 30571 | sqlite3_fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); |
| 30572 | rc = 1; |
| 30573 | }else{ |
| 30574 | rc = process_input(p, azArg[1]); |
| 30575 | fclose(p->in); |
| 30576 | } |
| 30577 | p->in = inSaved; |
| 30578 | p->lineno = savedLineno; |
| 30579 | }else |
| @@ -32509,11 +32560,11 @@ | |
| 32560 | ** is saved only if input is interactive. An interrupt signal will |
| 32561 | ** cause this routine to exit immediately, unless input is interactive. |
| 32562 | ** |
| 32563 | ** Return the number of errors. |
| 32564 | */ |
| 32565 | static int process_input(ShellState *p, const char *zSrc){ |
| 32566 | char *zLine = 0; /* A single input line */ |
| 32567 | char *zSql = 0; /* Accumulated SQL text */ |
| 32568 | i64 nLine; /* Length of current line */ |
| 32569 | i64 nSql = 0; /* Bytes of zSql[] used */ |
| 32570 | i64 nAlloc = 0; /* Allocated zSql[] space */ |
| @@ -32522,12 +32573,12 @@ | |
| 32573 | i64 startline = 0; /* Line number for start of current input */ |
| 32574 | QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */ |
| 32575 | |
| 32576 | if( p->inputNesting==MAX_INPUT_NESTING ){ |
| 32577 | /* This will be more informative in a later version. */ |
| 32578 | sqlite3_fprintf(stderr,"%s: Input nesting limit (%d) reached at line %lld." |
| 32579 | " Check recursion.\n", zSrc, MAX_INPUT_NESTING, p->lineno); |
| 32580 | return 1; |
| 32581 | } |
| 32582 | ++p->inputNesting; |
| 32583 | p->lineno = 0; |
| 32584 | CONTINUE_PROMPT_RESET; |
| @@ -32588,11 +32639,19 @@ | |
| 32639 | }else{ |
| 32640 | zSql[nSql++] = '\n'; |
| 32641 | memcpy(zSql+nSql, zLine, nLine+1); |
| 32642 | nSql += nLine; |
| 32643 | } |
| 32644 | if( nSql>0x7fff0000 ){ |
| 32645 | char zSize[100]; |
| 32646 | sqlite3_snprintf(sizeof(zSize),zSize,"%,lld",nSql); |
| 32647 | sqlite3_fprintf(stderr, "%s:%lld: Input SQL is too big: %s bytes\n", |
| 32648 | zSrc, startline, zSize); |
| 32649 | nSql = 0; |
| 32650 | errCnt++; |
| 32651 | break; |
| 32652 | }else if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){ |
| 32653 | echo_group_input(p, zSql); |
| 32654 | errCnt += runOneSqlLine(p, zSql, p->in, startline); |
| 32655 | CONTINUE_PROMPT_RESET; |
| 32656 | nSql = 0; |
| 32657 | if( p->outCount ){ |
| @@ -32756,11 +32815,11 @@ | |
| 32815 | const char *sqliterc_override /* Name of config file. NULL to use default */ |
| 32816 | ){ |
| 32817 | char *home_dir = NULL; |
| 32818 | char *sqliterc = (char*)sqliterc_override; |
| 32819 | FILE *inSaved = p->in; |
| 32820 | i64 savedLineno = p->lineno; |
| 32821 | |
| 32822 | if( sqliterc == NULL ){ |
| 32823 | sqliterc = find_xdg_file("XDG_CONFIG_HOME", |
| 32824 | ".config", |
| 32825 | "sqlite3/sqliterc"); |
| @@ -32778,11 +32837,11 @@ | |
| 32837 | p->in = sqliterc ? sqlite3_fopen(sqliterc,"rb") : 0; |
| 32838 | if( p->in ){ |
| 32839 | if( stdin_is_interactive ){ |
| 32840 | sqlite3_fprintf(stderr,"-- Loading resources from %s\n", sqliterc); |
| 32841 | } |
| 32842 | if( process_input(p, sqliterc) && bail_on_error ) exit(1); |
| 32843 | fclose(p->in); |
| 32844 | }else if( sqliterc_override!=0 ){ |
| 32845 | sqlite3_fprintf(stderr,"cannot open: \"%s\"\n", sqliterc); |
| 32846 | if( bail_on_error ) exit(1); |
| 32847 | } |
| @@ -33609,19 +33668,19 @@ | |
| 33668 | linenoiseSetCompletionCallback(linenoise_completion); |
| 33669 | #elif HAVE_LINENOISE==2 |
| 33670 | linenoiseSetCompletionCallback(linenoise_completion, NULL); |
| 33671 | #endif |
| 33672 | data.in = 0; |
| 33673 | rc = process_input(&data, "<stdin>"); |
| 33674 | if( zHistory ){ |
| 33675 | shell_stifle_history(2000); |
| 33676 | shell_write_history(zHistory); |
| 33677 | sqlite3_free(zHistory); |
| 33678 | } |
| 33679 | }else{ |
| 33680 | data.in = stdin; |
| 33681 | rc = process_input(&data, "<stdin>"); |
| 33682 | } |
| 33683 | } |
| 33684 | #ifndef SQLITE_SHELL_FIDDLE |
| 33685 | /* In WASM mode we have to leave the db state in place so that |
| 33686 | ** client code can "push" SQL into it after this call returns. */ |
| @@ -33799,10 +33858,10 @@ | |
| 33858 | void fiddle_exec(const char * zSql){ |
| 33859 | if(zSql && *zSql){ |
| 33860 | if('.'==*zSql) puts(zSql); |
| 33861 | shellState.wasm.zInput = zSql; |
| 33862 | shellState.wasm.zPos = zSql; |
| 33863 | process_input(&shellState, "<stdin>"); |
| 33864 | shellState.wasm.zInput = shellState.wasm.zPos = 0; |
| 33865 | } |
| 33866 | } |
| 33867 | #endif /* SQLITE_SHELL_FIDDLE */ |
| 33868 |
+378
-38
| --- extsrc/sqlite3.c | ||
| +++ extsrc/sqlite3.c | ||
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | -** 5cbccab499bc3983aac1f57355552db607de with changes in files: | |
| 21 | +** 724f2299f206cc9e7f830f984c50a8fc4ac1 with changes in files: | |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| @@ -467,14 +467,14 @@ | ||
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | 470 | #define SQLITE_VERSION "3.51.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3051000 |
| 472 | -#define SQLITE_SOURCE_ID "2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70" | |
| 472 | +#define SQLITE_SOURCE_ID "2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060" | |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | -#define SQLITE_SCM_DATETIME "2025-10-15T10:52:45.276Z" | |
| 475 | +#define SQLITE_SCM_DATETIME "2025-10-28T13:24:50.858Z" | |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| @@ -1251,11 +1251,11 @@ | ||
| 1251 | 1251 | ** to the [sqlite3_file] object associated with the journal file (either |
| 1252 | 1252 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 1253 | 1253 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 1254 | 1254 | ** |
| 1255 | 1255 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 1256 | -** No longer in use. | |
| 1256 | +** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. | |
| 1257 | 1257 | ** |
| 1258 | 1258 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 1259 | 1259 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 1260 | 1260 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 1261 | 1261 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1548,10 +1548,19 @@ | ||
| 1548 | 1548 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1549 | 1549 | ** If there is currently no transaction open on the database, and the |
| 1550 | 1550 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1551 | 1551 | ** purges the contents of the in-memory page cache. If there is an open |
| 1552 | 1552 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1553 | +** | |
| 1554 | +** <li>[[SQLITE_FCNTL_FILESTAT]] | |
| 1555 | +** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information | |
| 1556 | +** about the [sqlite3_file] objects used access the database and journal files | |
| 1557 | +** for the given schema. The fourth parameter to [sqlite3_file_control()] | |
| 1558 | +** should be an initialized [sqlite3_str] pointer. JSON text describing | |
| 1559 | +** various aspects of the sqlite3_file object is appended to the sqlite3_str. | |
| 1560 | +** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time | |
| 1561 | +** options are used to enable it. | |
| 1553 | 1562 | ** </ul> |
| 1554 | 1563 | */ |
| 1555 | 1564 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1556 | 1565 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1557 | 1566 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1593,10 +1602,11 @@ | ||
| 1593 | 1602 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1594 | 1603 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1595 | 1604 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1596 | 1605 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1597 | 1606 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1607 | +#define SQLITE_FCNTL_FILESTAT 45 | |
| 1598 | 1608 | |
| 1599 | 1609 | /* deprecated names */ |
| 1600 | 1610 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1601 | 1611 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1602 | 1612 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -5226,13 +5236,15 @@ | ||
| 5226 | 5236 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 5227 | 5237 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 5228 | 5238 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 5229 | 5239 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 5230 | 5240 | ** destructor D with a single argument of P when it is finished using |
| 5231 | -** P. The T parameter should be a static string, preferably a string | |
| 5232 | -** literal. The sqlite3_bind_pointer() routine is part of the | |
| 5233 | -** [pointer passing interface] added for SQLite 3.20.0. | |
| 5241 | +** P, even if the call to sqlite3_bind_pointer() fails. Due to a | |
| 5242 | +** historical design quirk, results are undefined if D is | |
| 5243 | +** SQLITE_TRANSIENT. The T parameter should be a static string, | |
| 5244 | +** preferably a string literal. The sqlite3_bind_pointer() routine is | |
| 5245 | +** part of the [pointer passing interface] added for SQLite 3.20.0. | |
| 5234 | 5246 | ** |
| 5235 | 5247 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 5236 | 5248 | ** for the [prepared statement] or with a prepared statement for which |
| 5237 | 5249 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 5238 | 5250 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11472,23 +11484,25 @@ | ||
| 11472 | 11484 | ** array to be bound, and N is the number of eements in the array. The |
| 11473 | 11485 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11474 | 11486 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11475 | 11487 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11476 | 11488 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11477 | -** after it has finished using P. | |
| 11489 | +** after it has finished using P, even if the call to | |
| 11490 | +** sqlite3_carray_bind() fails. The special-case finalizer | |
| 11491 | +** SQLITE_TRANSIENT has no effect here. | |
| 11478 | 11492 | */ |
| 11479 | -SQLITE_API SQLITE_API int sqlite3_carray_bind( | |
| 11493 | +SQLITE_API int sqlite3_carray_bind( | |
| 11480 | 11494 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11481 | 11495 | int i, /* Parameter index */ |
| 11482 | 11496 | void *aData, /* Pointer to array data */ |
| 11483 | 11497 | int nData, /* Number of data elements */ |
| 11484 | 11498 | int mFlags, /* CARRAY flags */ |
| 11485 | 11499 | void (*xDel)(void*) /* Destructor for aData */ |
| 11486 | 11500 | ); |
| 11487 | 11501 | |
| 11488 | 11502 | /* |
| 11489 | -** CAPI3REF: Datatypes for the CARRAY table-valued funtion | |
| 11503 | +** CAPI3REF: Datatypes for the CARRAY table-valued function | |
| 11490 | 11504 | ** |
| 11491 | 11505 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11492 | 11506 | ** one of the following constants, to specify the datatype of the array |
| 11493 | 11507 | ** that is being bound into the [carray table-valued function]. |
| 11494 | 11508 | */ |
| @@ -22014,11 +22028,11 @@ | ||
| 22014 | 22028 | SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno); |
| 22015 | 22029 | SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); |
| 22016 | 22030 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); |
| 22017 | 22031 | SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); |
| 22018 | 22032 | SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); |
| 22019 | -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); | |
| 22033 | +SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); | |
| 22020 | 22034 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 22021 | 22035 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); |
| 22022 | 22036 | SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); |
| 22023 | 22037 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); |
| 22024 | 22038 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| @@ -39781,10 +39795,123 @@ | ||
| 39781 | 39795 | #endif |
| 39782 | 39796 | |
| 39783 | 39797 | }; /* End of the overrideable system calls */ |
| 39784 | 39798 | |
| 39785 | 39799 | |
| 39800 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 39801 | +/* | |
| 39802 | +** Extract Posix Advisory Locking information about file description fd | |
| 39803 | +** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16] | |
| 39804 | +** with characters to indicate which SQLite-relevant locks are held. | |
| 39805 | +** a[16] will be a 15-character zero-terminated string with the following | |
| 39806 | +** schema: | |
| 39807 | +** | |
| 39808 | +** AAA/B.DDD.DDDDD | |
| 39809 | +** | |
| 39810 | +** Each of character A-D will be "w" or "r" or "-" to indicate either a | |
| 39811 | +** write-lock, a read-lock, or no-lock, respectively. The "." and "/" | |
| 39812 | +** characters are delimiters intended to make the string more easily | |
| 39813 | +** readable by humans. Here are the meaning of the specific letters: | |
| 39814 | +** | |
| 39815 | +** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE, | |
| 39816 | +** and SHARED_FIRST, respectively. | |
| 39817 | +** | |
| 39818 | +** B -> The deadman switch lock. Offset 128 of the -shm file. | |
| 39819 | +** | |
| 39820 | +** CCC -> WAL locks: WRITE, CKPT, RECOVER | |
| 39821 | +** | |
| 39822 | +** DDDDD -> WAL read-locks 0 through 5 | |
| 39823 | +** | |
| 39824 | +** Note that elements before the "/" apply to the main database file and | |
| 39825 | +** elements after the "/" apply to the -shm file in WAL mode. | |
| 39826 | +** | |
| 39827 | +** Here is another way of thinking about the meaning of the result string: | |
| 39828 | +** | |
| 39829 | +** AAA/B.CCC.DDDDD | |
| 39830 | +** ||| | ||| \___/ | |
| 39831 | +** PENDING--'|| | ||| `----- READ 0-5 | |
| 39832 | +** RESERVED--'| | ||`---- RECOVER | |
| 39833 | +** SHARED ----' | |`----- CKPT | |
| 39834 | +** DMS ------' `------ WRITE | |
| 39835 | +** | |
| 39836 | +** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc | |
| 39837 | +** pseudo-filesystem is unavailable. | |
| 39838 | +*/ | |
| 39839 | +static int unixPosixAdvisoryLocks( | |
| 39840 | + int fd, /* The file descriptor to analyze */ | |
| 39841 | + char a[16] /* Write a text description of PALs here */ | |
| 39842 | +){ | |
| 39843 | + int in; | |
| 39844 | + ssize_t n; | |
| 39845 | + char *p, *pNext, *x; | |
| 39846 | + char z[2000]; | |
| 39847 | + | |
| 39848 | + /* 1 */ | |
| 39849 | + /* 012 4 678 01234 */ | |
| 39850 | + memcpy(a, "---/-.---.-----", 16); | |
| 39851 | + sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd); | |
| 39852 | + in = osOpen(z, O_RDONLY, 0); | |
| 39853 | + if( in<0 ){ | |
| 39854 | + return SQLITE_ERROR_UNABLE; | |
| 39855 | + } | |
| 39856 | + n = osRead(in, z, sizeof(z)-1); | |
| 39857 | + osClose(in); | |
| 39858 | + if( n<=0 ) return SQLITE_ERROR_UNABLE; | |
| 39859 | + z[n] = 0; | |
| 39860 | + | |
| 39861 | + /* We are looking for lines that begin with "lock:\t". Examples: | |
| 39862 | + ** | |
| 39863 | + ** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335 | |
| 39864 | + ** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120 | |
| 39865 | + ** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123 | |
| 39866 | + ** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128 | |
| 39867 | + */ | |
| 39868 | + pNext = strstr(z, "lock:\t"); | |
| 39869 | + while( pNext ){ | |
| 39870 | + char cType = 0; | |
| 39871 | + sqlite3_int64 iFirst, iLast; | |
| 39872 | + p = pNext+6; | |
| 39873 | + pNext = strstr(p, "lock:\t"); | |
| 39874 | + if( pNext ) pNext[-1] = 0; | |
| 39875 | + if( (x = strstr(p, " READ "))!=0 ){ | |
| 39876 | + cType = 'r'; | |
| 39877 | + x += 6; | |
| 39878 | + }else if( (x = strstr(p, " WRITE "))!=0 ){ | |
| 39879 | + cType = 'w'; | |
| 39880 | + x += 7; | |
| 39881 | + }else{ | |
| 39882 | + continue; | |
| 39883 | + } | |
| 39884 | + x = strrchr(x, ' '); | |
| 39885 | + if( x==0 ) continue; | |
| 39886 | + iLast = strtoll(x+1, 0, 10); | |
| 39887 | + *x = 0; | |
| 39888 | + x = strrchr(p, ' '); | |
| 39889 | + if( x==0 ) continue; | |
| 39890 | + iFirst = strtoll(x+1, 0, 10); | |
| 39891 | + if( iLast>=PENDING_BYTE ){ | |
| 39892 | + if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType; | |
| 39893 | + if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType; | |
| 39894 | + if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType; | |
| 39895 | + }else if( iLast<=128 ){ | |
| 39896 | + if( iFirst<=128 && iLast>=128 ) a[4] = cType; | |
| 39897 | + if( iFirst<=120 && iLast>=120 ) a[6] = cType; | |
| 39898 | + if( iFirst<=121 && iLast>=121 ) a[7] = cType; | |
| 39899 | + if( iFirst<=122 && iLast>=122 ) a[8] = cType; | |
| 39900 | + if( iFirst<=123 && iLast>=123 ) a[10] = cType; | |
| 39901 | + if( iFirst<=124 && iLast>=124 ) a[11] = cType; | |
| 39902 | + if( iFirst<=125 && iLast>=125 ) a[12] = cType; | |
| 39903 | + if( iFirst<=126 && iLast>=126 ) a[13] = cType; | |
| 39904 | + if( iFirst<=127 && iLast>=127 ) a[14] = cType; | |
| 39905 | + } | |
| 39906 | + } | |
| 39907 | + return SQLITE_OK; | |
| 39908 | +} | |
| 39909 | +#else | |
| 39910 | +# define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE | |
| 39911 | +#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ | |
| 39912 | + | |
| 39786 | 39913 | /* |
| 39787 | 39914 | ** On some systems, calls to fchown() will trigger a message in a security |
| 39788 | 39915 | ** log if they come from non-root processes. So avoid calling fchown() if |
| 39789 | 39916 | ** we are not running as root. |
| 39790 | 39917 | */ |
| @@ -40904,10 +41031,13 @@ | ||
| 40904 | 41031 | rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 40905 | 41032 | } |
| 40906 | 41033 | return rc; |
| 40907 | 41034 | } |
| 40908 | 41035 | |
| 41036 | +/* Forward reference */ | |
| 41037 | +static int unixIsSharingShmNode(unixFile*); | |
| 41038 | + | |
| 40909 | 41039 | /* |
| 40910 | 41040 | ** Lock the file with the lock specified by parameter eFileLock - one |
| 40911 | 41041 | ** of the following: |
| 40912 | 41042 | ** |
| 40913 | 41043 | ** (1) SHARED_LOCK |
| @@ -41092,11 +41222,13 @@ | ||
| 41092 | 41222 | }else{ |
| 41093 | 41223 | pFile->eFileLock = SHARED_LOCK; |
| 41094 | 41224 | pInode->nLock++; |
| 41095 | 41225 | pInode->nShared = 1; |
| 41096 | 41226 | } |
| 41097 | - }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ | |
| 41227 | + }else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1) | |
| 41228 | + || unixIsSharingShmNode(pFile) | |
| 41229 | + ){ | |
| 41098 | 41230 | /* We are trying for an exclusive lock but another thread in this |
| 41099 | 41231 | ** same process is still holding a shared lock. */ |
| 41100 | 41232 | rc = SQLITE_BUSY; |
| 41101 | 41233 | }else{ |
| 41102 | 41234 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| @@ -43187,10 +43319,14 @@ | ||
| 43187 | 43319 | /* Forward declaration */ |
| 43188 | 43320 | static int unixGetTempname(int nBuf, char *zBuf); |
| 43189 | 43321 | #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) |
| 43190 | 43322 | static int unixFcntlExternalReader(unixFile*, int*); |
| 43191 | 43323 | #endif |
| 43324 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 43325 | + static void unixDescribeShm(sqlite3_str*,unixShm*); | |
| 43326 | +#endif | |
| 43327 | + | |
| 43192 | 43328 | |
| 43193 | 43329 | /* |
| 43194 | 43330 | ** Information and control of an open file handle. |
| 43195 | 43331 | */ |
| 43196 | 43332 | static int unixFileControl(sqlite3_file *id, int op, void *pArg){ |
| @@ -43329,10 +43465,70 @@ | ||
| 43329 | 43465 | #else |
| 43330 | 43466 | *(int*)pArg = 0; |
| 43331 | 43467 | return SQLITE_OK; |
| 43332 | 43468 | #endif |
| 43333 | 43469 | } |
| 43470 | + | |
| 43471 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 43472 | + case SQLITE_FCNTL_FILESTAT: { | |
| 43473 | + sqlite3_str *pStr = (sqlite3_str*)pArg; | |
| 43474 | + char aLck[16]; | |
| 43475 | + unixInodeInfo *pInode; | |
| 43476 | + static const char *azLock[] = { "SHARED", "RESERVED", | |
| 43477 | + "PENDING", "EXCLUSIVE" }; | |
| 43478 | + sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h); | |
| 43479 | + sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); | |
| 43480 | + if( pFile->eFileLock ){ | |
| 43481 | + sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", | |
| 43482 | + azLock[pFile->eFileLock-1]); | |
| 43483 | + if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){ | |
| 43484 | + sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); | |
| 43485 | + } | |
| 43486 | + } | |
| 43487 | + unixEnterMutex(); | |
| 43488 | + if( pFile->pShm ){ | |
| 43489 | + sqlite3_str_appendall(pStr, ",\"shm\":"); | |
| 43490 | + unixDescribeShm(pStr, pFile->pShm); | |
| 43491 | + } | |
| 43492 | +#if SQLITE_MAX_MMAP_SIZE>0 | |
| 43493 | + if( pFile->mmapSize ){ | |
| 43494 | + sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); | |
| 43495 | + sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); | |
| 43496 | + } | |
| 43497 | +#endif | |
| 43498 | + if( (pInode = pFile->pInode)!=0 ){ | |
| 43499 | + sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef); | |
| 43500 | + sqlite3_mutex_enter(pInode->pLockMutex); | |
| 43501 | + sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared); | |
| 43502 | + if( pInode->eFileLock ){ | |
| 43503 | + sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", | |
| 43504 | + azLock[pInode->eFileLock-1]); | |
| 43505 | + } | |
| 43506 | + if( pInode->pUnused ){ | |
| 43507 | + char cSep = '['; | |
| 43508 | + UnixUnusedFd *pUFd = pFile->pInode->pUnused; | |
| 43509 | + sqlite3_str_appendall(pStr, ",\"unusedFd\":"); | |
| 43510 | + while( pUFd ){ | |
| 43511 | + sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d", | |
| 43512 | + cSep, pUFd->fd, pUFd->flags); | |
| 43513 | + cSep = ','; | |
| 43514 | + if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){ | |
| 43515 | + sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); | |
| 43516 | + } | |
| 43517 | + sqlite3_str_append(pStr, "}", 1); | |
| 43518 | + pUFd = pUFd->pNext; | |
| 43519 | + } | |
| 43520 | + sqlite3_str_append(pStr, "]", 1); | |
| 43521 | + } | |
| 43522 | + sqlite3_mutex_leave(pInode->pLockMutex); | |
| 43523 | + sqlite3_str_append(pStr, "}", 1); | |
| 43524 | + } | |
| 43525 | + unixLeaveMutex(); | |
| 43526 | + sqlite3_str_append(pStr, "}", 1); | |
| 43527 | + return SQLITE_OK; | |
| 43528 | + } | |
| 43529 | +#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ | |
| 43334 | 43530 | } |
| 43335 | 43531 | return SQLITE_NOTFOUND; |
| 43336 | 43532 | } |
| 43337 | 43533 | |
| 43338 | 43534 | /* |
| @@ -43595,10 +43791,30 @@ | ||
| 43595 | 43791 | ** Constants used for locking |
| 43596 | 43792 | */ |
| 43597 | 43793 | #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 43598 | 43794 | #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 43599 | 43795 | |
| 43796 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 43797 | +/* | |
| 43798 | +** Describe the pShm object using JSON. Used for diagnostics only. | |
| 43799 | +*/ | |
| 43800 | +static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){ | |
| 43801 | + unixShmNode *pNode = pShm->pShmNode; | |
| 43802 | + char aLck[16]; | |
| 43803 | + sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm); | |
| 43804 | + assert( unixMutexHeld() ); | |
| 43805 | + sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef); | |
| 43806 | + sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id); | |
| 43807 | + sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask); | |
| 43808 | + sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask); | |
| 43809 | + if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){ | |
| 43810 | + sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); | |
| 43811 | + } | |
| 43812 | + sqlite3_str_append(pStr, "}", 1); | |
| 43813 | +} | |
| 43814 | +#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ | |
| 43815 | + | |
| 43600 | 43816 | /* |
| 43601 | 43817 | ** Use F_GETLK to check whether or not there are any readers with open |
| 43602 | 43818 | ** wal-mode transactions in other processes on database file pFile. If |
| 43603 | 43819 | ** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are |
| 43604 | 43820 | ** such transactions, or 0 otherwise. If an error occurs, return an |
| @@ -43628,10 +43844,53 @@ | ||
| 43628 | 43844 | } |
| 43629 | 43845 | |
| 43630 | 43846 | return rc; |
| 43631 | 43847 | } |
| 43632 | 43848 | |
| 43849 | +/* | |
| 43850 | +** If pFile has a -shm file open and it is sharing that file with some | |
| 43851 | +** other connection, either in the same process or in a separate process, | |
| 43852 | +** then return true. Return false if either pFile does not have a -shm | |
| 43853 | +** file open or if it is the only connection to that -shm file across the | |
| 43854 | +** entire system. | |
| 43855 | +** | |
| 43856 | +** This routine is not required for correct operation. It can always return | |
| 43857 | +** false and SQLite will continue to operate according to spec. However, | |
| 43858 | +** when this routine does its job, it adds extra robustness in cases | |
| 43859 | +** where database file locks have been erroneously deleted in a WAL-mode | |
| 43860 | +** database by doing close(open(DATABASE_PATHNAME)) or similar. | |
| 43861 | +** | |
| 43862 | +** With false negatives, SQLite still operates to spec, though with less | |
| 43863 | +** robustness. With false positives, the last database connection on a | |
| 43864 | +** WAL-mode database will fail to unlink the -wal and -shm files, which | |
| 43865 | +** is annoying but harmless. False positives will also prevent a database | |
| 43866 | +** connection from running "PRAGMA journal_mode=DELETE" in order to take | |
| 43867 | +** the database out of WAL mode, which is perhaps more serious, but is | |
| 43868 | +** still not a disaster. | |
| 43869 | +*/ | |
| 43870 | +static int unixIsSharingShmNode(unixFile *pFile){ | |
| 43871 | + int rc; | |
| 43872 | + unixShmNode *pShmNode; | |
| 43873 | + if( pFile->pShm==0 ) return 0; | |
| 43874 | + if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0; | |
| 43875 | + pShmNode = pFile->pShm->pShmNode; | |
| 43876 | + rc = 1; | |
| 43877 | + unixEnterMutex(); | |
| 43878 | + if( ALWAYS(pShmNode->nRef==1) ){ | |
| 43879 | + struct flock lock; | |
| 43880 | + lock.l_whence = SEEK_SET; | |
| 43881 | + lock.l_start = UNIX_SHM_DMS; | |
| 43882 | + lock.l_len = 1; | |
| 43883 | + lock.l_type = F_WRLCK; | |
| 43884 | + osFcntl(pShmNode->hShm, F_GETLK, &lock); | |
| 43885 | + if( lock.l_type==F_UNLCK ){ | |
| 43886 | + rc = 0; | |
| 43887 | + } | |
| 43888 | + } | |
| 43889 | + unixLeaveMutex(); | |
| 43890 | + return rc; | |
| 43891 | +} | |
| 43633 | 43892 | |
| 43634 | 43893 | /* |
| 43635 | 43894 | ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. |
| 43636 | 43895 | ** |
| 43637 | 43896 | ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking |
| @@ -43673,11 +43932,12 @@ | ||
| 43673 | 43932 | /* Shared locks never span more than one byte */ |
| 43674 | 43933 | assert( n==1 || lockType!=F_RDLCK ); |
| 43675 | 43934 | |
| 43676 | 43935 | /* Locks are within range */ |
| 43677 | 43936 | assert( n>=1 && n<=SQLITE_SHM_NLOCK ); |
| 43678 | - assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); | |
| 43937 | + assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS ); | |
| 43938 | + assert( ofst+n-1<=UNIX_SHM_DMS ); | |
| 43679 | 43939 | |
| 43680 | 43940 | if( pShmNode->hShm>=0 ){ |
| 43681 | 43941 | int res; |
| 43682 | 43942 | /* Initialize the locking parameters */ |
| 43683 | 43943 | f.l_type = lockType; |
| @@ -51478,10 +51738,32 @@ | ||
| 51478 | 51738 | int iNew = *(int*)pArg; |
| 51479 | 51739 | pFile->bBlockOnConnect = iNew; |
| 51480 | 51740 | return SQLITE_OK; |
| 51481 | 51741 | } |
| 51482 | 51742 | #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 51743 | + | |
| 51744 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 51745 | + case SQLITE_FCNTL_FILESTAT: { | |
| 51746 | + sqlite3_str *pStr = (sqlite3_str*)pArg; | |
| 51747 | + sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h); | |
| 51748 | + sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); | |
| 51749 | + if( pFile->locktype ){ | |
| 51750 | + static const char *azLock[] = { "SHARED", "RESERVED", | |
| 51751 | + "PENDING", "EXCLUSIVE" }; | |
| 51752 | + sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"", | |
| 51753 | + azLock[pFile->locktype-1]); | |
| 51754 | + } | |
| 51755 | +#if SQLITE_MAX_MMAP_SIZE>0 | |
| 51756 | + if( pFile->mmapSize ){ | |
| 51757 | + sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); | |
| 51758 | + sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); | |
| 51759 | + } | |
| 51760 | +#endif | |
| 51761 | + sqlite3_str_append(pStr, "}", 1); | |
| 51762 | + return SQLITE_OK; | |
| 51763 | + } | |
| 51764 | +#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ | |
| 51483 | 51765 | |
| 51484 | 51766 | } |
| 51485 | 51767 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| 51486 | 51768 | return SQLITE_NOTFOUND; |
| 51487 | 51769 | } |
| @@ -67063,11 +67345,11 @@ | ||
| 67063 | 67345 | } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */ |
| 67064 | 67346 | }; |
| 67065 | 67347 | |
| 67066 | 67348 | /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ |
| 67067 | 67349 | #define SZ_WALITERATOR(N) \ |
| 67068 | - (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment)) | |
| 67350 | + (offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment)) | |
| 67069 | 67351 | |
| 67070 | 67352 | /* |
| 67071 | 67353 | ** Define the parameters of the hash tables in the wal-index file. There |
| 67072 | 67354 | ** is a hash-table following every HASHTABLE_NPAGE page numbers in the |
| 67073 | 67355 | ** wal-index. |
| @@ -94735,14 +95017,14 @@ | ||
| 94735 | 95017 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 94736 | 95018 | ** bytes in this text up to but excluding the first character in |
| 94737 | 95019 | ** a host parameter. If the text contains no host parameters, return |
| 94738 | 95020 | ** the total number of bytes in the text. |
| 94739 | 95021 | */ |
| 94740 | -static int findNextHostParameter(const char *zSql, int *pnToken){ | |
| 95022 | +static i64 findNextHostParameter(const char *zSql, i64 *pnToken){ | |
| 94741 | 95023 | int tokenType; |
| 94742 | - int nTotal = 0; | |
| 94743 | - int n; | |
| 95024 | + i64 nTotal = 0; | |
| 95025 | + i64 n; | |
| 94744 | 95026 | |
| 94745 | 95027 | *pnToken = 0; |
| 94746 | 95028 | while( zSql[0] ){ |
| 94747 | 95029 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 94748 | 95030 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| @@ -94785,12 +95067,12 @@ | ||
| 94785 | 95067 | const char *zRawSql /* Raw text of the SQL statement */ |
| 94786 | 95068 | ){ |
| 94787 | 95069 | sqlite3 *db; /* The database connection */ |
| 94788 | 95070 | int idx = 0; /* Index of a host parameter */ |
| 94789 | 95071 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 94790 | - int n; /* Length of a token prefix */ | |
| 94791 | - int nToken; /* Length of the parameter token */ | |
| 95072 | + i64 n; /* Length of a token prefix */ | |
| 95073 | + i64 nToken; /* Length of the parameter token */ | |
| 94792 | 95074 | int i; /* Loop counter */ |
| 94793 | 95075 | Mem *pVar; /* Value of a host parameter */ |
| 94794 | 95076 | StrAccum out; /* Accumulate the output here */ |
| 94795 | 95077 | #ifndef SQLITE_OMIT_UTF16 |
| 94796 | 95078 | Mem utf8; /* Used to convert UTF16 into UTF8 for display */ |
| @@ -96816,10 +97098,13 @@ | ||
| 96816 | 97098 | nByte = pIn1->n; |
| 96817 | 97099 | nByte += pIn2->n; |
| 96818 | 97100 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 96819 | 97101 | goto too_big; |
| 96820 | 97102 | } |
| 97103 | +#if SQLITE_MAX_LENGTH>2147483645 | |
| 97104 | + if( nByte>2147483645 ){ goto too_big; } | |
| 97105 | +#endif | |
| 96821 | 97106 | if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ |
| 96822 | 97107 | goto no_mem; |
| 96823 | 97108 | } |
| 96824 | 97109 | MemSetTypeFlag(pOut, MEM_Str); |
| 96825 | 97110 | if( pOut!=pIn2 ){ |
| @@ -131915,11 +132200,11 @@ | ||
| 131915 | 132200 | static void *contextMalloc(sqlite3_context *context, i64 nByte){ |
| 131916 | 132201 | char *z; |
| 131917 | 132202 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 131918 | 132203 | assert( nByte>0 ); |
| 131919 | 132204 | testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 131920 | - testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); | |
| 132205 | + testcase( nByte==(i64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); | |
| 131921 | 132206 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 131922 | 132207 | sqlite3_result_error_toobig(context); |
| 131923 | 132208 | z = 0; |
| 131924 | 132209 | }else{ |
| 131925 | 132210 | z = sqlite3Malloc(nByte); |
| @@ -134180,12 +134465,12 @@ | ||
| 134180 | 134465 | ** aggregate. Remember all input Y values until the very end. |
| 134181 | 134466 | ** Those values are accumulated in the Percentile.a[] array. |
| 134182 | 134467 | */ |
| 134183 | 134468 | typedef struct Percentile Percentile; |
| 134184 | 134469 | struct Percentile { |
| 134185 | - unsigned nAlloc; /* Number of slots allocated for a[] */ | |
| 134186 | - unsigned nUsed; /* Number of slots actually used in a[] */ | |
| 134470 | + u64 nAlloc; /* Number of slots allocated for a[] */ | |
| 134471 | + u64 nUsed; /* Number of slots actually used in a[] */ | |
| 134187 | 134472 | char bSorted; /* True if a[] is already in sorted order */ |
| 134188 | 134473 | char bKeepSorted; /* True if advantageous to keep a[] sorted */ |
| 134189 | 134474 | char bPctValid; /* True if rPct is valid */ |
| 134190 | 134475 | double rPct; /* Fraction. 0.0 to 1.0 */ |
| 134191 | 134476 | double *a; /* Array of Y values */ |
| @@ -134218,15 +134503,15 @@ | ||
| 134218 | 134503 | ** If bExact is false, return the index at which a new entry with |
| 134219 | 134504 | ** value y should be insert in order to keep the values in sorted |
| 134220 | 134505 | ** order. The smallest return value in this case will be 0, and |
| 134221 | 134506 | ** the largest return value will be p->nUsed. |
| 134222 | 134507 | */ |
| 134223 | -static int percentBinarySearch(Percentile *p, double y, int bExact){ | |
| 134224 | - int iFirst = 0; /* First element of search range */ | |
| 134225 | - int iLast = p->nUsed - 1; /* Last element of search range */ | |
| 134508 | +static i64 percentBinarySearch(Percentile *p, double y, int bExact){ | |
| 134509 | + i64 iFirst = 0; /* First element of search range */ | |
| 134510 | + i64 iLast = (i64)p->nUsed - 1; /* Last element of search range */ | |
| 134226 | 134511 | while( iLast>=iFirst ){ |
| 134227 | - int iMid = (iFirst+iLast)/2; | |
| 134512 | + i64 iMid = (iFirst+iLast)/2; | |
| 134228 | 134513 | double x = p->a[iMid]; |
| 134229 | 134514 | if( x<y ){ |
| 134230 | 134515 | iFirst = iMid + 1; |
| 134231 | 134516 | }else if( x>y ){ |
| 134232 | 134517 | iLast = iMid - 1; |
| @@ -134325,11 +134610,11 @@ | ||
| 134325 | 134610 | return; |
| 134326 | 134611 | } |
| 134327 | 134612 | |
| 134328 | 134613 | /* Allocate and store the Y */ |
| 134329 | 134614 | if( p->nUsed>=p->nAlloc ){ |
| 134330 | - unsigned n = p->nAlloc*2 + 250; | |
| 134615 | + u64 n = p->nAlloc*2 + 250; | |
| 134331 | 134616 | double *a = sqlite3_realloc64(p->a, sizeof(double)*n); |
| 134332 | 134617 | if( a==0 ){ |
| 134333 | 134618 | sqlite3_free(p->a); |
| 134334 | 134619 | memset(p, 0, sizeof(*p)); |
| 134335 | 134620 | sqlite3_result_error_nomem(pCtx); |
| @@ -134342,11 +134627,11 @@ | ||
| 134342 | 134627 | p->a[p->nUsed++] = y; |
| 134343 | 134628 | p->bSorted = 1; |
| 134344 | 134629 | }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ |
| 134345 | 134630 | p->a[p->nUsed++] = y; |
| 134346 | 134631 | }else if( p->bKeepSorted ){ |
| 134347 | - int i; | |
| 134632 | + i64 i; | |
| 134348 | 134633 | i = percentBinarySearch(p, y, 0); |
| 134349 | 134634 | if( i<(int)p->nUsed ){ |
| 134350 | 134635 | memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); |
| 134351 | 134636 | } |
| 134352 | 134637 | p->a[i] = y; |
| @@ -134427,11 +134712,11 @@ | ||
| 134427 | 134712 | */ |
| 134428 | 134713 | static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){ |
| 134429 | 134714 | Percentile *p; |
| 134430 | 134715 | int eType; |
| 134431 | 134716 | double y; |
| 134432 | - int i; | |
| 134717 | + i64 i; | |
| 134433 | 134718 | assert( argc==2 || argc==1 ); |
| 134434 | 134719 | |
| 134435 | 134720 | /* Allocate the session context. */ |
| 134436 | 134721 | p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); |
| 134437 | 134722 | assert( p!=0 ); |
| @@ -134513,10 +134798,60 @@ | ||
| 134513 | 134798 | percentCompute(pCtx, 0); |
| 134514 | 134799 | } |
| 134515 | 134800 | /****** End of percentile family of functions ******/ |
| 134516 | 134801 | #endif /* SQLITE_ENABLE_PERCENTILE */ |
| 134517 | 134802 | |
| 134803 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 134804 | +/* | |
| 134805 | +** Implementation of sqlite_filestat(SCHEMA). | |
| 134806 | +** | |
| 134807 | +** Return JSON text that describes low-level debug/diagnostic information | |
| 134808 | +** about the sqlite3_file object associated with SCHEMA. | |
| 134809 | +*/ | |
| 134810 | +static void filestatFunc( | |
| 134811 | + sqlite3_context *context, | |
| 134812 | + int argc, | |
| 134813 | + sqlite3_value **argv | |
| 134814 | +){ | |
| 134815 | + sqlite3 *db = sqlite3_context_db_handle(context); | |
| 134816 | + const char *zDbName; | |
| 134817 | + sqlite3_str *pStr; | |
| 134818 | + Btree *pBtree; | |
| 134819 | + | |
| 134820 | + zDbName = (const char*)sqlite3_value_text(argv[0]); | |
| 134821 | + pBtree = sqlite3DbNameToBtree(db, zDbName); | |
| 134822 | + if( pBtree ){ | |
| 134823 | + Pager *pPager; | |
| 134824 | + sqlite3_file *fd; | |
| 134825 | + int rc; | |
| 134826 | + sqlite3BtreeEnter(pBtree); | |
| 134827 | + pPager = sqlite3BtreePager(pBtree); | |
| 134828 | + assert( pPager!=0 ); | |
| 134829 | + fd = sqlite3PagerFile(pPager); | |
| 134830 | + pStr = sqlite3_str_new(db); | |
| 134831 | + if( pStr==0 ){ | |
| 134832 | + sqlite3_result_error_nomem(context); | |
| 134833 | + }else{ | |
| 134834 | + sqlite3_str_append(pStr, "{\"db\":", 6); | |
| 134835 | + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); | |
| 134836 | + if( rc ) sqlite3_str_append(pStr, "null", 4); | |
| 134837 | + fd = sqlite3PagerJrnlFile(pPager); | |
| 134838 | + if( fd && fd->pMethods!=0 ){ | |
| 134839 | + sqlite3_str_appendall(pStr, ",\"journal\":"); | |
| 134840 | + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); | |
| 134841 | + if( rc ) sqlite3_str_append(pStr, "null", 4); | |
| 134842 | + } | |
| 134843 | + sqlite3_str_append(pStr, "}", 1); | |
| 134844 | + sqlite3_result_text(context, sqlite3_str_finish(pStr), -1, | |
| 134845 | + sqlite3_free); | |
| 134846 | + } | |
| 134847 | + sqlite3BtreeLeave(pBtree); | |
| 134848 | + }else{ | |
| 134849 | + sqlite3_result_text(context, "{}", 2, SQLITE_STATIC); | |
| 134850 | + } | |
| 134851 | +} | |
| 134852 | +#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ | |
| 134518 | 134853 | |
| 134519 | 134854 | #ifdef SQLITE_DEBUG |
| 134520 | 134855 | /* |
| 134521 | 134856 | ** Implementation of fpdecode(x,y,z) function. |
| 134522 | 134857 | ** |
| @@ -134672,10 +135007,13 @@ | ||
| 134672 | 135007 | INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 134673 | 135008 | INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 134674 | 135009 | #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC |
| 134675 | 135010 | INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ), |
| 134676 | 135011 | #endif |
| 135012 | +#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) | |
| 135013 | + FUNCTION(sqlite_filestat, 1, 0, 0, filestatFunc ), | |
| 135014 | +#endif | |
| 134677 | 135015 | FUNCTION(ltrim, 1, 1, 0, trimFunc ), |
| 134678 | 135016 | FUNCTION(ltrim, 2, 1, 0, trimFunc ), |
| 134679 | 135017 | FUNCTION(rtrim, 1, 2, 0, trimFunc ), |
| 134680 | 135018 | FUNCTION(rtrim, 2, 2, 0, trimFunc ), |
| 134681 | 135019 | FUNCTION(trim, 1, 3, 0, trimFunc ), |
| @@ -183458,12 +183796,13 @@ | ||
| 183458 | 183796 | |
| 183459 | 183797 | /* |
| 183460 | 183798 | ** Return the length (in bytes) of the token that begins at z[0]. |
| 183461 | 183799 | ** Store the token type in *tokenType before returning. |
| 183462 | 183800 | */ |
| 183463 | -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ | |
| 183464 | - int i, c; | |
| 183801 | +SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ | |
| 183802 | + i64 i; | |
| 183803 | + int c; | |
| 183465 | 183804 | switch( aiClass[*z] ){ /* Switch on the character-class of the first byte |
| 183466 | 183805 | ** of the token. See the comment on the CC_ defines |
| 183467 | 183806 | ** above. */ |
| 183468 | 183807 | case CC_SPACE: { |
| 183469 | 183808 | testcase( z[0]==' ' ); |
| @@ -183787,11 +184126,11 @@ | ||
| 183787 | 184126 | ** Run the parser on the given SQL string. |
| 183788 | 184127 | */ |
| 183789 | 184128 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ |
| 183790 | 184129 | int nErr = 0; /* Number of errors encountered */ |
| 183791 | 184130 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 183792 | - int n = 0; /* Length of the next token token */ | |
| 184131 | + i64 n = 0; /* Length of the next token token */ | |
| 183793 | 184132 | int tokenType; /* type of the next token */ |
| 183794 | 184133 | int lastTokenParsed = -1; /* type of the previous token */ |
| 183795 | 184134 | sqlite3 *db = pParse->db; /* The database connection */ |
| 183796 | 184135 | int mxSqlLen; /* Max length of an SQL string */ |
| 183797 | 184136 | Parse *pParentParse = 0; /* Outer parse context, if any */ |
| @@ -183890,17 +184229,17 @@ | ||
| 183890 | 184229 | zSql += n; |
| 183891 | 184230 | continue; |
| 183892 | 184231 | }else if( tokenType!=TK_QNUMBER ){ |
| 183893 | 184232 | Token x; |
| 183894 | 184233 | x.z = zSql; |
| 183895 | - x.n = n; | |
| 184234 | + x.n = (u32)n; | |
| 183896 | 184235 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); |
| 183897 | 184236 | break; |
| 183898 | 184237 | } |
| 183899 | 184238 | } |
| 183900 | 184239 | pParse->sLastToken.z = zSql; |
| 183901 | - pParse->sLastToken.n = n; | |
| 184240 | + pParse->sLastToken.n = (u32)n; | |
| 183902 | 184241 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken); |
| 183903 | 184242 | lastTokenParsed = tokenType; |
| 183904 | 184243 | zSql += n; |
| 183905 | 184244 | assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); |
| 183906 | 184245 | if( pParse->rc!=SQLITE_OK ) break; |
| @@ -183972,11 +184311,11 @@ | ||
| 183972 | 184311 | Vdbe *pVdbe, /* VM being reprepared */ |
| 183973 | 184312 | const char *zSql /* The original SQL string */ |
| 183974 | 184313 | ){ |
| 183975 | 184314 | sqlite3 *db; /* The database connection */ |
| 183976 | 184315 | int i; /* Next unread byte of zSql[] */ |
| 183977 | - int n; /* length of current token */ | |
| 184316 | + i64 n; /* length of current token */ | |
| 183978 | 184317 | int tokenType; /* type of current token */ |
| 183979 | 184318 | int prevType = 0; /* Previous non-whitespace token */ |
| 183980 | 184319 | int nParen; /* Number of nested levels of parentheses */ |
| 183981 | 184320 | int iStartIN; /* Start of RHS of IN operator in z[] */ |
| 183982 | 184321 | int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ |
| @@ -215365,11 +215704,11 @@ | ||
| 215365 | 215704 | /* #include "sqlite3ext.h" */ |
| 215366 | 215705 | SQLITE_EXTENSION_INIT1 |
| 215367 | 215706 | #else |
| 215368 | 215707 | /* #include "sqlite3.h" */ |
| 215369 | 215708 | #endif |
| 215370 | -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */ | |
| 215709 | +SQLITE_PRIVATE sqlite3_int64 sqlite3GetToken(const unsigned char*,int*); /* In SQLite core */ | |
| 215371 | 215710 | |
| 215372 | 215711 | /* #include <stddef.h> */ |
| 215373 | 215712 | |
| 215374 | 215713 | /* |
| 215375 | 215714 | ** If building separately, we will need some setup that is normally |
| @@ -229904,11 +230243,12 @@ | ||
| 229904 | 230243 | if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ |
| 229905 | 230244 | unsigned char *aPage = sqlite3PagerGetData(pDbPage); |
| 229906 | 230245 | memcpy(aPage, pData, szPage); |
| 229907 | 230246 | pTab->pgnoTrunc = 0; |
| 229908 | 230247 | } |
| 229909 | - }else{ | |
| 230248 | + } | |
| 230249 | + if( rc!=SQLITE_OK ){ | |
| 229910 | 230250 | pTab->pgnoTrunc = 0; |
| 229911 | 230251 | } |
| 229912 | 230252 | sqlite3PagerUnref(pDbPage); |
| 229913 | 230253 | return rc; |
| 229914 | 230254 | |
| @@ -259926,11 +260266,11 @@ | ||
| 259926 | 260266 | int nArg, /* Number of args */ |
| 259927 | 260267 | sqlite3_value **apUnused /* Function arguments */ |
| 259928 | 260268 | ){ |
| 259929 | 260269 | assert( nArg==0 ); |
| 259930 | 260270 | UNUSED_PARAM2(nArg, apUnused); |
| 259931 | - sqlite3_result_text(pCtx, "fts5: 2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70", -1, SQLITE_TRANSIENT); | |
| 260271 | + sqlite3_result_text(pCtx, "fts5: 2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060", -1, SQLITE_TRANSIENT); | |
| 259932 | 260272 | } |
| 259933 | 260273 | |
| 259934 | 260274 | /* |
| 259935 | 260275 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 259936 | 260276 | ** |
| 259937 | 260277 |
| --- extsrc/sqlite3.c | |
| +++ extsrc/sqlite3.c | |
| @@ -16,11 +16,11 @@ | |
| 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | ** |
| 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | ** 5cbccab499bc3983aac1f57355552db607de with changes in files: |
| 22 | ** |
| 23 | ** |
| 24 | */ |
| 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | #define SQLITE_CORE 1 |
| @@ -467,14 +467,14 @@ | |
| 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | */ |
| 470 | #define SQLITE_VERSION "3.51.0" |
| 471 | #define SQLITE_VERSION_NUMBER 3051000 |
| 472 | #define SQLITE_SOURCE_ID "2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70" |
| 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | #define SQLITE_SCM_TAGS "" |
| 475 | #define SQLITE_SCM_DATETIME "2025-10-15T10:52:45.276Z" |
| 476 | |
| 477 | /* |
| 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | ** |
| @@ -1251,11 +1251,11 @@ | |
| 1251 | ** to the [sqlite3_file] object associated with the journal file (either |
| 1252 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 1253 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 1254 | ** |
| 1255 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 1256 | ** No longer in use. |
| 1257 | ** |
| 1258 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 1259 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 1260 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 1261 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1548,10 +1548,19 @@ | |
| 1548 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1549 | ** If there is currently no transaction open on the database, and the |
| 1550 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1551 | ** purges the contents of the in-memory page cache. If there is an open |
| 1552 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1553 | ** </ul> |
| 1554 | */ |
| 1555 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1556 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1557 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1593,10 +1602,11 @@ | |
| 1593 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1594 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1595 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1596 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1597 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1598 | |
| 1599 | /* deprecated names */ |
| 1600 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1601 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1602 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -5226,13 +5236,15 @@ | |
| 5226 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 5227 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 5228 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 5229 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 5230 | ** destructor D with a single argument of P when it is finished using |
| 5231 | ** P. The T parameter should be a static string, preferably a string |
| 5232 | ** literal. The sqlite3_bind_pointer() routine is part of the |
| 5233 | ** [pointer passing interface] added for SQLite 3.20.0. |
| 5234 | ** |
| 5235 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 5236 | ** for the [prepared statement] or with a prepared statement for which |
| 5237 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 5238 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11472,23 +11484,25 @@ | |
| 11472 | ** array to be bound, and N is the number of eements in the array. The |
| 11473 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11474 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11475 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11476 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11477 | ** after it has finished using P. |
| 11478 | */ |
| 11479 | SQLITE_API SQLITE_API int sqlite3_carray_bind( |
| 11480 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11481 | int i, /* Parameter index */ |
| 11482 | void *aData, /* Pointer to array data */ |
| 11483 | int nData, /* Number of data elements */ |
| 11484 | int mFlags, /* CARRAY flags */ |
| 11485 | void (*xDel)(void*) /* Destructor for aData */ |
| 11486 | ); |
| 11487 | |
| 11488 | /* |
| 11489 | ** CAPI3REF: Datatypes for the CARRAY table-valued funtion |
| 11490 | ** |
| 11491 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11492 | ** one of the following constants, to specify the datatype of the array |
| 11493 | ** that is being bound into the [carray table-valued function]. |
| 11494 | */ |
| @@ -22014,11 +22028,11 @@ | |
| 22014 | SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno); |
| 22015 | SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); |
| 22016 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); |
| 22017 | SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); |
| 22018 | SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); |
| 22019 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 22020 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 22021 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); |
| 22022 | SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); |
| 22023 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); |
| 22024 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| @@ -39781,10 +39795,123 @@ | |
| 39781 | #endif |
| 39782 | |
| 39783 | }; /* End of the overrideable system calls */ |
| 39784 | |
| 39785 | |
| 39786 | /* |
| 39787 | ** On some systems, calls to fchown() will trigger a message in a security |
| 39788 | ** log if they come from non-root processes. So avoid calling fchown() if |
| 39789 | ** we are not running as root. |
| 39790 | */ |
| @@ -40904,10 +41031,13 @@ | |
| 40904 | rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 40905 | } |
| 40906 | return rc; |
| 40907 | } |
| 40908 | |
| 40909 | /* |
| 40910 | ** Lock the file with the lock specified by parameter eFileLock - one |
| 40911 | ** of the following: |
| 40912 | ** |
| 40913 | ** (1) SHARED_LOCK |
| @@ -41092,11 +41222,13 @@ | |
| 41092 | }else{ |
| 41093 | pFile->eFileLock = SHARED_LOCK; |
| 41094 | pInode->nLock++; |
| 41095 | pInode->nShared = 1; |
| 41096 | } |
| 41097 | }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ |
| 41098 | /* We are trying for an exclusive lock but another thread in this |
| 41099 | ** same process is still holding a shared lock. */ |
| 41100 | rc = SQLITE_BUSY; |
| 41101 | }else{ |
| 41102 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| @@ -43187,10 +43319,14 @@ | |
| 43187 | /* Forward declaration */ |
| 43188 | static int unixGetTempname(int nBuf, char *zBuf); |
| 43189 | #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) |
| 43190 | static int unixFcntlExternalReader(unixFile*, int*); |
| 43191 | #endif |
| 43192 | |
| 43193 | /* |
| 43194 | ** Information and control of an open file handle. |
| 43195 | */ |
| 43196 | static int unixFileControl(sqlite3_file *id, int op, void *pArg){ |
| @@ -43329,10 +43465,70 @@ | |
| 43329 | #else |
| 43330 | *(int*)pArg = 0; |
| 43331 | return SQLITE_OK; |
| 43332 | #endif |
| 43333 | } |
| 43334 | } |
| 43335 | return SQLITE_NOTFOUND; |
| 43336 | } |
| 43337 | |
| 43338 | /* |
| @@ -43595,10 +43791,30 @@ | |
| 43595 | ** Constants used for locking |
| 43596 | */ |
| 43597 | #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 43598 | #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 43599 | |
| 43600 | /* |
| 43601 | ** Use F_GETLK to check whether or not there are any readers with open |
| 43602 | ** wal-mode transactions in other processes on database file pFile. If |
| 43603 | ** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are |
| 43604 | ** such transactions, or 0 otherwise. If an error occurs, return an |
| @@ -43628,10 +43844,53 @@ | |
| 43628 | } |
| 43629 | |
| 43630 | return rc; |
| 43631 | } |
| 43632 | |
| 43633 | |
| 43634 | /* |
| 43635 | ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. |
| 43636 | ** |
| 43637 | ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking |
| @@ -43673,11 +43932,12 @@ | |
| 43673 | /* Shared locks never span more than one byte */ |
| 43674 | assert( n==1 || lockType!=F_RDLCK ); |
| 43675 | |
| 43676 | /* Locks are within range */ |
| 43677 | assert( n>=1 && n<=SQLITE_SHM_NLOCK ); |
| 43678 | assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); |
| 43679 | |
| 43680 | if( pShmNode->hShm>=0 ){ |
| 43681 | int res; |
| 43682 | /* Initialize the locking parameters */ |
| 43683 | f.l_type = lockType; |
| @@ -51478,10 +51738,32 @@ | |
| 51478 | int iNew = *(int*)pArg; |
| 51479 | pFile->bBlockOnConnect = iNew; |
| 51480 | return SQLITE_OK; |
| 51481 | } |
| 51482 | #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 51483 | |
| 51484 | } |
| 51485 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| 51486 | return SQLITE_NOTFOUND; |
| 51487 | } |
| @@ -67063,11 +67345,11 @@ | |
| 67063 | } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */ |
| 67064 | }; |
| 67065 | |
| 67066 | /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ |
| 67067 | #define SZ_WALITERATOR(N) \ |
| 67068 | (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment)) |
| 67069 | |
| 67070 | /* |
| 67071 | ** Define the parameters of the hash tables in the wal-index file. There |
| 67072 | ** is a hash-table following every HASHTABLE_NPAGE page numbers in the |
| 67073 | ** wal-index. |
| @@ -94735,14 +95017,14 @@ | |
| 94735 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 94736 | ** bytes in this text up to but excluding the first character in |
| 94737 | ** a host parameter. If the text contains no host parameters, return |
| 94738 | ** the total number of bytes in the text. |
| 94739 | */ |
| 94740 | static int findNextHostParameter(const char *zSql, int *pnToken){ |
| 94741 | int tokenType; |
| 94742 | int nTotal = 0; |
| 94743 | int n; |
| 94744 | |
| 94745 | *pnToken = 0; |
| 94746 | while( zSql[0] ){ |
| 94747 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 94748 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| @@ -94785,12 +95067,12 @@ | |
| 94785 | const char *zRawSql /* Raw text of the SQL statement */ |
| 94786 | ){ |
| 94787 | sqlite3 *db; /* The database connection */ |
| 94788 | int idx = 0; /* Index of a host parameter */ |
| 94789 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 94790 | int n; /* Length of a token prefix */ |
| 94791 | int nToken; /* Length of the parameter token */ |
| 94792 | int i; /* Loop counter */ |
| 94793 | Mem *pVar; /* Value of a host parameter */ |
| 94794 | StrAccum out; /* Accumulate the output here */ |
| 94795 | #ifndef SQLITE_OMIT_UTF16 |
| 94796 | Mem utf8; /* Used to convert UTF16 into UTF8 for display */ |
| @@ -96816,10 +97098,13 @@ | |
| 96816 | nByte = pIn1->n; |
| 96817 | nByte += pIn2->n; |
| 96818 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 96819 | goto too_big; |
| 96820 | } |
| 96821 | if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ |
| 96822 | goto no_mem; |
| 96823 | } |
| 96824 | MemSetTypeFlag(pOut, MEM_Str); |
| 96825 | if( pOut!=pIn2 ){ |
| @@ -131915,11 +132200,11 @@ | |
| 131915 | static void *contextMalloc(sqlite3_context *context, i64 nByte){ |
| 131916 | char *z; |
| 131917 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 131918 | assert( nByte>0 ); |
| 131919 | testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 131920 | testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 131921 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 131922 | sqlite3_result_error_toobig(context); |
| 131923 | z = 0; |
| 131924 | }else{ |
| 131925 | z = sqlite3Malloc(nByte); |
| @@ -134180,12 +134465,12 @@ | |
| 134180 | ** aggregate. Remember all input Y values until the very end. |
| 134181 | ** Those values are accumulated in the Percentile.a[] array. |
| 134182 | */ |
| 134183 | typedef struct Percentile Percentile; |
| 134184 | struct Percentile { |
| 134185 | unsigned nAlloc; /* Number of slots allocated for a[] */ |
| 134186 | unsigned nUsed; /* Number of slots actually used in a[] */ |
| 134187 | char bSorted; /* True if a[] is already in sorted order */ |
| 134188 | char bKeepSorted; /* True if advantageous to keep a[] sorted */ |
| 134189 | char bPctValid; /* True if rPct is valid */ |
| 134190 | double rPct; /* Fraction. 0.0 to 1.0 */ |
| 134191 | double *a; /* Array of Y values */ |
| @@ -134218,15 +134503,15 @@ | |
| 134218 | ** If bExact is false, return the index at which a new entry with |
| 134219 | ** value y should be insert in order to keep the values in sorted |
| 134220 | ** order. The smallest return value in this case will be 0, and |
| 134221 | ** the largest return value will be p->nUsed. |
| 134222 | */ |
| 134223 | static int percentBinarySearch(Percentile *p, double y, int bExact){ |
| 134224 | int iFirst = 0; /* First element of search range */ |
| 134225 | int iLast = p->nUsed - 1; /* Last element of search range */ |
| 134226 | while( iLast>=iFirst ){ |
| 134227 | int iMid = (iFirst+iLast)/2; |
| 134228 | double x = p->a[iMid]; |
| 134229 | if( x<y ){ |
| 134230 | iFirst = iMid + 1; |
| 134231 | }else if( x>y ){ |
| 134232 | iLast = iMid - 1; |
| @@ -134325,11 +134610,11 @@ | |
| 134325 | return; |
| 134326 | } |
| 134327 | |
| 134328 | /* Allocate and store the Y */ |
| 134329 | if( p->nUsed>=p->nAlloc ){ |
| 134330 | unsigned n = p->nAlloc*2 + 250; |
| 134331 | double *a = sqlite3_realloc64(p->a, sizeof(double)*n); |
| 134332 | if( a==0 ){ |
| 134333 | sqlite3_free(p->a); |
| 134334 | memset(p, 0, sizeof(*p)); |
| 134335 | sqlite3_result_error_nomem(pCtx); |
| @@ -134342,11 +134627,11 @@ | |
| 134342 | p->a[p->nUsed++] = y; |
| 134343 | p->bSorted = 1; |
| 134344 | }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ |
| 134345 | p->a[p->nUsed++] = y; |
| 134346 | }else if( p->bKeepSorted ){ |
| 134347 | int i; |
| 134348 | i = percentBinarySearch(p, y, 0); |
| 134349 | if( i<(int)p->nUsed ){ |
| 134350 | memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); |
| 134351 | } |
| 134352 | p->a[i] = y; |
| @@ -134427,11 +134712,11 @@ | |
| 134427 | */ |
| 134428 | static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){ |
| 134429 | Percentile *p; |
| 134430 | int eType; |
| 134431 | double y; |
| 134432 | int i; |
| 134433 | assert( argc==2 || argc==1 ); |
| 134434 | |
| 134435 | /* Allocate the session context. */ |
| 134436 | p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); |
| 134437 | assert( p!=0 ); |
| @@ -134513,10 +134798,60 @@ | |
| 134513 | percentCompute(pCtx, 0); |
| 134514 | } |
| 134515 | /****** End of percentile family of functions ******/ |
| 134516 | #endif /* SQLITE_ENABLE_PERCENTILE */ |
| 134517 | |
| 134518 | |
| 134519 | #ifdef SQLITE_DEBUG |
| 134520 | /* |
| 134521 | ** Implementation of fpdecode(x,y,z) function. |
| 134522 | ** |
| @@ -134672,10 +135007,13 @@ | |
| 134672 | INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 134673 | INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 134674 | #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC |
| 134675 | INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ), |
| 134676 | #endif |
| 134677 | FUNCTION(ltrim, 1, 1, 0, trimFunc ), |
| 134678 | FUNCTION(ltrim, 2, 1, 0, trimFunc ), |
| 134679 | FUNCTION(rtrim, 1, 2, 0, trimFunc ), |
| 134680 | FUNCTION(rtrim, 2, 2, 0, trimFunc ), |
| 134681 | FUNCTION(trim, 1, 3, 0, trimFunc ), |
| @@ -183458,12 +183796,13 @@ | |
| 183458 | |
| 183459 | /* |
| 183460 | ** Return the length (in bytes) of the token that begins at z[0]. |
| 183461 | ** Store the token type in *tokenType before returning. |
| 183462 | */ |
| 183463 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 183464 | int i, c; |
| 183465 | switch( aiClass[*z] ){ /* Switch on the character-class of the first byte |
| 183466 | ** of the token. See the comment on the CC_ defines |
| 183467 | ** above. */ |
| 183468 | case CC_SPACE: { |
| 183469 | testcase( z[0]==' ' ); |
| @@ -183787,11 +184126,11 @@ | |
| 183787 | ** Run the parser on the given SQL string. |
| 183788 | */ |
| 183789 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ |
| 183790 | int nErr = 0; /* Number of errors encountered */ |
| 183791 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 183792 | int n = 0; /* Length of the next token token */ |
| 183793 | int tokenType; /* type of the next token */ |
| 183794 | int lastTokenParsed = -1; /* type of the previous token */ |
| 183795 | sqlite3 *db = pParse->db; /* The database connection */ |
| 183796 | int mxSqlLen; /* Max length of an SQL string */ |
| 183797 | Parse *pParentParse = 0; /* Outer parse context, if any */ |
| @@ -183890,17 +184229,17 @@ | |
| 183890 | zSql += n; |
| 183891 | continue; |
| 183892 | }else if( tokenType!=TK_QNUMBER ){ |
| 183893 | Token x; |
| 183894 | x.z = zSql; |
| 183895 | x.n = n; |
| 183896 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); |
| 183897 | break; |
| 183898 | } |
| 183899 | } |
| 183900 | pParse->sLastToken.z = zSql; |
| 183901 | pParse->sLastToken.n = n; |
| 183902 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken); |
| 183903 | lastTokenParsed = tokenType; |
| 183904 | zSql += n; |
| 183905 | assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); |
| 183906 | if( pParse->rc!=SQLITE_OK ) break; |
| @@ -183972,11 +184311,11 @@ | |
| 183972 | Vdbe *pVdbe, /* VM being reprepared */ |
| 183973 | const char *zSql /* The original SQL string */ |
| 183974 | ){ |
| 183975 | sqlite3 *db; /* The database connection */ |
| 183976 | int i; /* Next unread byte of zSql[] */ |
| 183977 | int n; /* length of current token */ |
| 183978 | int tokenType; /* type of current token */ |
| 183979 | int prevType = 0; /* Previous non-whitespace token */ |
| 183980 | int nParen; /* Number of nested levels of parentheses */ |
| 183981 | int iStartIN; /* Start of RHS of IN operator in z[] */ |
| 183982 | int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ |
| @@ -215365,11 +215704,11 @@ | |
| 215365 | /* #include "sqlite3ext.h" */ |
| 215366 | SQLITE_EXTENSION_INIT1 |
| 215367 | #else |
| 215368 | /* #include "sqlite3.h" */ |
| 215369 | #endif |
| 215370 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */ |
| 215371 | |
| 215372 | /* #include <stddef.h> */ |
| 215373 | |
| 215374 | /* |
| 215375 | ** If building separately, we will need some setup that is normally |
| @@ -229904,11 +230243,12 @@ | |
| 229904 | if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ |
| 229905 | unsigned char *aPage = sqlite3PagerGetData(pDbPage); |
| 229906 | memcpy(aPage, pData, szPage); |
| 229907 | pTab->pgnoTrunc = 0; |
| 229908 | } |
| 229909 | }else{ |
| 229910 | pTab->pgnoTrunc = 0; |
| 229911 | } |
| 229912 | sqlite3PagerUnref(pDbPage); |
| 229913 | return rc; |
| 229914 | |
| @@ -259926,11 +260266,11 @@ | |
| 259926 | int nArg, /* Number of args */ |
| 259927 | sqlite3_value **apUnused /* Function arguments */ |
| 259928 | ){ |
| 259929 | assert( nArg==0 ); |
| 259930 | UNUSED_PARAM2(nArg, apUnused); |
| 259931 | sqlite3_result_text(pCtx, "fts5: 2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70", -1, SQLITE_TRANSIENT); |
| 259932 | } |
| 259933 | |
| 259934 | /* |
| 259935 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 259936 | ** |
| 259937 |
| --- extsrc/sqlite3.c | |
| +++ extsrc/sqlite3.c | |
| @@ -16,11 +16,11 @@ | |
| 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | ** |
| 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | ** 724f2299f206cc9e7f830f984c50a8fc4ac1 with changes in files: |
| 22 | ** |
| 23 | ** |
| 24 | */ |
| 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | #define SQLITE_CORE 1 |
| @@ -467,14 +467,14 @@ | |
| 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | */ |
| 470 | #define SQLITE_VERSION "3.51.0" |
| 471 | #define SQLITE_VERSION_NUMBER 3051000 |
| 472 | #define SQLITE_SOURCE_ID "2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060" |
| 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | #define SQLITE_SCM_TAGS "" |
| 475 | #define SQLITE_SCM_DATETIME "2025-10-28T13:24:50.858Z" |
| 476 | |
| 477 | /* |
| 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | ** |
| @@ -1251,11 +1251,11 @@ | |
| 1251 | ** to the [sqlite3_file] object associated with the journal file (either |
| 1252 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 1253 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 1254 | ** |
| 1255 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 1256 | ** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. |
| 1257 | ** |
| 1258 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 1259 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 1260 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 1261 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1548,10 +1548,19 @@ | |
| 1548 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1549 | ** If there is currently no transaction open on the database, and the |
| 1550 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1551 | ** purges the contents of the in-memory page cache. If there is an open |
| 1552 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1553 | ** |
| 1554 | ** <li>[[SQLITE_FCNTL_FILESTAT]] |
| 1555 | ** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information |
| 1556 | ** about the [sqlite3_file] objects used access the database and journal files |
| 1557 | ** for the given schema. The fourth parameter to [sqlite3_file_control()] |
| 1558 | ** should be an initialized [sqlite3_str] pointer. JSON text describing |
| 1559 | ** various aspects of the sqlite3_file object is appended to the sqlite3_str. |
| 1560 | ** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time |
| 1561 | ** options are used to enable it. |
| 1562 | ** </ul> |
| 1563 | */ |
| 1564 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1565 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1566 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1593,10 +1602,11 @@ | |
| 1602 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1603 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1604 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1605 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1606 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1607 | #define SQLITE_FCNTL_FILESTAT 45 |
| 1608 | |
| 1609 | /* deprecated names */ |
| 1610 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1611 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1612 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -5226,13 +5236,15 @@ | |
| 5236 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 5237 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 5238 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 5239 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 5240 | ** destructor D with a single argument of P when it is finished using |
| 5241 | ** P, even if the call to sqlite3_bind_pointer() fails. Due to a |
| 5242 | ** historical design quirk, results are undefined if D is |
| 5243 | ** SQLITE_TRANSIENT. The T parameter should be a static string, |
| 5244 | ** preferably a string literal. The sqlite3_bind_pointer() routine is |
| 5245 | ** part of the [pointer passing interface] added for SQLite 3.20.0. |
| 5246 | ** |
| 5247 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 5248 | ** for the [prepared statement] or with a prepared statement for which |
| 5249 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 5250 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11472,23 +11484,25 @@ | |
| 11484 | ** array to be bound, and N is the number of eements in the array. The |
| 11485 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11486 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11487 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11488 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11489 | ** after it has finished using P, even if the call to |
| 11490 | ** sqlite3_carray_bind() fails. The special-case finalizer |
| 11491 | ** SQLITE_TRANSIENT has no effect here. |
| 11492 | */ |
| 11493 | SQLITE_API int sqlite3_carray_bind( |
| 11494 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11495 | int i, /* Parameter index */ |
| 11496 | void *aData, /* Pointer to array data */ |
| 11497 | int nData, /* Number of data elements */ |
| 11498 | int mFlags, /* CARRAY flags */ |
| 11499 | void (*xDel)(void*) /* Destructor for aData */ |
| 11500 | ); |
| 11501 | |
| 11502 | /* |
| 11503 | ** CAPI3REF: Datatypes for the CARRAY table-valued function |
| 11504 | ** |
| 11505 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11506 | ** one of the following constants, to specify the datatype of the array |
| 11507 | ** that is being bound into the [carray table-valued function]. |
| 11508 | */ |
| @@ -22014,11 +22028,11 @@ | |
| 22028 | SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno); |
| 22029 | SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); |
| 22030 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); |
| 22031 | SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); |
| 22032 | SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); |
| 22033 | SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); |
| 22034 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 22035 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); |
| 22036 | SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); |
| 22037 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); |
| 22038 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| @@ -39781,10 +39795,123 @@ | |
| 39795 | #endif |
| 39796 | |
| 39797 | }; /* End of the overrideable system calls */ |
| 39798 | |
| 39799 | |
| 39800 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 39801 | /* |
| 39802 | ** Extract Posix Advisory Locking information about file description fd |
| 39803 | ** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16] |
| 39804 | ** with characters to indicate which SQLite-relevant locks are held. |
| 39805 | ** a[16] will be a 15-character zero-terminated string with the following |
| 39806 | ** schema: |
| 39807 | ** |
| 39808 | ** AAA/B.DDD.DDDDD |
| 39809 | ** |
| 39810 | ** Each of character A-D will be "w" or "r" or "-" to indicate either a |
| 39811 | ** write-lock, a read-lock, or no-lock, respectively. The "." and "/" |
| 39812 | ** characters are delimiters intended to make the string more easily |
| 39813 | ** readable by humans. Here are the meaning of the specific letters: |
| 39814 | ** |
| 39815 | ** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE, |
| 39816 | ** and SHARED_FIRST, respectively. |
| 39817 | ** |
| 39818 | ** B -> The deadman switch lock. Offset 128 of the -shm file. |
| 39819 | ** |
| 39820 | ** CCC -> WAL locks: WRITE, CKPT, RECOVER |
| 39821 | ** |
| 39822 | ** DDDDD -> WAL read-locks 0 through 5 |
| 39823 | ** |
| 39824 | ** Note that elements before the "/" apply to the main database file and |
| 39825 | ** elements after the "/" apply to the -shm file in WAL mode. |
| 39826 | ** |
| 39827 | ** Here is another way of thinking about the meaning of the result string: |
| 39828 | ** |
| 39829 | ** AAA/B.CCC.DDDDD |
| 39830 | ** ||| | ||| \___/ |
| 39831 | ** PENDING--'|| | ||| `----- READ 0-5 |
| 39832 | ** RESERVED--'| | ||`---- RECOVER |
| 39833 | ** SHARED ----' | |`----- CKPT |
| 39834 | ** DMS ------' `------ WRITE |
| 39835 | ** |
| 39836 | ** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc |
| 39837 | ** pseudo-filesystem is unavailable. |
| 39838 | */ |
| 39839 | static int unixPosixAdvisoryLocks( |
| 39840 | int fd, /* The file descriptor to analyze */ |
| 39841 | char a[16] /* Write a text description of PALs here */ |
| 39842 | ){ |
| 39843 | int in; |
| 39844 | ssize_t n; |
| 39845 | char *p, *pNext, *x; |
| 39846 | char z[2000]; |
| 39847 | |
| 39848 | /* 1 */ |
| 39849 | /* 012 4 678 01234 */ |
| 39850 | memcpy(a, "---/-.---.-----", 16); |
| 39851 | sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd); |
| 39852 | in = osOpen(z, O_RDONLY, 0); |
| 39853 | if( in<0 ){ |
| 39854 | return SQLITE_ERROR_UNABLE; |
| 39855 | } |
| 39856 | n = osRead(in, z, sizeof(z)-1); |
| 39857 | osClose(in); |
| 39858 | if( n<=0 ) return SQLITE_ERROR_UNABLE; |
| 39859 | z[n] = 0; |
| 39860 | |
| 39861 | /* We are looking for lines that begin with "lock:\t". Examples: |
| 39862 | ** |
| 39863 | ** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335 |
| 39864 | ** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120 |
| 39865 | ** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123 |
| 39866 | ** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128 |
| 39867 | */ |
| 39868 | pNext = strstr(z, "lock:\t"); |
| 39869 | while( pNext ){ |
| 39870 | char cType = 0; |
| 39871 | sqlite3_int64 iFirst, iLast; |
| 39872 | p = pNext+6; |
| 39873 | pNext = strstr(p, "lock:\t"); |
| 39874 | if( pNext ) pNext[-1] = 0; |
| 39875 | if( (x = strstr(p, " READ "))!=0 ){ |
| 39876 | cType = 'r'; |
| 39877 | x += 6; |
| 39878 | }else if( (x = strstr(p, " WRITE "))!=0 ){ |
| 39879 | cType = 'w'; |
| 39880 | x += 7; |
| 39881 | }else{ |
| 39882 | continue; |
| 39883 | } |
| 39884 | x = strrchr(x, ' '); |
| 39885 | if( x==0 ) continue; |
| 39886 | iLast = strtoll(x+1, 0, 10); |
| 39887 | *x = 0; |
| 39888 | x = strrchr(p, ' '); |
| 39889 | if( x==0 ) continue; |
| 39890 | iFirst = strtoll(x+1, 0, 10); |
| 39891 | if( iLast>=PENDING_BYTE ){ |
| 39892 | if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType; |
| 39893 | if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType; |
| 39894 | if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType; |
| 39895 | }else if( iLast<=128 ){ |
| 39896 | if( iFirst<=128 && iLast>=128 ) a[4] = cType; |
| 39897 | if( iFirst<=120 && iLast>=120 ) a[6] = cType; |
| 39898 | if( iFirst<=121 && iLast>=121 ) a[7] = cType; |
| 39899 | if( iFirst<=122 && iLast>=122 ) a[8] = cType; |
| 39900 | if( iFirst<=123 && iLast>=123 ) a[10] = cType; |
| 39901 | if( iFirst<=124 && iLast>=124 ) a[11] = cType; |
| 39902 | if( iFirst<=125 && iLast>=125 ) a[12] = cType; |
| 39903 | if( iFirst<=126 && iLast>=126 ) a[13] = cType; |
| 39904 | if( iFirst<=127 && iLast>=127 ) a[14] = cType; |
| 39905 | } |
| 39906 | } |
| 39907 | return SQLITE_OK; |
| 39908 | } |
| 39909 | #else |
| 39910 | # define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE |
| 39911 | #endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ |
| 39912 | |
| 39913 | /* |
| 39914 | ** On some systems, calls to fchown() will trigger a message in a security |
| 39915 | ** log if they come from non-root processes. So avoid calling fchown() if |
| 39916 | ** we are not running as root. |
| 39917 | */ |
| @@ -40904,10 +41031,13 @@ | |
| 41031 | rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 41032 | } |
| 41033 | return rc; |
| 41034 | } |
| 41035 | |
| 41036 | /* Forward reference */ |
| 41037 | static int unixIsSharingShmNode(unixFile*); |
| 41038 | |
| 41039 | /* |
| 41040 | ** Lock the file with the lock specified by parameter eFileLock - one |
| 41041 | ** of the following: |
| 41042 | ** |
| 41043 | ** (1) SHARED_LOCK |
| @@ -41092,11 +41222,13 @@ | |
| 41222 | }else{ |
| 41223 | pFile->eFileLock = SHARED_LOCK; |
| 41224 | pInode->nLock++; |
| 41225 | pInode->nShared = 1; |
| 41226 | } |
| 41227 | }else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1) |
| 41228 | || unixIsSharingShmNode(pFile) |
| 41229 | ){ |
| 41230 | /* We are trying for an exclusive lock but another thread in this |
| 41231 | ** same process is still holding a shared lock. */ |
| 41232 | rc = SQLITE_BUSY; |
| 41233 | }else{ |
| 41234 | /* The request was for a RESERVED or EXCLUSIVE lock. It is |
| @@ -43187,10 +43319,14 @@ | |
| 43319 | /* Forward declaration */ |
| 43320 | static int unixGetTempname(int nBuf, char *zBuf); |
| 43321 | #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) |
| 43322 | static int unixFcntlExternalReader(unixFile*, int*); |
| 43323 | #endif |
| 43324 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 43325 | static void unixDescribeShm(sqlite3_str*,unixShm*); |
| 43326 | #endif |
| 43327 | |
| 43328 | |
| 43329 | /* |
| 43330 | ** Information and control of an open file handle. |
| 43331 | */ |
| 43332 | static int unixFileControl(sqlite3_file *id, int op, void *pArg){ |
| @@ -43329,10 +43465,70 @@ | |
| 43465 | #else |
| 43466 | *(int*)pArg = 0; |
| 43467 | return SQLITE_OK; |
| 43468 | #endif |
| 43469 | } |
| 43470 | |
| 43471 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 43472 | case SQLITE_FCNTL_FILESTAT: { |
| 43473 | sqlite3_str *pStr = (sqlite3_str*)pArg; |
| 43474 | char aLck[16]; |
| 43475 | unixInodeInfo *pInode; |
| 43476 | static const char *azLock[] = { "SHARED", "RESERVED", |
| 43477 | "PENDING", "EXCLUSIVE" }; |
| 43478 | sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h); |
| 43479 | sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); |
| 43480 | if( pFile->eFileLock ){ |
| 43481 | sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", |
| 43482 | azLock[pFile->eFileLock-1]); |
| 43483 | if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){ |
| 43484 | sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); |
| 43485 | } |
| 43486 | } |
| 43487 | unixEnterMutex(); |
| 43488 | if( pFile->pShm ){ |
| 43489 | sqlite3_str_appendall(pStr, ",\"shm\":"); |
| 43490 | unixDescribeShm(pStr, pFile->pShm); |
| 43491 | } |
| 43492 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 43493 | if( pFile->mmapSize ){ |
| 43494 | sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); |
| 43495 | sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); |
| 43496 | } |
| 43497 | #endif |
| 43498 | if( (pInode = pFile->pInode)!=0 ){ |
| 43499 | sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef); |
| 43500 | sqlite3_mutex_enter(pInode->pLockMutex); |
| 43501 | sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared); |
| 43502 | if( pInode->eFileLock ){ |
| 43503 | sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", |
| 43504 | azLock[pInode->eFileLock-1]); |
| 43505 | } |
| 43506 | if( pInode->pUnused ){ |
| 43507 | char cSep = '['; |
| 43508 | UnixUnusedFd *pUFd = pFile->pInode->pUnused; |
| 43509 | sqlite3_str_appendall(pStr, ",\"unusedFd\":"); |
| 43510 | while( pUFd ){ |
| 43511 | sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d", |
| 43512 | cSep, pUFd->fd, pUFd->flags); |
| 43513 | cSep = ','; |
| 43514 | if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){ |
| 43515 | sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); |
| 43516 | } |
| 43517 | sqlite3_str_append(pStr, "}", 1); |
| 43518 | pUFd = pUFd->pNext; |
| 43519 | } |
| 43520 | sqlite3_str_append(pStr, "]", 1); |
| 43521 | } |
| 43522 | sqlite3_mutex_leave(pInode->pLockMutex); |
| 43523 | sqlite3_str_append(pStr, "}", 1); |
| 43524 | } |
| 43525 | unixLeaveMutex(); |
| 43526 | sqlite3_str_append(pStr, "}", 1); |
| 43527 | return SQLITE_OK; |
| 43528 | } |
| 43529 | #endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ |
| 43530 | } |
| 43531 | return SQLITE_NOTFOUND; |
| 43532 | } |
| 43533 | |
| 43534 | /* |
| @@ -43595,10 +43791,30 @@ | |
| 43791 | ** Constants used for locking |
| 43792 | */ |
| 43793 | #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 43794 | #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 43795 | |
| 43796 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 43797 | /* |
| 43798 | ** Describe the pShm object using JSON. Used for diagnostics only. |
| 43799 | */ |
| 43800 | static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){ |
| 43801 | unixShmNode *pNode = pShm->pShmNode; |
| 43802 | char aLck[16]; |
| 43803 | sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm); |
| 43804 | assert( unixMutexHeld() ); |
| 43805 | sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef); |
| 43806 | sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id); |
| 43807 | sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask); |
| 43808 | sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask); |
| 43809 | if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){ |
| 43810 | sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); |
| 43811 | } |
| 43812 | sqlite3_str_append(pStr, "}", 1); |
| 43813 | } |
| 43814 | #endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ |
| 43815 | |
| 43816 | /* |
| 43817 | ** Use F_GETLK to check whether or not there are any readers with open |
| 43818 | ** wal-mode transactions in other processes on database file pFile. If |
| 43819 | ** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are |
| 43820 | ** such transactions, or 0 otherwise. If an error occurs, return an |
| @@ -43628,10 +43844,53 @@ | |
| 43844 | } |
| 43845 | |
| 43846 | return rc; |
| 43847 | } |
| 43848 | |
| 43849 | /* |
| 43850 | ** If pFile has a -shm file open and it is sharing that file with some |
| 43851 | ** other connection, either in the same process or in a separate process, |
| 43852 | ** then return true. Return false if either pFile does not have a -shm |
| 43853 | ** file open or if it is the only connection to that -shm file across the |
| 43854 | ** entire system. |
| 43855 | ** |
| 43856 | ** This routine is not required for correct operation. It can always return |
| 43857 | ** false and SQLite will continue to operate according to spec. However, |
| 43858 | ** when this routine does its job, it adds extra robustness in cases |
| 43859 | ** where database file locks have been erroneously deleted in a WAL-mode |
| 43860 | ** database by doing close(open(DATABASE_PATHNAME)) or similar. |
| 43861 | ** |
| 43862 | ** With false negatives, SQLite still operates to spec, though with less |
| 43863 | ** robustness. With false positives, the last database connection on a |
| 43864 | ** WAL-mode database will fail to unlink the -wal and -shm files, which |
| 43865 | ** is annoying but harmless. False positives will also prevent a database |
| 43866 | ** connection from running "PRAGMA journal_mode=DELETE" in order to take |
| 43867 | ** the database out of WAL mode, which is perhaps more serious, but is |
| 43868 | ** still not a disaster. |
| 43869 | */ |
| 43870 | static int unixIsSharingShmNode(unixFile *pFile){ |
| 43871 | int rc; |
| 43872 | unixShmNode *pShmNode; |
| 43873 | if( pFile->pShm==0 ) return 0; |
| 43874 | if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0; |
| 43875 | pShmNode = pFile->pShm->pShmNode; |
| 43876 | rc = 1; |
| 43877 | unixEnterMutex(); |
| 43878 | if( ALWAYS(pShmNode->nRef==1) ){ |
| 43879 | struct flock lock; |
| 43880 | lock.l_whence = SEEK_SET; |
| 43881 | lock.l_start = UNIX_SHM_DMS; |
| 43882 | lock.l_len = 1; |
| 43883 | lock.l_type = F_WRLCK; |
| 43884 | osFcntl(pShmNode->hShm, F_GETLK, &lock); |
| 43885 | if( lock.l_type==F_UNLCK ){ |
| 43886 | rc = 0; |
| 43887 | } |
| 43888 | } |
| 43889 | unixLeaveMutex(); |
| 43890 | return rc; |
| 43891 | } |
| 43892 | |
| 43893 | /* |
| 43894 | ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. |
| 43895 | ** |
| 43896 | ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking |
| @@ -43673,11 +43932,12 @@ | |
| 43932 | /* Shared locks never span more than one byte */ |
| 43933 | assert( n==1 || lockType!=F_RDLCK ); |
| 43934 | |
| 43935 | /* Locks are within range */ |
| 43936 | assert( n>=1 && n<=SQLITE_SHM_NLOCK ); |
| 43937 | assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS ); |
| 43938 | assert( ofst+n-1<=UNIX_SHM_DMS ); |
| 43939 | |
| 43940 | if( pShmNode->hShm>=0 ){ |
| 43941 | int res; |
| 43942 | /* Initialize the locking parameters */ |
| 43943 | f.l_type = lockType; |
| @@ -51478,10 +51738,32 @@ | |
| 51738 | int iNew = *(int*)pArg; |
| 51739 | pFile->bBlockOnConnect = iNew; |
| 51740 | return SQLITE_OK; |
| 51741 | } |
| 51742 | #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 51743 | |
| 51744 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 51745 | case SQLITE_FCNTL_FILESTAT: { |
| 51746 | sqlite3_str *pStr = (sqlite3_str*)pArg; |
| 51747 | sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h); |
| 51748 | sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); |
| 51749 | if( pFile->locktype ){ |
| 51750 | static const char *azLock[] = { "SHARED", "RESERVED", |
| 51751 | "PENDING", "EXCLUSIVE" }; |
| 51752 | sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"", |
| 51753 | azLock[pFile->locktype-1]); |
| 51754 | } |
| 51755 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 51756 | if( pFile->mmapSize ){ |
| 51757 | sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); |
| 51758 | sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); |
| 51759 | } |
| 51760 | #endif |
| 51761 | sqlite3_str_append(pStr, "}", 1); |
| 51762 | return SQLITE_OK; |
| 51763 | } |
| 51764 | #endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ |
| 51765 | |
| 51766 | } |
| 51767 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| 51768 | return SQLITE_NOTFOUND; |
| 51769 | } |
| @@ -67063,11 +67345,11 @@ | |
| 67345 | } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */ |
| 67346 | }; |
| 67347 | |
| 67348 | /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ |
| 67349 | #define SZ_WALITERATOR(N) \ |
| 67350 | (offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment)) |
| 67351 | |
| 67352 | /* |
| 67353 | ** Define the parameters of the hash tables in the wal-index file. There |
| 67354 | ** is a hash-table following every HASHTABLE_NPAGE page numbers in the |
| 67355 | ** wal-index. |
| @@ -94735,14 +95017,14 @@ | |
| 95017 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
| 95018 | ** bytes in this text up to but excluding the first character in |
| 95019 | ** a host parameter. If the text contains no host parameters, return |
| 95020 | ** the total number of bytes in the text. |
| 95021 | */ |
| 95022 | static i64 findNextHostParameter(const char *zSql, i64 *pnToken){ |
| 95023 | int tokenType; |
| 95024 | i64 nTotal = 0; |
| 95025 | i64 n; |
| 95026 | |
| 95027 | *pnToken = 0; |
| 95028 | while( zSql[0] ){ |
| 95029 | n = sqlite3GetToken((u8*)zSql, &tokenType); |
| 95030 | assert( n>0 && tokenType!=TK_ILLEGAL ); |
| @@ -94785,12 +95067,12 @@ | |
| 95067 | const char *zRawSql /* Raw text of the SQL statement */ |
| 95068 | ){ |
| 95069 | sqlite3 *db; /* The database connection */ |
| 95070 | int idx = 0; /* Index of a host parameter */ |
| 95071 | int nextIndex = 1; /* Index of next ? host parameter */ |
| 95072 | i64 n; /* Length of a token prefix */ |
| 95073 | i64 nToken; /* Length of the parameter token */ |
| 95074 | int i; /* Loop counter */ |
| 95075 | Mem *pVar; /* Value of a host parameter */ |
| 95076 | StrAccum out; /* Accumulate the output here */ |
| 95077 | #ifndef SQLITE_OMIT_UTF16 |
| 95078 | Mem utf8; /* Used to convert UTF16 into UTF8 for display */ |
| @@ -96816,10 +97098,13 @@ | |
| 97098 | nByte = pIn1->n; |
| 97099 | nByte += pIn2->n; |
| 97100 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 97101 | goto too_big; |
| 97102 | } |
| 97103 | #if SQLITE_MAX_LENGTH>2147483645 |
| 97104 | if( nByte>2147483645 ){ goto too_big; } |
| 97105 | #endif |
| 97106 | if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ |
| 97107 | goto no_mem; |
| 97108 | } |
| 97109 | MemSetTypeFlag(pOut, MEM_Str); |
| 97110 | if( pOut!=pIn2 ){ |
| @@ -131915,11 +132200,11 @@ | |
| 132200 | static void *contextMalloc(sqlite3_context *context, i64 nByte){ |
| 132201 | char *z; |
| 132202 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 132203 | assert( nByte>0 ); |
| 132204 | testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
| 132205 | testcase( nByte==(i64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
| 132206 | if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 132207 | sqlite3_result_error_toobig(context); |
| 132208 | z = 0; |
| 132209 | }else{ |
| 132210 | z = sqlite3Malloc(nByte); |
| @@ -134180,12 +134465,12 @@ | |
| 134465 | ** aggregate. Remember all input Y values until the very end. |
| 134466 | ** Those values are accumulated in the Percentile.a[] array. |
| 134467 | */ |
| 134468 | typedef struct Percentile Percentile; |
| 134469 | struct Percentile { |
| 134470 | u64 nAlloc; /* Number of slots allocated for a[] */ |
| 134471 | u64 nUsed; /* Number of slots actually used in a[] */ |
| 134472 | char bSorted; /* True if a[] is already in sorted order */ |
| 134473 | char bKeepSorted; /* True if advantageous to keep a[] sorted */ |
| 134474 | char bPctValid; /* True if rPct is valid */ |
| 134475 | double rPct; /* Fraction. 0.0 to 1.0 */ |
| 134476 | double *a; /* Array of Y values */ |
| @@ -134218,15 +134503,15 @@ | |
| 134503 | ** If bExact is false, return the index at which a new entry with |
| 134504 | ** value y should be insert in order to keep the values in sorted |
| 134505 | ** order. The smallest return value in this case will be 0, and |
| 134506 | ** the largest return value will be p->nUsed. |
| 134507 | */ |
| 134508 | static i64 percentBinarySearch(Percentile *p, double y, int bExact){ |
| 134509 | i64 iFirst = 0; /* First element of search range */ |
| 134510 | i64 iLast = (i64)p->nUsed - 1; /* Last element of search range */ |
| 134511 | while( iLast>=iFirst ){ |
| 134512 | i64 iMid = (iFirst+iLast)/2; |
| 134513 | double x = p->a[iMid]; |
| 134514 | if( x<y ){ |
| 134515 | iFirst = iMid + 1; |
| 134516 | }else if( x>y ){ |
| 134517 | iLast = iMid - 1; |
| @@ -134325,11 +134610,11 @@ | |
| 134610 | return; |
| 134611 | } |
| 134612 | |
| 134613 | /* Allocate and store the Y */ |
| 134614 | if( p->nUsed>=p->nAlloc ){ |
| 134615 | u64 n = p->nAlloc*2 + 250; |
| 134616 | double *a = sqlite3_realloc64(p->a, sizeof(double)*n); |
| 134617 | if( a==0 ){ |
| 134618 | sqlite3_free(p->a); |
| 134619 | memset(p, 0, sizeof(*p)); |
| 134620 | sqlite3_result_error_nomem(pCtx); |
| @@ -134342,11 +134627,11 @@ | |
| 134627 | p->a[p->nUsed++] = y; |
| 134628 | p->bSorted = 1; |
| 134629 | }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ |
| 134630 | p->a[p->nUsed++] = y; |
| 134631 | }else if( p->bKeepSorted ){ |
| 134632 | i64 i; |
| 134633 | i = percentBinarySearch(p, y, 0); |
| 134634 | if( i<(int)p->nUsed ){ |
| 134635 | memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); |
| 134636 | } |
| 134637 | p->a[i] = y; |
| @@ -134427,11 +134712,11 @@ | |
| 134712 | */ |
| 134713 | static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){ |
| 134714 | Percentile *p; |
| 134715 | int eType; |
| 134716 | double y; |
| 134717 | i64 i; |
| 134718 | assert( argc==2 || argc==1 ); |
| 134719 | |
| 134720 | /* Allocate the session context. */ |
| 134721 | p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); |
| 134722 | assert( p!=0 ); |
| @@ -134513,10 +134798,60 @@ | |
| 134798 | percentCompute(pCtx, 0); |
| 134799 | } |
| 134800 | /****** End of percentile family of functions ******/ |
| 134801 | #endif /* SQLITE_ENABLE_PERCENTILE */ |
| 134802 | |
| 134803 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 134804 | /* |
| 134805 | ** Implementation of sqlite_filestat(SCHEMA). |
| 134806 | ** |
| 134807 | ** Return JSON text that describes low-level debug/diagnostic information |
| 134808 | ** about the sqlite3_file object associated with SCHEMA. |
| 134809 | */ |
| 134810 | static void filestatFunc( |
| 134811 | sqlite3_context *context, |
| 134812 | int argc, |
| 134813 | sqlite3_value **argv |
| 134814 | ){ |
| 134815 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 134816 | const char *zDbName; |
| 134817 | sqlite3_str *pStr; |
| 134818 | Btree *pBtree; |
| 134819 | |
| 134820 | zDbName = (const char*)sqlite3_value_text(argv[0]); |
| 134821 | pBtree = sqlite3DbNameToBtree(db, zDbName); |
| 134822 | if( pBtree ){ |
| 134823 | Pager *pPager; |
| 134824 | sqlite3_file *fd; |
| 134825 | int rc; |
| 134826 | sqlite3BtreeEnter(pBtree); |
| 134827 | pPager = sqlite3BtreePager(pBtree); |
| 134828 | assert( pPager!=0 ); |
| 134829 | fd = sqlite3PagerFile(pPager); |
| 134830 | pStr = sqlite3_str_new(db); |
| 134831 | if( pStr==0 ){ |
| 134832 | sqlite3_result_error_nomem(context); |
| 134833 | }else{ |
| 134834 | sqlite3_str_append(pStr, "{\"db\":", 6); |
| 134835 | rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); |
| 134836 | if( rc ) sqlite3_str_append(pStr, "null", 4); |
| 134837 | fd = sqlite3PagerJrnlFile(pPager); |
| 134838 | if( fd && fd->pMethods!=0 ){ |
| 134839 | sqlite3_str_appendall(pStr, ",\"journal\":"); |
| 134840 | rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); |
| 134841 | if( rc ) sqlite3_str_append(pStr, "null", 4); |
| 134842 | } |
| 134843 | sqlite3_str_append(pStr, "}", 1); |
| 134844 | sqlite3_result_text(context, sqlite3_str_finish(pStr), -1, |
| 134845 | sqlite3_free); |
| 134846 | } |
| 134847 | sqlite3BtreeLeave(pBtree); |
| 134848 | }else{ |
| 134849 | sqlite3_result_text(context, "{}", 2, SQLITE_STATIC); |
| 134850 | } |
| 134851 | } |
| 134852 | #endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ |
| 134853 | |
| 134854 | #ifdef SQLITE_DEBUG |
| 134855 | /* |
| 134856 | ** Implementation of fpdecode(x,y,z) function. |
| 134857 | ** |
| @@ -134672,10 +135007,13 @@ | |
| 135007 | INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 135008 | INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), |
| 135009 | #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC |
| 135010 | INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ), |
| 135011 | #endif |
| 135012 | #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) |
| 135013 | FUNCTION(sqlite_filestat, 1, 0, 0, filestatFunc ), |
| 135014 | #endif |
| 135015 | FUNCTION(ltrim, 1, 1, 0, trimFunc ), |
| 135016 | FUNCTION(ltrim, 2, 1, 0, trimFunc ), |
| 135017 | FUNCTION(rtrim, 1, 2, 0, trimFunc ), |
| 135018 | FUNCTION(rtrim, 2, 2, 0, trimFunc ), |
| 135019 | FUNCTION(trim, 1, 3, 0, trimFunc ), |
| @@ -183458,12 +183796,13 @@ | |
| 183796 | |
| 183797 | /* |
| 183798 | ** Return the length (in bytes) of the token that begins at z[0]. |
| 183799 | ** Store the token type in *tokenType before returning. |
| 183800 | */ |
| 183801 | SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 183802 | i64 i; |
| 183803 | int c; |
| 183804 | switch( aiClass[*z] ){ /* Switch on the character-class of the first byte |
| 183805 | ** of the token. See the comment on the CC_ defines |
| 183806 | ** above. */ |
| 183807 | case CC_SPACE: { |
| 183808 | testcase( z[0]==' ' ); |
| @@ -183787,11 +184126,11 @@ | |
| 184126 | ** Run the parser on the given SQL string. |
| 184127 | */ |
| 184128 | SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ |
| 184129 | int nErr = 0; /* Number of errors encountered */ |
| 184130 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 184131 | i64 n = 0; /* Length of the next token token */ |
| 184132 | int tokenType; /* type of the next token */ |
| 184133 | int lastTokenParsed = -1; /* type of the previous token */ |
| 184134 | sqlite3 *db = pParse->db; /* The database connection */ |
| 184135 | int mxSqlLen; /* Max length of an SQL string */ |
| 184136 | Parse *pParentParse = 0; /* Outer parse context, if any */ |
| @@ -183890,17 +184229,17 @@ | |
| 184229 | zSql += n; |
| 184230 | continue; |
| 184231 | }else if( tokenType!=TK_QNUMBER ){ |
| 184232 | Token x; |
| 184233 | x.z = zSql; |
| 184234 | x.n = (u32)n; |
| 184235 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); |
| 184236 | break; |
| 184237 | } |
| 184238 | } |
| 184239 | pParse->sLastToken.z = zSql; |
| 184240 | pParse->sLastToken.n = (u32)n; |
| 184241 | sqlite3Parser(pEngine, tokenType, pParse->sLastToken); |
| 184242 | lastTokenParsed = tokenType; |
| 184243 | zSql += n; |
| 184244 | assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); |
| 184245 | if( pParse->rc!=SQLITE_OK ) break; |
| @@ -183972,11 +184311,11 @@ | |
| 184311 | Vdbe *pVdbe, /* VM being reprepared */ |
| 184312 | const char *zSql /* The original SQL string */ |
| 184313 | ){ |
| 184314 | sqlite3 *db; /* The database connection */ |
| 184315 | int i; /* Next unread byte of zSql[] */ |
| 184316 | i64 n; /* length of current token */ |
| 184317 | int tokenType; /* type of current token */ |
| 184318 | int prevType = 0; /* Previous non-whitespace token */ |
| 184319 | int nParen; /* Number of nested levels of parentheses */ |
| 184320 | int iStartIN; /* Start of RHS of IN operator in z[] */ |
| 184321 | int nParenAtIN; /* Value of nParent at start of RHS of IN operator */ |
| @@ -215365,11 +215704,11 @@ | |
| 215704 | /* #include "sqlite3ext.h" */ |
| 215705 | SQLITE_EXTENSION_INIT1 |
| 215706 | #else |
| 215707 | /* #include "sqlite3.h" */ |
| 215708 | #endif |
| 215709 | SQLITE_PRIVATE sqlite3_int64 sqlite3GetToken(const unsigned char*,int*); /* In SQLite core */ |
| 215710 | |
| 215711 | /* #include <stddef.h> */ |
| 215712 | |
| 215713 | /* |
| 215714 | ** If building separately, we will need some setup that is normally |
| @@ -229904,11 +230243,12 @@ | |
| 230243 | if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ |
| 230244 | unsigned char *aPage = sqlite3PagerGetData(pDbPage); |
| 230245 | memcpy(aPage, pData, szPage); |
| 230246 | pTab->pgnoTrunc = 0; |
| 230247 | } |
| 230248 | } |
| 230249 | if( rc!=SQLITE_OK ){ |
| 230250 | pTab->pgnoTrunc = 0; |
| 230251 | } |
| 230252 | sqlite3PagerUnref(pDbPage); |
| 230253 | return rc; |
| 230254 | |
| @@ -259926,11 +260266,11 @@ | |
| 260266 | int nArg, /* Number of args */ |
| 260267 | sqlite3_value **apUnused /* Function arguments */ |
| 260268 | ){ |
| 260269 | assert( nArg==0 ); |
| 260270 | UNUSED_PARAM2(nArg, apUnused); |
| 260271 | sqlite3_result_text(pCtx, "fts5: 2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060", -1, SQLITE_TRANSIENT); |
| 260272 | } |
| 260273 | |
| 260274 | /* |
| 260275 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 260276 | ** |
| 260277 |
+23
-9
| --- extsrc/sqlite3.h | ||
| +++ extsrc/sqlite3.h | ||
| @@ -146,14 +146,14 @@ | ||
| 146 | 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | 148 | */ |
| 149 | 149 | #define SQLITE_VERSION "3.51.0" |
| 150 | 150 | #define SQLITE_VERSION_NUMBER 3051000 |
| 151 | -#define SQLITE_SOURCE_ID "2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70" | |
| 151 | +#define SQLITE_SOURCE_ID "2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060" | |
| 152 | 152 | #define SQLITE_SCM_BRANCH "trunk" |
| 153 | 153 | #define SQLITE_SCM_TAGS "" |
| 154 | -#define SQLITE_SCM_DATETIME "2025-10-15T10:52:45.276Z" | |
| 154 | +#define SQLITE_SCM_DATETIME "2025-10-28T13:24:50.858Z" | |
| 155 | 155 | |
| 156 | 156 | /* |
| 157 | 157 | ** CAPI3REF: Run-Time Library Version Numbers |
| 158 | 158 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 159 | 159 | ** |
| @@ -930,11 +930,11 @@ | ||
| 930 | 930 | ** to the [sqlite3_file] object associated with the journal file (either |
| 931 | 931 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 932 | 932 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 933 | 933 | ** |
| 934 | 934 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 935 | -** No longer in use. | |
| 935 | +** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. | |
| 936 | 936 | ** |
| 937 | 937 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 938 | 938 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 939 | 939 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 940 | 940 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1227,10 +1227,19 @@ | ||
| 1227 | 1227 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1228 | 1228 | ** If there is currently no transaction open on the database, and the |
| 1229 | 1229 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1230 | 1230 | ** purges the contents of the in-memory page cache. If there is an open |
| 1231 | 1231 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1232 | +** | |
| 1233 | +** <li>[[SQLITE_FCNTL_FILESTAT]] | |
| 1234 | +** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information | |
| 1235 | +** about the [sqlite3_file] objects used access the database and journal files | |
| 1236 | +** for the given schema. The fourth parameter to [sqlite3_file_control()] | |
| 1237 | +** should be an initialized [sqlite3_str] pointer. JSON text describing | |
| 1238 | +** various aspects of the sqlite3_file object is appended to the sqlite3_str. | |
| 1239 | +** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time | |
| 1240 | +** options are used to enable it. | |
| 1232 | 1241 | ** </ul> |
| 1233 | 1242 | */ |
| 1234 | 1243 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1235 | 1244 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1236 | 1245 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1272,10 +1281,11 @@ | ||
| 1272 | 1281 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1273 | 1282 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1274 | 1283 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1275 | 1284 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1276 | 1285 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1286 | +#define SQLITE_FCNTL_FILESTAT 45 | |
| 1277 | 1287 | |
| 1278 | 1288 | /* deprecated names */ |
| 1279 | 1289 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1280 | 1290 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1281 | 1291 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -4905,13 +4915,15 @@ | ||
| 4905 | 4915 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 4906 | 4916 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 4907 | 4917 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 4908 | 4918 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 4909 | 4919 | ** destructor D with a single argument of P when it is finished using |
| 4910 | -** P. The T parameter should be a static string, preferably a string | |
| 4911 | -** literal. The sqlite3_bind_pointer() routine is part of the | |
| 4912 | -** [pointer passing interface] added for SQLite 3.20.0. | |
| 4920 | +** P, even if the call to sqlite3_bind_pointer() fails. Due to a | |
| 4921 | +** historical design quirk, results are undefined if D is | |
| 4922 | +** SQLITE_TRANSIENT. The T parameter should be a static string, | |
| 4923 | +** preferably a string literal. The sqlite3_bind_pointer() routine is | |
| 4924 | +** part of the [pointer passing interface] added for SQLite 3.20.0. | |
| 4913 | 4925 | ** |
| 4914 | 4926 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 4915 | 4927 | ** for the [prepared statement] or with a prepared statement for which |
| 4916 | 4928 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 4917 | 4929 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11151,23 +11163,25 @@ | ||
| 11151 | 11163 | ** array to be bound, and N is the number of eements in the array. The |
| 11152 | 11164 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11153 | 11165 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11154 | 11166 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11155 | 11167 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11156 | -** after it has finished using P. | |
| 11168 | +** after it has finished using P, even if the call to | |
| 11169 | +** sqlite3_carray_bind() fails. The special-case finalizer | |
| 11170 | +** SQLITE_TRANSIENT has no effect here. | |
| 11157 | 11171 | */ |
| 11158 | -SQLITE_API SQLITE_API int sqlite3_carray_bind( | |
| 11172 | +SQLITE_API int sqlite3_carray_bind( | |
| 11159 | 11173 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11160 | 11174 | int i, /* Parameter index */ |
| 11161 | 11175 | void *aData, /* Pointer to array data */ |
| 11162 | 11176 | int nData, /* Number of data elements */ |
| 11163 | 11177 | int mFlags, /* CARRAY flags */ |
| 11164 | 11178 | void (*xDel)(void*) /* Destructor for aData */ |
| 11165 | 11179 | ); |
| 11166 | 11180 | |
| 11167 | 11181 | /* |
| 11168 | -** CAPI3REF: Datatypes for the CARRAY table-valued funtion | |
| 11182 | +** CAPI3REF: Datatypes for the CARRAY table-valued function | |
| 11169 | 11183 | ** |
| 11170 | 11184 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11171 | 11185 | ** one of the following constants, to specify the datatype of the array |
| 11172 | 11186 | ** that is being bound into the [carray table-valued function]. |
| 11173 | 11187 | */ |
| 11174 | 11188 |
| --- extsrc/sqlite3.h | |
| +++ extsrc/sqlite3.h | |
| @@ -146,14 +146,14 @@ | |
| 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | */ |
| 149 | #define SQLITE_VERSION "3.51.0" |
| 150 | #define SQLITE_VERSION_NUMBER 3051000 |
| 151 | #define SQLITE_SOURCE_ID "2025-10-15 10:52:45 5cbccab499bc3983aac1f57355552db607dee6c7ef4eb00d794dbee89c18db70" |
| 152 | #define SQLITE_SCM_BRANCH "trunk" |
| 153 | #define SQLITE_SCM_TAGS "" |
| 154 | #define SQLITE_SCM_DATETIME "2025-10-15T10:52:45.276Z" |
| 155 | |
| 156 | /* |
| 157 | ** CAPI3REF: Run-Time Library Version Numbers |
| 158 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 159 | ** |
| @@ -930,11 +930,11 @@ | |
| 930 | ** to the [sqlite3_file] object associated with the journal file (either |
| 931 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 932 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 933 | ** |
| 934 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 935 | ** No longer in use. |
| 936 | ** |
| 937 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 938 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 939 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 940 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1227,10 +1227,19 @@ | |
| 1227 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1228 | ** If there is currently no transaction open on the database, and the |
| 1229 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1230 | ** purges the contents of the in-memory page cache. If there is an open |
| 1231 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1232 | ** </ul> |
| 1233 | */ |
| 1234 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1235 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1236 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1272,10 +1281,11 @@ | |
| 1272 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1273 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1274 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1275 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1276 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1277 | |
| 1278 | /* deprecated names */ |
| 1279 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1280 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1281 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -4905,13 +4915,15 @@ | |
| 4905 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 4906 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 4907 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 4908 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 4909 | ** destructor D with a single argument of P when it is finished using |
| 4910 | ** P. The T parameter should be a static string, preferably a string |
| 4911 | ** literal. The sqlite3_bind_pointer() routine is part of the |
| 4912 | ** [pointer passing interface] added for SQLite 3.20.0. |
| 4913 | ** |
| 4914 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 4915 | ** for the [prepared statement] or with a prepared statement for which |
| 4916 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 4917 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11151,23 +11163,25 @@ | |
| 11151 | ** array to be bound, and N is the number of eements in the array. The |
| 11152 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11153 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11154 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11155 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11156 | ** after it has finished using P. |
| 11157 | */ |
| 11158 | SQLITE_API SQLITE_API int sqlite3_carray_bind( |
| 11159 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11160 | int i, /* Parameter index */ |
| 11161 | void *aData, /* Pointer to array data */ |
| 11162 | int nData, /* Number of data elements */ |
| 11163 | int mFlags, /* CARRAY flags */ |
| 11164 | void (*xDel)(void*) /* Destructor for aData */ |
| 11165 | ); |
| 11166 | |
| 11167 | /* |
| 11168 | ** CAPI3REF: Datatypes for the CARRAY table-valued funtion |
| 11169 | ** |
| 11170 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11171 | ** one of the following constants, to specify the datatype of the array |
| 11172 | ** that is being bound into the [carray table-valued function]. |
| 11173 | */ |
| 11174 |
| --- extsrc/sqlite3.h | |
| +++ extsrc/sqlite3.h | |
| @@ -146,14 +146,14 @@ | |
| 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | */ |
| 149 | #define SQLITE_VERSION "3.51.0" |
| 150 | #define SQLITE_VERSION_NUMBER 3051000 |
| 151 | #define SQLITE_SOURCE_ID "2025-10-28 13:24:50 724f2299f206cc9e7f830f984c50a8fc4ac1c17210d71d9affe657b45252b060" |
| 152 | #define SQLITE_SCM_BRANCH "trunk" |
| 153 | #define SQLITE_SCM_TAGS "" |
| 154 | #define SQLITE_SCM_DATETIME "2025-10-28T13:24:50.858Z" |
| 155 | |
| 156 | /* |
| 157 | ** CAPI3REF: Run-Time Library Version Numbers |
| 158 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 159 | ** |
| @@ -930,11 +930,11 @@ | |
| 930 | ** to the [sqlite3_file] object associated with the journal file (either |
| 931 | ** the [rollback journal] or the [write-ahead log]) for a particular database |
| 932 | ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. |
| 933 | ** |
| 934 | ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] |
| 935 | ** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. |
| 936 | ** |
| 937 | ** <li>[[SQLITE_FCNTL_SYNC]] |
| 938 | ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and |
| 939 | ** sent to the VFS immediately before the xSync method is invoked on a |
| 940 | ** database file descriptor. Or, if the xSync method is not invoked |
| @@ -1227,10 +1227,19 @@ | |
| 1227 | ** <li>[[SQLITE_FCNTL_RESET_CACHE]] |
| 1228 | ** If there is currently no transaction open on the database, and the |
| 1229 | ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control |
| 1230 | ** purges the contents of the in-memory page cache. If there is an open |
| 1231 | ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. |
| 1232 | ** |
| 1233 | ** <li>[[SQLITE_FCNTL_FILESTAT]] |
| 1234 | ** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information |
| 1235 | ** about the [sqlite3_file] objects used access the database and journal files |
| 1236 | ** for the given schema. The fourth parameter to [sqlite3_file_control()] |
| 1237 | ** should be an initialized [sqlite3_str] pointer. JSON text describing |
| 1238 | ** various aspects of the sqlite3_file object is appended to the sqlite3_str. |
| 1239 | ** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time |
| 1240 | ** options are used to enable it. |
| 1241 | ** </ul> |
| 1242 | */ |
| 1243 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 1244 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 1245 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| @@ -1272,10 +1281,11 @@ | |
| 1281 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1282 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1283 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1284 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1285 | #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1286 | #define SQLITE_FCNTL_FILESTAT 45 |
| 1287 | |
| 1288 | /* deprecated names */ |
| 1289 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1290 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1291 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -4905,13 +4915,15 @@ | |
| 4915 | ** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in |
| 4916 | ** [prepared statement] S to have an SQL value of NULL, but to also be |
| 4917 | ** associated with the pointer P of type T. ^D is either a NULL pointer or |
| 4918 | ** a pointer to a destructor function for P. ^SQLite will invoke the |
| 4919 | ** destructor D with a single argument of P when it is finished using |
| 4920 | ** P, even if the call to sqlite3_bind_pointer() fails. Due to a |
| 4921 | ** historical design quirk, results are undefined if D is |
| 4922 | ** SQLITE_TRANSIENT. The T parameter should be a static string, |
| 4923 | ** preferably a string literal. The sqlite3_bind_pointer() routine is |
| 4924 | ** part of the [pointer passing interface] added for SQLite 3.20.0. |
| 4925 | ** |
| 4926 | ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer |
| 4927 | ** for the [prepared statement] or with a prepared statement for which |
| 4928 | ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], |
| 4929 | ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() |
| @@ -11151,23 +11163,25 @@ | |
| 11163 | ** array to be bound, and N is the number of eements in the array. The |
| 11164 | ** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], |
| 11165 | ** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to |
| 11166 | ** indicate the datatype of the array being bound. The X argument is not a |
| 11167 | ** NULL pointer, then SQLite will invoke the function X on the P parameter |
| 11168 | ** after it has finished using P, even if the call to |
| 11169 | ** sqlite3_carray_bind() fails. The special-case finalizer |
| 11170 | ** SQLITE_TRANSIENT has no effect here. |
| 11171 | */ |
| 11172 | SQLITE_API int sqlite3_carray_bind( |
| 11173 | sqlite3_stmt *pStmt, /* Statement to be bound */ |
| 11174 | int i, /* Parameter index */ |
| 11175 | void *aData, /* Pointer to array data */ |
| 11176 | int nData, /* Number of data elements */ |
| 11177 | int mFlags, /* CARRAY flags */ |
| 11178 | void (*xDel)(void*) /* Destructor for aData */ |
| 11179 | ); |
| 11180 | |
| 11181 | /* |
| 11182 | ** CAPI3REF: Datatypes for the CARRAY table-valued function |
| 11183 | ** |
| 11184 | ** The fifth argument to the [sqlite3_carray_bind()] interface musts be |
| 11185 | ** one of the following constants, to specify the datatype of the array |
| 11186 | ** that is being bound into the [carray table-valued function]. |
| 11187 | */ |
| 11188 |
+16
-4
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -18,10 +18,22 @@ | ||
| 18 | 18 | ** This file contains code used to create new branches within a repository. |
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include "branch.h" |
| 22 | 22 | #include <assert.h> |
| 23 | + | |
| 24 | +/* | |
| 25 | +** Return the name of the main branch. Cache the result. | |
| 26 | +** | |
| 27 | +** This is the current value of the "main-branch" setting, or its default | |
| 28 | +** value (historically, and as of 2025-10-28: "trunk") if not set. | |
| 29 | +*/ | |
| 30 | +const char *db_main_branch(void){ | |
| 31 | + static char *zMainBranch = 0; | |
| 32 | + if( zMainBranch==0 ) zMainBranch = db_get("main-branch", 0); | |
| 33 | + return zMainBranch; | |
| 34 | +} | |
| 23 | 35 | |
| 24 | 36 | /* |
| 25 | 37 | ** Return true if zBr is the branch name associated with check-in with |
| 26 | 38 | ** blob.uuid value of zUuid |
| 27 | 39 | */ |
| @@ -53,13 +65,11 @@ | ||
| 53 | 65 | if( db_step(&q)==SQLITE_ROW ){ |
| 54 | 66 | zBr = fossil_strdup(db_column_text(&q,0)); |
| 55 | 67 | } |
| 56 | 68 | db_reset(&q); |
| 57 | 69 | if( zBr==0 ){ |
| 58 | - static char *zMain = 0; | |
| 59 | - if( zMain==0 ) zMain = db_get("main-branch",0); | |
| 60 | - zBr = fossil_strdup(zMain); | |
| 70 | + zBr = fossil_strdup(db_main_branch()); | |
| 61 | 71 | } |
| 62 | 72 | return zBr; |
| 63 | 73 | } |
| 64 | 74 | |
| 65 | 75 | /* |
| @@ -837,18 +847,20 @@ | ||
| 837 | 847 | */ |
| 838 | 848 | static void new_brlist_page(void){ |
| 839 | 849 | Stmt q; |
| 840 | 850 | double rNow; |
| 841 | 851 | int show_colors = PB("colors"); |
| 852 | + const char *zMainBranch; | |
| 842 | 853 | login_check_credentials(); |
| 843 | 854 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 844 | 855 | style_set_current_feature("branch"); |
| 845 | 856 | style_header("Branches"); |
| 846 | 857 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 847 | 858 | style_submenu_checkbox("colors", "Use Branch Colors", 0, 0); |
| 848 | 859 | |
| 849 | 860 | login_anonymous_available(); |
| 861 | + zMainBranch = db_main_branch(); | |
| 850 | 862 | |
| 851 | 863 | brlist_create_temp_table(); |
| 852 | 864 | db_prepare(&q, "SELECT * FROM tmp_brlist ORDER BY mtime DESC"); |
| 853 | 865 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 854 | 866 | @ <script id="brlist-data" type="application/json">\ |
| @@ -873,11 +885,11 @@ | ||
| 873 | 885 | char *zAge = human_readable_age(rNow - rMtime); |
| 874 | 886 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 875 | 887 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 876 | 888 | if( zBgClr ) zBgClr = reasonable_bg_color(zBgClr, 0); |
| 877 | 889 | if( zBgClr==0 ){ |
| 878 | - if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ | |
| 890 | + if( zBranch==0 || strcmp(zBranch, zMainBranch)==0 ){ | |
| 879 | 891 | zBgClr = 0; |
| 880 | 892 | }else{ |
| 881 | 893 | zBgClr = hash_color(zBranch); |
| 882 | 894 | } |
| 883 | 895 | } |
| 884 | 896 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -18,10 +18,22 @@ | |
| 18 | ** This file contains code used to create new branches within a repository. |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include "branch.h" |
| 22 | #include <assert.h> |
| 23 | |
| 24 | /* |
| 25 | ** Return true if zBr is the branch name associated with check-in with |
| 26 | ** blob.uuid value of zUuid |
| 27 | */ |
| @@ -53,13 +65,11 @@ | |
| 53 | if( db_step(&q)==SQLITE_ROW ){ |
| 54 | zBr = fossil_strdup(db_column_text(&q,0)); |
| 55 | } |
| 56 | db_reset(&q); |
| 57 | if( zBr==0 ){ |
| 58 | static char *zMain = 0; |
| 59 | if( zMain==0 ) zMain = db_get("main-branch",0); |
| 60 | zBr = fossil_strdup(zMain); |
| 61 | } |
| 62 | return zBr; |
| 63 | } |
| 64 | |
| 65 | /* |
| @@ -837,18 +847,20 @@ | |
| 837 | */ |
| 838 | static void new_brlist_page(void){ |
| 839 | Stmt q; |
| 840 | double rNow; |
| 841 | int show_colors = PB("colors"); |
| 842 | login_check_credentials(); |
| 843 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 844 | style_set_current_feature("branch"); |
| 845 | style_header("Branches"); |
| 846 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 847 | style_submenu_checkbox("colors", "Use Branch Colors", 0, 0); |
| 848 | |
| 849 | login_anonymous_available(); |
| 850 | |
| 851 | brlist_create_temp_table(); |
| 852 | db_prepare(&q, "SELECT * FROM tmp_brlist ORDER BY mtime DESC"); |
| 853 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 854 | @ <script id="brlist-data" type="application/json">\ |
| @@ -873,11 +885,11 @@ | |
| 873 | char *zAge = human_readable_age(rNow - rMtime); |
| 874 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 875 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 876 | if( zBgClr ) zBgClr = reasonable_bg_color(zBgClr, 0); |
| 877 | if( zBgClr==0 ){ |
| 878 | if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ |
| 879 | zBgClr = 0; |
| 880 | }else{ |
| 881 | zBgClr = hash_color(zBranch); |
| 882 | } |
| 883 | } |
| 884 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -18,10 +18,22 @@ | |
| 18 | ** This file contains code used to create new branches within a repository. |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include "branch.h" |
| 22 | #include <assert.h> |
| 23 | |
| 24 | /* |
| 25 | ** Return the name of the main branch. Cache the result. |
| 26 | ** |
| 27 | ** This is the current value of the "main-branch" setting, or its default |
| 28 | ** value (historically, and as of 2025-10-28: "trunk") if not set. |
| 29 | */ |
| 30 | const char *db_main_branch(void){ |
| 31 | static char *zMainBranch = 0; |
| 32 | if( zMainBranch==0 ) zMainBranch = db_get("main-branch", 0); |
| 33 | return zMainBranch; |
| 34 | } |
| 35 | |
| 36 | /* |
| 37 | ** Return true if zBr is the branch name associated with check-in with |
| 38 | ** blob.uuid value of zUuid |
| 39 | */ |
| @@ -53,13 +65,11 @@ | |
| 65 | if( db_step(&q)==SQLITE_ROW ){ |
| 66 | zBr = fossil_strdup(db_column_text(&q,0)); |
| 67 | } |
| 68 | db_reset(&q); |
| 69 | if( zBr==0 ){ |
| 70 | zBr = fossil_strdup(db_main_branch()); |
| 71 | } |
| 72 | return zBr; |
| 73 | } |
| 74 | |
| 75 | /* |
| @@ -837,18 +847,20 @@ | |
| 847 | */ |
| 848 | static void new_brlist_page(void){ |
| 849 | Stmt q; |
| 850 | double rNow; |
| 851 | int show_colors = PB("colors"); |
| 852 | const char *zMainBranch; |
| 853 | login_check_credentials(); |
| 854 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 855 | style_set_current_feature("branch"); |
| 856 | style_header("Branches"); |
| 857 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 858 | style_submenu_checkbox("colors", "Use Branch Colors", 0, 0); |
| 859 | |
| 860 | login_anonymous_available(); |
| 861 | zMainBranch = db_main_branch(); |
| 862 | |
| 863 | brlist_create_temp_table(); |
| 864 | db_prepare(&q, "SELECT * FROM tmp_brlist ORDER BY mtime DESC"); |
| 865 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 866 | @ <script id="brlist-data" type="application/json">\ |
| @@ -873,11 +885,11 @@ | |
| 885 | char *zAge = human_readable_age(rNow - rMtime); |
| 886 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 887 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 888 | if( zBgClr ) zBgClr = reasonable_bg_color(zBgClr, 0); |
| 889 | if( zBgClr==0 ){ |
| 890 | if( zBranch==0 || strcmp(zBranch, zMainBranch)==0 ){ |
| 891 | zBgClr = 0; |
| 892 | }else{ |
| 893 | zBgClr = hash_color(zBranch); |
| 894 | } |
| 895 | } |
| 896 |
+2
-2
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -127,11 +127,11 @@ | ||
| 127 | 127 | ** |
| 128 | 128 | ** * Links to files go to /doc (showing the file content directly, |
| 129 | 129 | ** depending on mimetype) rather than to /file (which always shows |
| 130 | 130 | ** the file embedded in a standard Fossil page frame). |
| 131 | 131 | ** |
| 132 | -** * The submenu and the page title is now show. The page is plain. | |
| 132 | +** * The submenu and the page title is not shown. The page is plain. | |
| 133 | 133 | ** |
| 134 | 134 | ** The /docdir page is a shorthand for /dir with the "dx" query parameter. |
| 135 | 135 | ** |
| 136 | 136 | ** Query parameters: |
| 137 | 137 | ** |
| @@ -192,11 +192,11 @@ | ||
| 192 | 192 | |
| 193 | 193 | /* If a specific check-in is requested, fetch and parse it. If the |
| 194 | 194 | ** specific check-in does not exist, clear zCI. zCI==0 will cause all |
| 195 | 195 | ** files from all check-ins to be displayed. |
| 196 | 196 | */ |
| 197 | - if( bDocDir && zCI==0 ) zCI = "trunk"; | |
| 197 | + if( bDocDir && zCI==0 ) zCI = db_main_branch(); | |
| 198 | 198 | if( zCI ){ |
| 199 | 199 | pM = manifest_get_by_name(zCI, &rid); |
| 200 | 200 | if( pM ){ |
| 201 | 201 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 202 | 202 | isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0); |
| 203 | 203 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -127,11 +127,11 @@ | |
| 127 | ** |
| 128 | ** * Links to files go to /doc (showing the file content directly, |
| 129 | ** depending on mimetype) rather than to /file (which always shows |
| 130 | ** the file embedded in a standard Fossil page frame). |
| 131 | ** |
| 132 | ** * The submenu and the page title is now show. The page is plain. |
| 133 | ** |
| 134 | ** The /docdir page is a shorthand for /dir with the "dx" query parameter. |
| 135 | ** |
| 136 | ** Query parameters: |
| 137 | ** |
| @@ -192,11 +192,11 @@ | |
| 192 | |
| 193 | /* If a specific check-in is requested, fetch and parse it. If the |
| 194 | ** specific check-in does not exist, clear zCI. zCI==0 will cause all |
| 195 | ** files from all check-ins to be displayed. |
| 196 | */ |
| 197 | if( bDocDir && zCI==0 ) zCI = "trunk"; |
| 198 | if( zCI ){ |
| 199 | pM = manifest_get_by_name(zCI, &rid); |
| 200 | if( pM ){ |
| 201 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 202 | isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0); |
| 203 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -127,11 +127,11 @@ | |
| 127 | ** |
| 128 | ** * Links to files go to /doc (showing the file content directly, |
| 129 | ** depending on mimetype) rather than to /file (which always shows |
| 130 | ** the file embedded in a standard Fossil page frame). |
| 131 | ** |
| 132 | ** * The submenu and the page title is not shown. The page is plain. |
| 133 | ** |
| 134 | ** The /docdir page is a shorthand for /dir with the "dx" query parameter. |
| 135 | ** |
| 136 | ** Query parameters: |
| 137 | ** |
| @@ -192,11 +192,11 @@ | |
| 192 | |
| 193 | /* If a specific check-in is requested, fetch and parse it. If the |
| 194 | ** specific check-in does not exist, clear zCI. zCI==0 will cause all |
| 195 | ** files from all check-ins to be displayed. |
| 196 | */ |
| 197 | if( bDocDir && zCI==0 ) zCI = db_main_branch(); |
| 198 | if( zCI ){ |
| 199 | pM = manifest_get_by_name(zCI, &rid); |
| 200 | if( pM ){ |
| 201 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 202 | isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0); |
| 203 |
+3
-2
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -1627,19 +1627,20 @@ | ||
| 1627 | 1627 | int dryRunFlag /* True for a dry-run only */ |
| 1628 | 1628 | ){ |
| 1629 | 1629 | Blob *pDesc; |
| 1630 | 1630 | char *zTags; |
| 1631 | 1631 | char *zFilename; |
| 1632 | + const char *zMainBranch = db_main_branch(); | |
| 1632 | 1633 | Blob desc; |
| 1633 | 1634 | blob_init(&desc, 0, 0); |
| 1634 | 1635 | pDesc = &desc; |
| 1635 | 1636 | blob_appendf(pDesc, "checkout %s\n", g.zLocalRoot); |
| 1636 | 1637 | blob_appendf(pDesc, "repository %s\n", g.zRepositoryName); |
| 1637 | 1638 | blob_appendf(pDesc, "user %s\n", |
| 1638 | 1639 | p->zUserOvrd ? p->zUserOvrd : login_name()); |
| 1639 | 1640 | blob_appendf(pDesc, "branch %s\n", |
| 1640 | - (p->zBranch && p->zBranch[0]) ? p->zBranch : "trunk"); | |
| 1641 | + (p->zBranch && p->zBranch[0]) ? p->zBranch : zMainBranch); | |
| 1641 | 1642 | zTags = info_tags_of_checkin(parent_rid, 1); |
| 1642 | 1643 | if( zTags || p->azTag ){ |
| 1643 | 1644 | blob_append(pDesc, "tags ", -1); |
| 1644 | 1645 | if(zTags){ |
| 1645 | 1646 | blob_appendf(pDesc, "%z%s", zTags, p->azTag ? ", " : ""); |
| @@ -2624,11 +2625,11 @@ | ||
| 2624 | 2625 | /* Get the ID of the parent manifest artifact */ |
| 2625 | 2626 | vid = db_lget_int("checkout", 0); |
| 2626 | 2627 | if( vid==0 ){ |
| 2627 | 2628 | useCksum = 1; |
| 2628 | 2629 | if( privateFlag==0 && sCiInfo.zBranch==0 ) { |
| 2629 | - sCiInfo.zBranch=db_get("main-branch", 0); | |
| 2630 | + sCiInfo.zBranch = db_main_branch(); | |
| 2630 | 2631 | } |
| 2631 | 2632 | }else{ |
| 2632 | 2633 | privateParent = content_is_private(vid); |
| 2633 | 2634 | } |
| 2634 | 2635 | |
| 2635 | 2636 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1627,19 +1627,20 @@ | |
| 1627 | int dryRunFlag /* True for a dry-run only */ |
| 1628 | ){ |
| 1629 | Blob *pDesc; |
| 1630 | char *zTags; |
| 1631 | char *zFilename; |
| 1632 | Blob desc; |
| 1633 | blob_init(&desc, 0, 0); |
| 1634 | pDesc = &desc; |
| 1635 | blob_appendf(pDesc, "checkout %s\n", g.zLocalRoot); |
| 1636 | blob_appendf(pDesc, "repository %s\n", g.zRepositoryName); |
| 1637 | blob_appendf(pDesc, "user %s\n", |
| 1638 | p->zUserOvrd ? p->zUserOvrd : login_name()); |
| 1639 | blob_appendf(pDesc, "branch %s\n", |
| 1640 | (p->zBranch && p->zBranch[0]) ? p->zBranch : "trunk"); |
| 1641 | zTags = info_tags_of_checkin(parent_rid, 1); |
| 1642 | if( zTags || p->azTag ){ |
| 1643 | blob_append(pDesc, "tags ", -1); |
| 1644 | if(zTags){ |
| 1645 | blob_appendf(pDesc, "%z%s", zTags, p->azTag ? ", " : ""); |
| @@ -2624,11 +2625,11 @@ | |
| 2624 | /* Get the ID of the parent manifest artifact */ |
| 2625 | vid = db_lget_int("checkout", 0); |
| 2626 | if( vid==0 ){ |
| 2627 | useCksum = 1; |
| 2628 | if( privateFlag==0 && sCiInfo.zBranch==0 ) { |
| 2629 | sCiInfo.zBranch=db_get("main-branch", 0); |
| 2630 | } |
| 2631 | }else{ |
| 2632 | privateParent = content_is_private(vid); |
| 2633 | } |
| 2634 | |
| 2635 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1627,19 +1627,20 @@ | |
| 1627 | int dryRunFlag /* True for a dry-run only */ |
| 1628 | ){ |
| 1629 | Blob *pDesc; |
| 1630 | char *zTags; |
| 1631 | char *zFilename; |
| 1632 | const char *zMainBranch = db_main_branch(); |
| 1633 | Blob desc; |
| 1634 | blob_init(&desc, 0, 0); |
| 1635 | pDesc = &desc; |
| 1636 | blob_appendf(pDesc, "checkout %s\n", g.zLocalRoot); |
| 1637 | blob_appendf(pDesc, "repository %s\n", g.zRepositoryName); |
| 1638 | blob_appendf(pDesc, "user %s\n", |
| 1639 | p->zUserOvrd ? p->zUserOvrd : login_name()); |
| 1640 | blob_appendf(pDesc, "branch %s\n", |
| 1641 | (p->zBranch && p->zBranch[0]) ? p->zBranch : zMainBranch); |
| 1642 | zTags = info_tags_of_checkin(parent_rid, 1); |
| 1643 | if( zTags || p->azTag ){ |
| 1644 | blob_append(pDesc, "tags ", -1); |
| 1645 | if(zTags){ |
| 1646 | blob_appendf(pDesc, "%z%s", zTags, p->azTag ? ", " : ""); |
| @@ -2624,11 +2625,11 @@ | |
| 2625 | /* Get the ID of the parent manifest artifact */ |
| 2626 | vid = db_lget_int("checkout", 0); |
| 2627 | if( vid==0 ){ |
| 2628 | useCksum = 1; |
| 2629 | if( privateFlag==0 && sCiInfo.zBranch==0 ) { |
| 2630 | sCiInfo.zBranch = db_main_branch(); |
| 2631 | } |
| 2632 | }else{ |
| 2633 | privateParent = content_is_private(vid); |
| 2634 | } |
| 2635 | |
| 2636 |
+1
-1
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -496,11 +496,11 @@ | ||
| 496 | 496 | verify_all_options(); |
| 497 | 497 | if( g.argc<3 || g.argc>4 ){ |
| 498 | 498 | usage("URL ?VERSION? ?OPTIONS?"); |
| 499 | 499 | } |
| 500 | 500 | zUrl = g.argv[2]; |
| 501 | - zVers = g.argc==4 ? g.argv[3] : "trunk"; | |
| 501 | + zVers = g.argc==4 ? g.argv[3] : db_main_branch(); | |
| 502 | 502 | |
| 503 | 503 | /* Parse the URL of the repository */ |
| 504 | 504 | url_parse(zUrl, 0); |
| 505 | 505 | |
| 506 | 506 | /* Construct an appropriate name for the destination directory */ |
| 507 | 507 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -496,11 +496,11 @@ | |
| 496 | verify_all_options(); |
| 497 | if( g.argc<3 || g.argc>4 ){ |
| 498 | usage("URL ?VERSION? ?OPTIONS?"); |
| 499 | } |
| 500 | zUrl = g.argv[2]; |
| 501 | zVers = g.argc==4 ? g.argv[3] : "trunk"; |
| 502 | |
| 503 | /* Parse the URL of the repository */ |
| 504 | url_parse(zUrl, 0); |
| 505 | |
| 506 | /* Construct an appropriate name for the destination directory */ |
| 507 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -496,11 +496,11 @@ | |
| 496 | verify_all_options(); |
| 497 | if( g.argc<3 || g.argc>4 ){ |
| 498 | usage("URL ?VERSION? ?OPTIONS?"); |
| 499 | } |
| 500 | zUrl = g.argv[2]; |
| 501 | zVers = g.argc==4 ? g.argv[3] : db_main_branch(); |
| 502 | |
| 503 | /* Parse the URL of the repository */ |
| 504 | url_parse(zUrl, 0); |
| 505 | |
| 506 | /* Construct an appropriate name for the destination directory */ |
| 507 |
M
src/db.c
+1
-1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -4403,11 +4403,11 @@ | ||
| 4403 | 4403 | /* Figure out which revision to open. */ |
| 4404 | 4404 | if( !emptyFlag ){ |
| 4405 | 4405 | if( g.argc==4 ){ |
| 4406 | 4406 | g.zOpenRevision = g.argv[3]; |
| 4407 | 4407 | }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ |
| 4408 | - g.zOpenRevision = db_get("main-branch", 0); | |
| 4408 | + g.zOpenRevision = fossil_strdup(db_main_branch()); | |
| 4409 | 4409 | } |
| 4410 | 4410 | if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){ |
| 4411 | 4411 | fossil_fatal("unable to auto-sync the repository"); |
| 4412 | 4412 | } |
| 4413 | 4413 | } |
| 4414 | 4414 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -4403,11 +4403,11 @@ | |
| 4403 | /* Figure out which revision to open. */ |
| 4404 | if( !emptyFlag ){ |
| 4405 | if( g.argc==4 ){ |
| 4406 | g.zOpenRevision = g.argv[3]; |
| 4407 | }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ |
| 4408 | g.zOpenRevision = db_get("main-branch", 0); |
| 4409 | } |
| 4410 | if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){ |
| 4411 | fossil_fatal("unable to auto-sync the repository"); |
| 4412 | } |
| 4413 | } |
| 4414 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -4403,11 +4403,11 @@ | |
| 4403 | /* Figure out which revision to open. */ |
| 4404 | if( !emptyFlag ){ |
| 4405 | if( g.argc==4 ){ |
| 4406 | g.zOpenRevision = g.argv[3]; |
| 4407 | }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ |
| 4408 | g.zOpenRevision = fossil_strdup(db_main_branch()); |
| 4409 | } |
| 4410 | if( autosync_loop(SYNC_PULL, !bForce, "open") && !bForce ){ |
| 4411 | fossil_fatal("unable to auto-sync the repository"); |
| 4412 | } |
| 4413 | } |
| 4414 |
+1
-2
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -437,11 +437,11 @@ | ||
| 437 | 437 | int multipleFlag = find_option("multiple","m",0)!=0; |
| 438 | 438 | const char *zWidth = find_option("width","W",1); |
| 439 | 439 | char *zLastBr = 0; |
| 440 | 440 | int n, width; |
| 441 | 441 | char zLineNo[10]; |
| 442 | - char * const zMainBranch = db_get("main-branch","trunk"); | |
| 442 | + const char *zMainBranch = db_main_branch(); | |
| 443 | 443 | |
| 444 | 444 | if( multipleFlag ) byBranch = 1; |
| 445 | 445 | if( zWidth ){ |
| 446 | 446 | width = atoi(zWidth); |
| 447 | 447 | if( (width!=0) && (width<=39) ){ |
| @@ -535,11 +535,10 @@ | ||
| 535 | 535 | zBranchPoint ? zBranchPoint : ""); |
| 536 | 536 | comment_print(z, zCom, 7, width, get_comment_format()); |
| 537 | 537 | fossil_free(z); |
| 538 | 538 | fossil_free(zBranchPoint); |
| 539 | 539 | } |
| 540 | - fossil_free(zMainBranch); | |
| 541 | 540 | fossil_free(zLastBr); |
| 542 | 541 | db_finalize(&q); |
| 543 | 542 | } |
| 544 | 543 | |
| 545 | 544 | /* |
| 546 | 545 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -437,11 +437,11 @@ | |
| 437 | int multipleFlag = find_option("multiple","m",0)!=0; |
| 438 | const char *zWidth = find_option("width","W",1); |
| 439 | char *zLastBr = 0; |
| 440 | int n, width; |
| 441 | char zLineNo[10]; |
| 442 | char * const zMainBranch = db_get("main-branch","trunk"); |
| 443 | |
| 444 | if( multipleFlag ) byBranch = 1; |
| 445 | if( zWidth ){ |
| 446 | width = atoi(zWidth); |
| 447 | if( (width!=0) && (width<=39) ){ |
| @@ -535,11 +535,10 @@ | |
| 535 | zBranchPoint ? zBranchPoint : ""); |
| 536 | comment_print(z, zCom, 7, width, get_comment_format()); |
| 537 | fossil_free(z); |
| 538 | fossil_free(zBranchPoint); |
| 539 | } |
| 540 | fossil_free(zMainBranch); |
| 541 | fossil_free(zLastBr); |
| 542 | db_finalize(&q); |
| 543 | } |
| 544 | |
| 545 | /* |
| 546 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -437,11 +437,11 @@ | |
| 437 | int multipleFlag = find_option("multiple","m",0)!=0; |
| 438 | const char *zWidth = find_option("width","W",1); |
| 439 | char *zLastBr = 0; |
| 440 | int n, width; |
| 441 | char zLineNo[10]; |
| 442 | const char *zMainBranch = db_main_branch(); |
| 443 | |
| 444 | if( multipleFlag ) byBranch = 1; |
| 445 | if( zWidth ){ |
| 446 | width = atoi(zWidth); |
| 447 | if( (width!=0) && (width<=39) ){ |
| @@ -535,11 +535,10 @@ | |
| 535 | zBranchPoint ? zBranchPoint : ""); |
| 536 | comment_print(z, zCom, 7, width, get_comment_format()); |
| 537 | fossil_free(z); |
| 538 | fossil_free(zBranchPoint); |
| 539 | } |
| 540 | fossil_free(zLastBr); |
| 541 | db_finalize(&q); |
| 542 | } |
| 543 | |
| 544 | /* |
| 545 |
+2
-1
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -3949,11 +3949,12 @@ | ||
| 3949 | 3949 | ** -n|--limit LIMIT LIMIT can be one of: |
| 3950 | 3950 | ** N Up to N versions |
| 3951 | 3951 | ** Xs As much as possible in X seconds |
| 3952 | 3952 | ** none No limit |
| 3953 | 3953 | ** -o|--origin VERSION The origin check-in. By default this is the |
| 3954 | -** root of the repository. Set to "trunk" or | |
| 3954 | +** root of the repository. Set to the name of | |
| 3955 | +** the main branch (usually "trunk") or | |
| 3955 | 3956 | ** similar for a reverse annotation. |
| 3956 | 3957 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 3957 | 3958 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 3958 | 3959 | ** |
| 3959 | 3960 | ** See also: [[info]], [[finfo]], [[timeline]] |
| 3960 | 3961 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -3949,11 +3949,12 @@ | |
| 3949 | ** -n|--limit LIMIT LIMIT can be one of: |
| 3950 | ** N Up to N versions |
| 3951 | ** Xs As much as possible in X seconds |
| 3952 | ** none No limit |
| 3953 | ** -o|--origin VERSION The origin check-in. By default this is the |
| 3954 | ** root of the repository. Set to "trunk" or |
| 3955 | ** similar for a reverse annotation. |
| 3956 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 3957 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 3958 | ** |
| 3959 | ** See also: [[info]], [[finfo]], [[timeline]] |
| 3960 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -3949,11 +3949,12 @@ | |
| 3949 | ** -n|--limit LIMIT LIMIT can be one of: |
| 3950 | ** N Up to N versions |
| 3951 | ** Xs As much as possible in X seconds |
| 3952 | ** none No limit |
| 3953 | ** -o|--origin VERSION The origin check-in. By default this is the |
| 3954 | ** root of the repository. Set to the name of |
| 3955 | ** the main branch (usually "trunk") or |
| 3956 | ** similar for a reverse annotation. |
| 3957 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 3958 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 3959 | ** |
| 3960 | ** See also: [[info]], [[finfo]], [[timeline]] |
| 3961 |
+8
-5
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -491,20 +491,21 @@ | ||
| 491 | 491 | Stmt q, q2, q3; |
| 492 | 492 | Bag blobs, vers; |
| 493 | 493 | unsigned int unused_mark = 1; |
| 494 | 494 | const char *markfile_in; |
| 495 | 495 | const char *markfile_out; |
| 496 | + const char *zMainBranch = db_main_branch(); | |
| 496 | 497 | |
| 497 | 498 | bag_init(&blobs); |
| 498 | 499 | bag_init(&vers); |
| 499 | 500 | |
| 500 | 501 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 501 | 502 | markfile_in = find_option("import-marks", 0, 1); |
| 502 | 503 | markfile_out = find_option("export-marks", 0, 1); |
| 503 | 504 | |
| 504 | 505 | if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 505 | - gexport.zTrunkName = "trunk"; | |
| 506 | + gexport.zTrunkName = fossil_strdup(zMainBranch); | |
| 506 | 507 | } |
| 507 | 508 | |
| 508 | 509 | db_find_and_open_repository(0, 2); |
| 509 | 510 | verify_all_options(); |
| 510 | 511 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| @@ -629,11 +630,11 @@ | ||
| 629 | 630 | |
| 630 | 631 | bag_insert(&vers, ckinId); |
| 631 | 632 | db_bind_int(&q2, ":rid", ckinId); |
| 632 | 633 | db_step(&q2); |
| 633 | 634 | db_reset(&q2); |
| 634 | - if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ){ | |
| 635 | + if( zBranch==0 || fossil_strcmp(zBranch, zMainBranch)==0 ){ | |
| 635 | 636 | zBranch = gexport.zTrunkName; |
| 636 | 637 | } |
| 637 | 638 | zMark = mark_name_from_rid(ckinId, &unused_mark); |
| 638 | 639 | printf("commit refs/heads/"); |
| 639 | 640 | print_ref(zBranch); |
| @@ -857,12 +858,12 @@ | ||
| 857 | 858 | #define VERB_ERROR 1 |
| 858 | 859 | #define VERB_NORMAL 2 |
| 859 | 860 | #define VERB_EXTRA 3 |
| 860 | 861 | static int gitmirror_verbosity = VERB_NORMAL; |
| 861 | 862 | |
| 862 | -/* The main branch in the Git repository. The "trunk" branch of | |
| 863 | -** Fossil is renamed to be this branch name. | |
| 863 | +/* The main branch in the Git repository. The main branch of the | |
| 864 | +** Fossil repository (usually "trunk") is renamed to be this branch name. | |
| 864 | 865 | */ |
| 865 | 866 | static const char *gitmirror_mainbranch = 0; |
| 866 | 867 | |
| 867 | 868 | /* |
| 868 | 869 | ** Output routine that depends on verbosity |
| @@ -1090,10 +1091,11 @@ | ||
| 1090 | 1091 | int bPhantomOk; /* True if phantom files should be ignored */ |
| 1091 | 1092 | char buf[24]; |
| 1092 | 1093 | char *zEmail; /* Contact info for Git committer field */ |
| 1093 | 1094 | int fManifest; /* Should the manifest files be included? */ |
| 1094 | 1095 | int fPManifest = 0; /* OR of the manifest files for all parents */ |
| 1096 | + const char *zMainBranch; | |
| 1095 | 1097 | |
| 1096 | 1098 | pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1097 | 1099 | if( pMan==0 ){ |
| 1098 | 1100 | /* Must be a phantom. Return without doing anything, and in particular |
| 1099 | 1101 | ** without creating a mark for this check-in. */ |
| @@ -1149,11 +1151,12 @@ | ||
| 1149 | 1151 | /* Figure out which branch this check-in is a member of */ |
| 1150 | 1152 | zBranch = db_text(0, |
| 1151 | 1153 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d", |
| 1152 | 1154 | TAG_BRANCH, rid |
| 1153 | 1155 | ); |
| 1154 | - if( fossil_strcmp(zBranch,"trunk")==0 ){ | |
| 1156 | + zMainBranch = db_main_branch(); | |
| 1157 | + if( fossil_strcmp(zBranch, zMainBranch)==0 ){ | |
| 1155 | 1158 | assert( gitmirror_mainbranch!=0 ); |
| 1156 | 1159 | fossil_free(zBranch); |
| 1157 | 1160 | zBranch = fossil_strdup(gitmirror_mainbranch); |
| 1158 | 1161 | }else if( zBranch==0 ){ |
| 1159 | 1162 | zBranch = mprintf("unknown"); |
| 1160 | 1163 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -491,20 +491,21 @@ | |
| 491 | Stmt q, q2, q3; |
| 492 | Bag blobs, vers; |
| 493 | unsigned int unused_mark = 1; |
| 494 | const char *markfile_in; |
| 495 | const char *markfile_out; |
| 496 | |
| 497 | bag_init(&blobs); |
| 498 | bag_init(&vers); |
| 499 | |
| 500 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 501 | markfile_in = find_option("import-marks", 0, 1); |
| 502 | markfile_out = find_option("export-marks", 0, 1); |
| 503 | |
| 504 | if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 505 | gexport.zTrunkName = "trunk"; |
| 506 | } |
| 507 | |
| 508 | db_find_and_open_repository(0, 2); |
| 509 | verify_all_options(); |
| 510 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| @@ -629,11 +630,11 @@ | |
| 629 | |
| 630 | bag_insert(&vers, ckinId); |
| 631 | db_bind_int(&q2, ":rid", ckinId); |
| 632 | db_step(&q2); |
| 633 | db_reset(&q2); |
| 634 | if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ){ |
| 635 | zBranch = gexport.zTrunkName; |
| 636 | } |
| 637 | zMark = mark_name_from_rid(ckinId, &unused_mark); |
| 638 | printf("commit refs/heads/"); |
| 639 | print_ref(zBranch); |
| @@ -857,12 +858,12 @@ | |
| 857 | #define VERB_ERROR 1 |
| 858 | #define VERB_NORMAL 2 |
| 859 | #define VERB_EXTRA 3 |
| 860 | static int gitmirror_verbosity = VERB_NORMAL; |
| 861 | |
| 862 | /* The main branch in the Git repository. The "trunk" branch of |
| 863 | ** Fossil is renamed to be this branch name. |
| 864 | */ |
| 865 | static const char *gitmirror_mainbranch = 0; |
| 866 | |
| 867 | /* |
| 868 | ** Output routine that depends on verbosity |
| @@ -1090,10 +1091,11 @@ | |
| 1090 | int bPhantomOk; /* True if phantom files should be ignored */ |
| 1091 | char buf[24]; |
| 1092 | char *zEmail; /* Contact info for Git committer field */ |
| 1093 | int fManifest; /* Should the manifest files be included? */ |
| 1094 | int fPManifest = 0; /* OR of the manifest files for all parents */ |
| 1095 | |
| 1096 | pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1097 | if( pMan==0 ){ |
| 1098 | /* Must be a phantom. Return without doing anything, and in particular |
| 1099 | ** without creating a mark for this check-in. */ |
| @@ -1149,11 +1151,12 @@ | |
| 1149 | /* Figure out which branch this check-in is a member of */ |
| 1150 | zBranch = db_text(0, |
| 1151 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d", |
| 1152 | TAG_BRANCH, rid |
| 1153 | ); |
| 1154 | if( fossil_strcmp(zBranch,"trunk")==0 ){ |
| 1155 | assert( gitmirror_mainbranch!=0 ); |
| 1156 | fossil_free(zBranch); |
| 1157 | zBranch = fossil_strdup(gitmirror_mainbranch); |
| 1158 | }else if( zBranch==0 ){ |
| 1159 | zBranch = mprintf("unknown"); |
| 1160 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -491,20 +491,21 @@ | |
| 491 | Stmt q, q2, q3; |
| 492 | Bag blobs, vers; |
| 493 | unsigned int unused_mark = 1; |
| 494 | const char *markfile_in; |
| 495 | const char *markfile_out; |
| 496 | const char *zMainBranch = db_main_branch(); |
| 497 | |
| 498 | bag_init(&blobs); |
| 499 | bag_init(&vers); |
| 500 | |
| 501 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 502 | markfile_in = find_option("import-marks", 0, 1); |
| 503 | markfile_out = find_option("export-marks", 0, 1); |
| 504 | |
| 505 | if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 506 | gexport.zTrunkName = fossil_strdup(zMainBranch); |
| 507 | } |
| 508 | |
| 509 | db_find_and_open_repository(0, 2); |
| 510 | verify_all_options(); |
| 511 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| @@ -629,11 +630,11 @@ | |
| 630 | |
| 631 | bag_insert(&vers, ckinId); |
| 632 | db_bind_int(&q2, ":rid", ckinId); |
| 633 | db_step(&q2); |
| 634 | db_reset(&q2); |
| 635 | if( zBranch==0 || fossil_strcmp(zBranch, zMainBranch)==0 ){ |
| 636 | zBranch = gexport.zTrunkName; |
| 637 | } |
| 638 | zMark = mark_name_from_rid(ckinId, &unused_mark); |
| 639 | printf("commit refs/heads/"); |
| 640 | print_ref(zBranch); |
| @@ -857,12 +858,12 @@ | |
| 858 | #define VERB_ERROR 1 |
| 859 | #define VERB_NORMAL 2 |
| 860 | #define VERB_EXTRA 3 |
| 861 | static int gitmirror_verbosity = VERB_NORMAL; |
| 862 | |
| 863 | /* The main branch in the Git repository. The main branch of the |
| 864 | ** Fossil repository (usually "trunk") is renamed to be this branch name. |
| 865 | */ |
| 866 | static const char *gitmirror_mainbranch = 0; |
| 867 | |
| 868 | /* |
| 869 | ** Output routine that depends on verbosity |
| @@ -1090,10 +1091,11 @@ | |
| 1091 | int bPhantomOk; /* True if phantom files should be ignored */ |
| 1092 | char buf[24]; |
| 1093 | char *zEmail; /* Contact info for Git committer field */ |
| 1094 | int fManifest; /* Should the manifest files be included? */ |
| 1095 | int fPManifest = 0; /* OR of the manifest files for all parents */ |
| 1096 | const char *zMainBranch; |
| 1097 | |
| 1098 | pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 1099 | if( pMan==0 ){ |
| 1100 | /* Must be a phantom. Return without doing anything, and in particular |
| 1101 | ** without creating a mark for this check-in. */ |
| @@ -1149,11 +1151,12 @@ | |
| 1151 | /* Figure out which branch this check-in is a member of */ |
| 1152 | zBranch = db_text(0, |
| 1153 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d", |
| 1154 | TAG_BRANCH, rid |
| 1155 | ); |
| 1156 | zMainBranch = db_main_branch(); |
| 1157 | if( fossil_strcmp(zBranch, zMainBranch)==0 ){ |
| 1158 | assert( gitmirror_mainbranch!=0 ); |
| 1159 | fossil_free(zBranch); |
| 1160 | zBranch = fossil_strdup(gitmirror_mainbranch); |
| 1161 | }else if( zBranch==0 ){ |
| 1162 | zBranch = mprintf("unknown"); |
| 1163 |
+1
-1
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -833,11 +833,11 @@ | ||
| 833 | 833 | } |
| 834 | 834 | if(zRevision==0 || zRevision[0]==0){ |
| 835 | 835 | if(g.localOpen/*check-out*/){ |
| 836 | 836 | zRevision = db_lget("checkout-hash", 0)/*leak*/; |
| 837 | 837 | }else{ |
| 838 | - zRevision = "trunk"; | |
| 838 | + zRevision = db_main_branch(); | |
| 839 | 839 | } |
| 840 | 840 | } |
| 841 | 841 | name_to_uuid2(zRevision, "ci", &cimi.zParentUuid); |
| 842 | 842 | if(cimi.zParentUuid==0){ |
| 843 | 843 | fossil_fatal("Cannot determine version to commit to."); |
| 844 | 844 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -833,11 +833,11 @@ | |
| 833 | } |
| 834 | if(zRevision==0 || zRevision[0]==0){ |
| 835 | if(g.localOpen/*check-out*/){ |
| 836 | zRevision = db_lget("checkout-hash", 0)/*leak*/; |
| 837 | }else{ |
| 838 | zRevision = "trunk"; |
| 839 | } |
| 840 | } |
| 841 | name_to_uuid2(zRevision, "ci", &cimi.zParentUuid); |
| 842 | if(cimi.zParentUuid==0){ |
| 843 | fossil_fatal("Cannot determine version to commit to."); |
| 844 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -833,11 +833,11 @@ | |
| 833 | } |
| 834 | if(zRevision==0 || zRevision[0]==0){ |
| 835 | if(g.localOpen/*check-out*/){ |
| 836 | zRevision = db_lget("checkout-hash", 0)/*leak*/; |
| 837 | }else{ |
| 838 | zRevision = db_main_branch(); |
| 839 | } |
| 840 | } |
| 841 | name_to_uuid2(zRevision, "ci", &cimi.zParentUuid); |
| 842 | if(cimi.zParentUuid==0){ |
| 843 | fossil_fatal("Cannot determine version to commit to."); |
| 844 |
+7
-3
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -176,10 +176,11 @@ | ||
| 176 | 176 | const char *zFilename; |
| 177 | 177 | const char *zLimit; |
| 178 | 178 | const char *zWidth; |
| 179 | 179 | const char *zOffset; |
| 180 | 180 | int iLimit, iOffset, iBrief, iWidth; |
| 181 | + const char *zMainBranch; | |
| 181 | 182 | |
| 182 | 183 | if( find_option("log","l",0) ){ |
| 183 | 184 | /* this is the default, no-op */ |
| 184 | 185 | } |
| 185 | 186 | zLimit = find_option("limit","n",1); |
| @@ -231,19 +232,20 @@ | ||
| 231 | 232 | ); |
| 232 | 233 | blob_zero(&line); |
| 233 | 234 | if( iBrief == 0 ){ |
| 234 | 235 | fossil_print("History for %s\n", blob_str(&fname)); |
| 235 | 236 | } |
| 237 | + zMainBranch = db_main_branch(); | |
| 236 | 238 | while( db_step(&q)==SQLITE_ROW ){ |
| 237 | 239 | const char *zFileUuid = db_column_text(&q, 0); |
| 238 | 240 | const char *zCiUuid = db_column_text(&q,1); |
| 239 | 241 | const char *zDate = db_column_text(&q, 2); |
| 240 | 242 | const char *zCom = db_column_text(&q, 3); |
| 241 | 243 | const char *zUser = db_column_text(&q, 4); |
| 242 | 244 | const char *zBr = db_column_text(&q, 5); |
| 243 | 245 | char *zOut; |
| 244 | - if( zBr==0 ) zBr = "trunk"; | |
| 246 | + if( zBr==0 ) zBr = fossil_strdup(zMainBranch); | |
| 245 | 247 | if( iBrief == 0 ){ |
| 246 | 248 | fossil_print("%s ", zDate); |
| 247 | 249 | zOut = mprintf( |
| 248 | 250 | "[%S] %s (user: %s, artifact: [%S], branch: %s)", |
| 249 | 251 | zCiUuid, zCom, zUser, zFileUuid, zBr); |
| @@ -376,10 +378,11 @@ | ||
| 376 | 378 | int tmFlags = 0; /* Viewing mode */ |
| 377 | 379 | const char *zStyle; /* Viewing mode name */ |
| 378 | 380 | const char *zMark; /* Mark this version of the file */ |
| 379 | 381 | int selRid = 0; /* RID of the marked file version */ |
| 380 | 382 | int mxfnid; /* Maximum filename.fnid value */ |
| 383 | + const char *zMainBranch; | |
| 381 | 384 | |
| 382 | 385 | login_check_credentials(); |
| 383 | 386 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 384 | 387 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 385 | 388 | ridCi = zCI ? name_to_rid_www("ci") : 0; |
| @@ -633,15 +636,16 @@ | ||
| 633 | 636 | while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ |
| 634 | 637 | aParent[nParent] = db_column_int64(&qparent, 0); |
| 635 | 638 | nParent++; |
| 636 | 639 | } |
| 637 | 640 | db_reset(&qparent); |
| 638 | - if( zBr==0 ) zBr = "trunk"; | |
| 641 | + zMainBranch = db_main_branch(); | |
| 642 | + if( zBr==0 ) zBr = fossil_strdup(zMainBranch); | |
| 639 | 643 | if( uBg ){ |
| 640 | 644 | zBgClr = user_color(zUser); |
| 641 | 645 | }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ |
| 642 | - zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); | |
| 646 | + zBgClr = strcmp(zBr, zMainBranch)==0 ? "" : hash_color(zBr); | |
| 643 | 647 | }else if( zBgClr ){ |
| 644 | 648 | zBgClr = reasonable_bg_color(zBgClr,0); |
| 645 | 649 | } |
| 646 | 650 | gidx = graph_add_row(pGraph, |
| 647 | 651 | frid>0 ? (GraphRowId)frid*(mxfnid+1)+fnid : fpid+1000000000, |
| 648 | 652 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -176,10 +176,11 @@ | |
| 176 | const char *zFilename; |
| 177 | const char *zLimit; |
| 178 | const char *zWidth; |
| 179 | const char *zOffset; |
| 180 | int iLimit, iOffset, iBrief, iWidth; |
| 181 | |
| 182 | if( find_option("log","l",0) ){ |
| 183 | /* this is the default, no-op */ |
| 184 | } |
| 185 | zLimit = find_option("limit","n",1); |
| @@ -231,19 +232,20 @@ | |
| 231 | ); |
| 232 | blob_zero(&line); |
| 233 | if( iBrief == 0 ){ |
| 234 | fossil_print("History for %s\n", blob_str(&fname)); |
| 235 | } |
| 236 | while( db_step(&q)==SQLITE_ROW ){ |
| 237 | const char *zFileUuid = db_column_text(&q, 0); |
| 238 | const char *zCiUuid = db_column_text(&q,1); |
| 239 | const char *zDate = db_column_text(&q, 2); |
| 240 | const char *zCom = db_column_text(&q, 3); |
| 241 | const char *zUser = db_column_text(&q, 4); |
| 242 | const char *zBr = db_column_text(&q, 5); |
| 243 | char *zOut; |
| 244 | if( zBr==0 ) zBr = "trunk"; |
| 245 | if( iBrief == 0 ){ |
| 246 | fossil_print("%s ", zDate); |
| 247 | zOut = mprintf( |
| 248 | "[%S] %s (user: %s, artifact: [%S], branch: %s)", |
| 249 | zCiUuid, zCom, zUser, zFileUuid, zBr); |
| @@ -376,10 +378,11 @@ | |
| 376 | int tmFlags = 0; /* Viewing mode */ |
| 377 | const char *zStyle; /* Viewing mode name */ |
| 378 | const char *zMark; /* Mark this version of the file */ |
| 379 | int selRid = 0; /* RID of the marked file version */ |
| 380 | int mxfnid; /* Maximum filename.fnid value */ |
| 381 | |
| 382 | login_check_credentials(); |
| 383 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 384 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 385 | ridCi = zCI ? name_to_rid_www("ci") : 0; |
| @@ -633,15 +636,16 @@ | |
| 633 | while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ |
| 634 | aParent[nParent] = db_column_int64(&qparent, 0); |
| 635 | nParent++; |
| 636 | } |
| 637 | db_reset(&qparent); |
| 638 | if( zBr==0 ) zBr = "trunk"; |
| 639 | if( uBg ){ |
| 640 | zBgClr = user_color(zUser); |
| 641 | }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ |
| 642 | zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr); |
| 643 | }else if( zBgClr ){ |
| 644 | zBgClr = reasonable_bg_color(zBgClr,0); |
| 645 | } |
| 646 | gidx = graph_add_row(pGraph, |
| 647 | frid>0 ? (GraphRowId)frid*(mxfnid+1)+fnid : fpid+1000000000, |
| 648 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -176,10 +176,11 @@ | |
| 176 | const char *zFilename; |
| 177 | const char *zLimit; |
| 178 | const char *zWidth; |
| 179 | const char *zOffset; |
| 180 | int iLimit, iOffset, iBrief, iWidth; |
| 181 | const char *zMainBranch; |
| 182 | |
| 183 | if( find_option("log","l",0) ){ |
| 184 | /* this is the default, no-op */ |
| 185 | } |
| 186 | zLimit = find_option("limit","n",1); |
| @@ -231,19 +232,20 @@ | |
| 232 | ); |
| 233 | blob_zero(&line); |
| 234 | if( iBrief == 0 ){ |
| 235 | fossil_print("History for %s\n", blob_str(&fname)); |
| 236 | } |
| 237 | zMainBranch = db_main_branch(); |
| 238 | while( db_step(&q)==SQLITE_ROW ){ |
| 239 | const char *zFileUuid = db_column_text(&q, 0); |
| 240 | const char *zCiUuid = db_column_text(&q,1); |
| 241 | const char *zDate = db_column_text(&q, 2); |
| 242 | const char *zCom = db_column_text(&q, 3); |
| 243 | const char *zUser = db_column_text(&q, 4); |
| 244 | const char *zBr = db_column_text(&q, 5); |
| 245 | char *zOut; |
| 246 | if( zBr==0 ) zBr = fossil_strdup(zMainBranch); |
| 247 | if( iBrief == 0 ){ |
| 248 | fossil_print("%s ", zDate); |
| 249 | zOut = mprintf( |
| 250 | "[%S] %s (user: %s, artifact: [%S], branch: %s)", |
| 251 | zCiUuid, zCom, zUser, zFileUuid, zBr); |
| @@ -376,10 +378,11 @@ | |
| 378 | int tmFlags = 0; /* Viewing mode */ |
| 379 | const char *zStyle; /* Viewing mode name */ |
| 380 | const char *zMark; /* Mark this version of the file */ |
| 381 | int selRid = 0; /* RID of the marked file version */ |
| 382 | int mxfnid; /* Maximum filename.fnid value */ |
| 383 | const char *zMainBranch; |
| 384 | |
| 385 | login_check_credentials(); |
| 386 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 387 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 388 | ridCi = zCI ? name_to_rid_www("ci") : 0; |
| @@ -633,15 +636,16 @@ | |
| 636 | while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ |
| 637 | aParent[nParent] = db_column_int64(&qparent, 0); |
| 638 | nParent++; |
| 639 | } |
| 640 | db_reset(&qparent); |
| 641 | zMainBranch = db_main_branch(); |
| 642 | if( zBr==0 ) zBr = fossil_strdup(zMainBranch); |
| 643 | if( uBg ){ |
| 644 | zBgClr = user_color(zUser); |
| 645 | }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){ |
| 646 | zBgClr = strcmp(zBr, zMainBranch)==0 ? "" : hash_color(zBr); |
| 647 | }else if( zBgClr ){ |
| 648 | zBgClr = reasonable_bg_color(zBgClr,0); |
| 649 | } |
| 650 | gidx = graph_add_row(pGraph, |
| 651 | frid>0 ? (GraphRowId)frid*(mxfnid+1)+fnid : fpid+1000000000, |
| 652 |
+4
-2
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -513,10 +513,11 @@ | ||
| 513 | 513 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 514 | 514 | int i, j; |
| 515 | 515 | u64 mask; |
| 516 | 516 | int hasDup = 0; /* True if one or more isDup entries */ |
| 517 | 517 | const char *zTrunk; |
| 518 | + const char *zMainBranch; | |
| 518 | 519 | u8 *aMap; /* Copy of p->aiRailMap */ |
| 519 | 520 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 520 | 521 | int nTimewarp = 0; |
| 521 | 522 | int riserMargin = (tmFlags & TIMELINE_DISJOINT) ? 0 : RISER_MARGIN; |
| 522 | 523 | |
| @@ -706,13 +707,14 @@ | ||
| 706 | 707 | } |
| 707 | 708 | |
| 708 | 709 | /* Identify rows where the primary parent is off screen. Assign |
| 709 | 710 | ** each to a rail and draw descenders downward. |
| 710 | 711 | ** |
| 711 | - ** Strive to put the "trunk" branch on far left. | |
| 712 | + ** Strive to put the main branch (usually "trunk") on far left. | |
| 712 | 713 | */ |
| 713 | - zTrunk = persistBranchName(p, "trunk"); | |
| 714 | + zMainBranch = db_main_branch(); | |
| 715 | + zTrunk = persistBranchName(p, zMainBranch); | |
| 714 | 716 | for(i=0; i<2; i++){ |
| 715 | 717 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 716 | 718 | if( i==0 && pRow->zBranch!=zTrunk ) continue; |
| 717 | 719 | if( pRow->iRail>=0 ) continue; |
| 718 | 720 | if( pRow->isDup ) continue; |
| 719 | 721 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -513,10 +513,11 @@ | |
| 513 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 514 | int i, j; |
| 515 | u64 mask; |
| 516 | int hasDup = 0; /* True if one or more isDup entries */ |
| 517 | const char *zTrunk; |
| 518 | u8 *aMap; /* Copy of p->aiRailMap */ |
| 519 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 520 | int nTimewarp = 0; |
| 521 | int riserMargin = (tmFlags & TIMELINE_DISJOINT) ? 0 : RISER_MARGIN; |
| 522 | |
| @@ -706,13 +707,14 @@ | |
| 706 | } |
| 707 | |
| 708 | /* Identify rows where the primary parent is off screen. Assign |
| 709 | ** each to a rail and draw descenders downward. |
| 710 | ** |
| 711 | ** Strive to put the "trunk" branch on far left. |
| 712 | */ |
| 713 | zTrunk = persistBranchName(p, "trunk"); |
| 714 | for(i=0; i<2; i++){ |
| 715 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 716 | if( i==0 && pRow->zBranch!=zTrunk ) continue; |
| 717 | if( pRow->iRail>=0 ) continue; |
| 718 | if( pRow->isDup ) continue; |
| 719 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -513,10 +513,11 @@ | |
| 513 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 514 | int i, j; |
| 515 | u64 mask; |
| 516 | int hasDup = 0; /* True if one or more isDup entries */ |
| 517 | const char *zTrunk; |
| 518 | const char *zMainBranch; |
| 519 | u8 *aMap; /* Copy of p->aiRailMap */ |
| 520 | int omitDescenders = (tmFlags & TIMELINE_DISJOINT)!=0; |
| 521 | int nTimewarp = 0; |
| 522 | int riserMargin = (tmFlags & TIMELINE_DISJOINT) ? 0 : RISER_MARGIN; |
| 523 | |
| @@ -706,13 +707,14 @@ | |
| 707 | } |
| 708 | |
| 709 | /* Identify rows where the primary parent is off screen. Assign |
| 710 | ** each to a rail and draw descenders downward. |
| 711 | ** |
| 712 | ** Strive to put the main branch (usually "trunk") on far left. |
| 713 | */ |
| 714 | zMainBranch = db_main_branch(); |
| 715 | zTrunk = persistBranchName(p, zMainBranch); |
| 716 | for(i=0; i<2; i++){ |
| 717 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 718 | if( i==0 && pRow->zBranch!=zTrunk ) continue; |
| 719 | if( pRow->iRail>=0 ) continue; |
| 720 | if( pRow->isDup ) continue; |
| 721 |
+7
-5
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -568,12 +568,12 @@ | ||
| 568 | 568 | ** |
| 569 | 569 | ** (A) refs/heads/BRANCHNAME |
| 570 | 570 | ** (B) refs/tags/TAGNAME |
| 571 | 571 | ** |
| 572 | 572 | ** If pattern A is used, then the branchname used is as shown. |
| 573 | - ** Except, the "master" branch which is the default branch name in | |
| 574 | - ** Git is changed to "trunk" which is the default name in Fossil. | |
| 573 | + ** Except, the "master" branch which is the default branch name in Git | |
| 574 | + ** is changed to the default main branch name in Fossil (usually "trunk") | |
| 575 | 575 | ** If the pattern is B, then the new commit should be on the same |
| 576 | 576 | ** branch as its parent. And, we might need to add the TAGNAME |
| 577 | 577 | ** tag to the new commit. However, if there are multiple instances |
| 578 | 578 | ** of pattern B with the same TAGNAME, then only put the tag on the |
| 579 | 579 | ** last commit that holds that tag. |
| @@ -1263,10 +1263,11 @@ | ||
| 1263 | 1263 | ** Return 0 if not a branch, tag, or trunk, or if ignored by --ignore-tree. |
| 1264 | 1264 | */ |
| 1265 | 1265 | static int svn_parse_path(char *zPath, char **zFile, int *type){ |
| 1266 | 1266 | char *zBranch = 0; |
| 1267 | 1267 | int branchId = 0; |
| 1268 | + const char *zMainBranch; | |
| 1268 | 1269 | if( gsvn.azIgnTree ){ |
| 1269 | 1270 | const char **pzIgnTree; |
| 1270 | 1271 | unsigned nPath = strlen(zPath); |
| 1271 | 1272 | for( pzIgnTree = gsvn.azIgnTree; *pzIgnTree; ++pzIgnTree ){ |
| 1272 | 1273 | const char *zIgn = *pzIgnTree; |
| @@ -1277,18 +1278,19 @@ | ||
| 1277 | 1278 | } |
| 1278 | 1279 | } |
| 1279 | 1280 | } |
| 1280 | 1281 | *type = SVN_UNKNOWN; |
| 1281 | 1282 | *zFile = 0; |
| 1283 | + zMainBranch = db_main_branch(); | |
| 1282 | 1284 | if( gsvn.lenTrunk==0 ){ |
| 1283 | - zBranch = "trunk"; | |
| 1285 | + zBranch = fossil_strdup(zMainBranch); | |
| 1284 | 1286 | *zFile = zPath; |
| 1285 | 1287 | *type = SVN_TRUNK; |
| 1286 | 1288 | }else |
| 1287 | 1289 | if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ |
| 1288 | 1290 | if( zPath[gsvn.lenTrunk-1]=='/' || zPath[gsvn.lenTrunk-1]==0 ){ |
| 1289 | - zBranch = "trunk"; | |
| 1291 | + zBranch = fossil_strdup(zMainBranch); | |
| 1290 | 1292 | *zFile = zPath+gsvn.lenTrunk; |
| 1291 | 1293 | *type = SVN_TRUNK; |
| 1292 | 1294 | }else{ |
| 1293 | 1295 | zBranch = 0; |
| 1294 | 1296 | *type = SVN_UNKNOWN; |
| @@ -1770,11 +1772,11 @@ | ||
| 1770 | 1772 | *renOpt->varSuf = renOpt->zDefaultSuf; |
| 1771 | 1773 | } |
| 1772 | 1774 | } |
| 1773 | 1775 | } |
| 1774 | 1776 | if( !(gimport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 1775 | - gimport.zTrunkName = "trunk"; | |
| 1777 | + gimport.zTrunkName = fossil_strdup(db_main_branch()); | |
| 1776 | 1778 | } |
| 1777 | 1779 | |
| 1778 | 1780 | if( svnFlag ){ |
| 1779 | 1781 | /* Get --svn related options here, so verify_all_options() fails when |
| 1780 | 1782 | * svn-only options are specified with --git |
| 1781 | 1783 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -568,12 +568,12 @@ | |
| 568 | ** |
| 569 | ** (A) refs/heads/BRANCHNAME |
| 570 | ** (B) refs/tags/TAGNAME |
| 571 | ** |
| 572 | ** If pattern A is used, then the branchname used is as shown. |
| 573 | ** Except, the "master" branch which is the default branch name in |
| 574 | ** Git is changed to "trunk" which is the default name in Fossil. |
| 575 | ** If the pattern is B, then the new commit should be on the same |
| 576 | ** branch as its parent. And, we might need to add the TAGNAME |
| 577 | ** tag to the new commit. However, if there are multiple instances |
| 578 | ** of pattern B with the same TAGNAME, then only put the tag on the |
| 579 | ** last commit that holds that tag. |
| @@ -1263,10 +1263,11 @@ | |
| 1263 | ** Return 0 if not a branch, tag, or trunk, or if ignored by --ignore-tree. |
| 1264 | */ |
| 1265 | static int svn_parse_path(char *zPath, char **zFile, int *type){ |
| 1266 | char *zBranch = 0; |
| 1267 | int branchId = 0; |
| 1268 | if( gsvn.azIgnTree ){ |
| 1269 | const char **pzIgnTree; |
| 1270 | unsigned nPath = strlen(zPath); |
| 1271 | for( pzIgnTree = gsvn.azIgnTree; *pzIgnTree; ++pzIgnTree ){ |
| 1272 | const char *zIgn = *pzIgnTree; |
| @@ -1277,18 +1278,19 @@ | |
| 1277 | } |
| 1278 | } |
| 1279 | } |
| 1280 | *type = SVN_UNKNOWN; |
| 1281 | *zFile = 0; |
| 1282 | if( gsvn.lenTrunk==0 ){ |
| 1283 | zBranch = "trunk"; |
| 1284 | *zFile = zPath; |
| 1285 | *type = SVN_TRUNK; |
| 1286 | }else |
| 1287 | if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ |
| 1288 | if( zPath[gsvn.lenTrunk-1]=='/' || zPath[gsvn.lenTrunk-1]==0 ){ |
| 1289 | zBranch = "trunk"; |
| 1290 | *zFile = zPath+gsvn.lenTrunk; |
| 1291 | *type = SVN_TRUNK; |
| 1292 | }else{ |
| 1293 | zBranch = 0; |
| 1294 | *type = SVN_UNKNOWN; |
| @@ -1770,11 +1772,11 @@ | |
| 1770 | *renOpt->varSuf = renOpt->zDefaultSuf; |
| 1771 | } |
| 1772 | } |
| 1773 | } |
| 1774 | if( !(gimport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 1775 | gimport.zTrunkName = "trunk"; |
| 1776 | } |
| 1777 | |
| 1778 | if( svnFlag ){ |
| 1779 | /* Get --svn related options here, so verify_all_options() fails when |
| 1780 | * svn-only options are specified with --git |
| 1781 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -568,12 +568,12 @@ | |
| 568 | ** |
| 569 | ** (A) refs/heads/BRANCHNAME |
| 570 | ** (B) refs/tags/TAGNAME |
| 571 | ** |
| 572 | ** If pattern A is used, then the branchname used is as shown. |
| 573 | ** Except, the "master" branch which is the default branch name in Git |
| 574 | ** is changed to the default main branch name in Fossil (usually "trunk") |
| 575 | ** If the pattern is B, then the new commit should be on the same |
| 576 | ** branch as its parent. And, we might need to add the TAGNAME |
| 577 | ** tag to the new commit. However, if there are multiple instances |
| 578 | ** of pattern B with the same TAGNAME, then only put the tag on the |
| 579 | ** last commit that holds that tag. |
| @@ -1263,10 +1263,11 @@ | |
| 1263 | ** Return 0 if not a branch, tag, or trunk, or if ignored by --ignore-tree. |
| 1264 | */ |
| 1265 | static int svn_parse_path(char *zPath, char **zFile, int *type){ |
| 1266 | char *zBranch = 0; |
| 1267 | int branchId = 0; |
| 1268 | const char *zMainBranch; |
| 1269 | if( gsvn.azIgnTree ){ |
| 1270 | const char **pzIgnTree; |
| 1271 | unsigned nPath = strlen(zPath); |
| 1272 | for( pzIgnTree = gsvn.azIgnTree; *pzIgnTree; ++pzIgnTree ){ |
| 1273 | const char *zIgn = *pzIgnTree; |
| @@ -1277,18 +1278,19 @@ | |
| 1278 | } |
| 1279 | } |
| 1280 | } |
| 1281 | *type = SVN_UNKNOWN; |
| 1282 | *zFile = 0; |
| 1283 | zMainBranch = db_main_branch(); |
| 1284 | if( gsvn.lenTrunk==0 ){ |
| 1285 | zBranch = fossil_strdup(zMainBranch); |
| 1286 | *zFile = zPath; |
| 1287 | *type = SVN_TRUNK; |
| 1288 | }else |
| 1289 | if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){ |
| 1290 | if( zPath[gsvn.lenTrunk-1]=='/' || zPath[gsvn.lenTrunk-1]==0 ){ |
| 1291 | zBranch = fossil_strdup(zMainBranch); |
| 1292 | *zFile = zPath+gsvn.lenTrunk; |
| 1293 | *type = SVN_TRUNK; |
| 1294 | }else{ |
| 1295 | zBranch = 0; |
| 1296 | *type = SVN_UNKNOWN; |
| @@ -1770,11 +1772,11 @@ | |
| 1772 | *renOpt->varSuf = renOpt->zDefaultSuf; |
| 1773 | } |
| 1774 | } |
| 1775 | } |
| 1776 | if( !(gimport.zTrunkName = find_option("rename-trunk", 0, 1)) ){ |
| 1777 | gimport.zTrunkName = fossil_strdup(db_main_branch()); |
| 1778 | } |
| 1779 | |
| 1780 | if( svnFlag ){ |
| 1781 | /* Get --svn related options here, so verify_all_options() fails when |
| 1782 | * svn-only options are specified with --git |
| 1783 |
+5
-3
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1141,13 +1141,14 @@ | ||
| 1141 | 1141 | } |
| 1142 | 1142 | @ %s(zLinks)</td></tr> |
| 1143 | 1143 | } |
| 1144 | 1144 | |
| 1145 | 1145 | if( g.perm.Hyperlink ){ |
| 1146 | + const char *zMainBranch = db_main_branch(); | |
| 1146 | 1147 | @ <tr><th>Other Links:</th> |
| 1147 | 1148 | @ <td> |
| 1148 | - if( fossil_strcmp(zBrName, db_get("main-branch",0))!=0 ){ | |
| 1149 | + if( fossil_strcmp(zBrName, zMainBranch)!=0 ){ | |
| 1149 | 1150 | @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff</a> | |
| 1150 | 1151 | } |
| 1151 | 1152 | @ %z(href("%R/artifact/%!S",zUuid))manifest</a> |
| 1152 | 1153 | @ | %z(href("%R/ci_tags/%!S",zUuid))tags</a> |
| 1153 | 1154 | if( g.perm.Admin ){ |
| @@ -3717,10 +3718,11 @@ | ||
| 3717 | 3718 | style_header("Edit Check-in [%s]", zUuid); |
| 3718 | 3719 | if( P("preview") ){ |
| 3719 | 3720 | Blob suffix; |
| 3720 | 3721 | int nTag = 0; |
| 3721 | 3722 | const char *zDplyBr; /* Branch name used to determine BG color */ |
| 3723 | + const char *zMainBranch = db_main_branch(); | |
| 3722 | 3724 | if( zNewBrFlag[0] && zNewBranch[0] ){ |
| 3723 | 3725 | zDplyBr = zNewBranch; |
| 3724 | 3726 | }else{ |
| 3725 | 3727 | zDplyBr = zBranchName; |
| 3726 | 3728 | } |
| @@ -3729,11 +3731,11 @@ | ||
| 3729 | 3731 | @ <table border=0> |
| 3730 | 3732 | if( zNewColorFlag[0] && zNewColor && zNewColor[0] ){ |
| 3731 | 3733 | @ <tr><td style="background-color:%h(reasonable_bg_color(zNewColor,0));"> |
| 3732 | 3734 | }else if( zColor[0] ){ |
| 3733 | 3735 | @ <tr><td style="background-color:%h(reasonable_bg_color(zColor,0));"> |
| 3734 | - }else if( zDplyBr && fossil_strcmp(zDplyBr,"trunk")!=0 ){ | |
| 3736 | + }else if( zDplyBr && fossil_strcmp(zDplyBr, zMainBranch)!=0 ){ | |
| 3735 | 3737 | @ <tr><td style="background-color:%h(hash_color(zDplyBr));"> |
| 3736 | 3738 | }else{ |
| 3737 | 3739 | @ <tr><td> |
| 3738 | 3740 | } |
| 3739 | 3741 | @ %!W(blob_str(&comment)) |
| @@ -3855,11 +3857,11 @@ | ||
| 3855 | 3857 | } |
| 3856 | 3858 | db_finalize(&q); |
| 3857 | 3859 | @ </td></tr> |
| 3858 | 3860 | |
| 3859 | 3861 | if( !zBranchName ){ |
| 3860 | - zBranchName = db_get("main-branch", 0); | |
| 3862 | + zBranchName = fossil_strdup(db_main_branch()); | |
| 3861 | 3863 | } |
| 3862 | 3864 | if( !zNewBranch || !zNewBranch[0]){ |
| 3863 | 3865 | zNewBranch = zBranchName; |
| 3864 | 3866 | } |
| 3865 | 3867 | @ <tr><th align="right" valign="top">Branching:</th> |
| 3866 | 3868 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1141,13 +1141,14 @@ | |
| 1141 | } |
| 1142 | @ %s(zLinks)</td></tr> |
| 1143 | } |
| 1144 | |
| 1145 | if( g.perm.Hyperlink ){ |
| 1146 | @ <tr><th>Other Links:</th> |
| 1147 | @ <td> |
| 1148 | if( fossil_strcmp(zBrName, db_get("main-branch",0))!=0 ){ |
| 1149 | @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff</a> | |
| 1150 | } |
| 1151 | @ %z(href("%R/artifact/%!S",zUuid))manifest</a> |
| 1152 | @ | %z(href("%R/ci_tags/%!S",zUuid))tags</a> |
| 1153 | if( g.perm.Admin ){ |
| @@ -3717,10 +3718,11 @@ | |
| 3717 | style_header("Edit Check-in [%s]", zUuid); |
| 3718 | if( P("preview") ){ |
| 3719 | Blob suffix; |
| 3720 | int nTag = 0; |
| 3721 | const char *zDplyBr; /* Branch name used to determine BG color */ |
| 3722 | if( zNewBrFlag[0] && zNewBranch[0] ){ |
| 3723 | zDplyBr = zNewBranch; |
| 3724 | }else{ |
| 3725 | zDplyBr = zBranchName; |
| 3726 | } |
| @@ -3729,11 +3731,11 @@ | |
| 3729 | @ <table border=0> |
| 3730 | if( zNewColorFlag[0] && zNewColor && zNewColor[0] ){ |
| 3731 | @ <tr><td style="background-color:%h(reasonable_bg_color(zNewColor,0));"> |
| 3732 | }else if( zColor[0] ){ |
| 3733 | @ <tr><td style="background-color:%h(reasonable_bg_color(zColor,0));"> |
| 3734 | }else if( zDplyBr && fossil_strcmp(zDplyBr,"trunk")!=0 ){ |
| 3735 | @ <tr><td style="background-color:%h(hash_color(zDplyBr));"> |
| 3736 | }else{ |
| 3737 | @ <tr><td> |
| 3738 | } |
| 3739 | @ %!W(blob_str(&comment)) |
| @@ -3855,11 +3857,11 @@ | |
| 3855 | } |
| 3856 | db_finalize(&q); |
| 3857 | @ </td></tr> |
| 3858 | |
| 3859 | if( !zBranchName ){ |
| 3860 | zBranchName = db_get("main-branch", 0); |
| 3861 | } |
| 3862 | if( !zNewBranch || !zNewBranch[0]){ |
| 3863 | zNewBranch = zBranchName; |
| 3864 | } |
| 3865 | @ <tr><th align="right" valign="top">Branching:</th> |
| 3866 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1141,13 +1141,14 @@ | |
| 1141 | } |
| 1142 | @ %s(zLinks)</td></tr> |
| 1143 | } |
| 1144 | |
| 1145 | if( g.perm.Hyperlink ){ |
| 1146 | const char *zMainBranch = db_main_branch(); |
| 1147 | @ <tr><th>Other Links:</th> |
| 1148 | @ <td> |
| 1149 | if( fossil_strcmp(zBrName, zMainBranch)!=0 ){ |
| 1150 | @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff</a> | |
| 1151 | } |
| 1152 | @ %z(href("%R/artifact/%!S",zUuid))manifest</a> |
| 1153 | @ | %z(href("%R/ci_tags/%!S",zUuid))tags</a> |
| 1154 | if( g.perm.Admin ){ |
| @@ -3717,10 +3718,11 @@ | |
| 3718 | style_header("Edit Check-in [%s]", zUuid); |
| 3719 | if( P("preview") ){ |
| 3720 | Blob suffix; |
| 3721 | int nTag = 0; |
| 3722 | const char *zDplyBr; /* Branch name used to determine BG color */ |
| 3723 | const char *zMainBranch = db_main_branch(); |
| 3724 | if( zNewBrFlag[0] && zNewBranch[0] ){ |
| 3725 | zDplyBr = zNewBranch; |
| 3726 | }else{ |
| 3727 | zDplyBr = zBranchName; |
| 3728 | } |
| @@ -3729,11 +3731,11 @@ | |
| 3731 | @ <table border=0> |
| 3732 | if( zNewColorFlag[0] && zNewColor && zNewColor[0] ){ |
| 3733 | @ <tr><td style="background-color:%h(reasonable_bg_color(zNewColor,0));"> |
| 3734 | }else if( zColor[0] ){ |
| 3735 | @ <tr><td style="background-color:%h(reasonable_bg_color(zColor,0));"> |
| 3736 | }else if( zDplyBr && fossil_strcmp(zDplyBr, zMainBranch)!=0 ){ |
| 3737 | @ <tr><td style="background-color:%h(hash_color(zDplyBr));"> |
| 3738 | }else{ |
| 3739 | @ <tr><td> |
| 3740 | } |
| 3741 | @ %!W(blob_str(&comment)) |
| @@ -3855,11 +3857,11 @@ | |
| 3857 | } |
| 3858 | db_finalize(&q); |
| 3859 | @ </td></tr> |
| 3860 | |
| 3861 | if( !zBranchName ){ |
| 3862 | zBranchName = fossil_strdup(db_main_branch()); |
| 3863 | } |
| 3864 | if( !zNewBranch || !zNewBranch[0]){ |
| 3865 | zNewBranch = zBranchName; |
| 3866 | } |
| 3867 | @ <tr><th align="right" valign="top">Branching:</th> |
| 3868 |
+2
-1
| --- src/json_branch.c | ||
| +++ src/json_branch.c | ||
| @@ -313,10 +313,11 @@ | ||
| 313 | 313 | cson_value * payV = NULL; |
| 314 | 314 | cson_object * pay = NULL; |
| 315 | 315 | int rc = 0; |
| 316 | 316 | BranchCreateOptions opt; |
| 317 | 317 | char * zUuid = NULL; |
| 318 | + const char *zMainBranch = db_main_branch(); | |
| 318 | 319 | int rid = 0; |
| 319 | 320 | if( !g.perm.Write ){ |
| 320 | 321 | json_set_err(FSL_JSON_E_DENIED, |
| 321 | 322 | "Requires 'i' permissions."); |
| 322 | 323 | return NULL; |
| @@ -340,11 +341,11 @@ | ||
| 340 | 341 | opt.zBasis = json_find_option_cstr("basis",NULL,NULL); |
| 341 | 342 | if(!opt.zBasis && !g.isHTTP){ |
| 342 | 343 | opt.zBasis = json_command_arg(g.json.dispatchDepth+2); |
| 343 | 344 | } |
| 344 | 345 | if(!opt.zBasis){ |
| 345 | - opt.zBasis = "trunk"; | |
| 346 | + opt.zBasis = fossil_strdup(zMainBranch); | |
| 346 | 347 | } |
| 347 | 348 | opt.isPrivate = json_find_option_bool("private",NULL,NULL,-1); |
| 348 | 349 | if(-1==opt.isPrivate){ |
| 349 | 350 | if(!g.isHTTP){ |
| 350 | 351 | opt.isPrivate = (NULL != find_option("private","",0)); |
| 351 | 352 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -313,10 +313,11 @@ | |
| 313 | cson_value * payV = NULL; |
| 314 | cson_object * pay = NULL; |
| 315 | int rc = 0; |
| 316 | BranchCreateOptions opt; |
| 317 | char * zUuid = NULL; |
| 318 | int rid = 0; |
| 319 | if( !g.perm.Write ){ |
| 320 | json_set_err(FSL_JSON_E_DENIED, |
| 321 | "Requires 'i' permissions."); |
| 322 | return NULL; |
| @@ -340,11 +341,11 @@ | |
| 340 | opt.zBasis = json_find_option_cstr("basis",NULL,NULL); |
| 341 | if(!opt.zBasis && !g.isHTTP){ |
| 342 | opt.zBasis = json_command_arg(g.json.dispatchDepth+2); |
| 343 | } |
| 344 | if(!opt.zBasis){ |
| 345 | opt.zBasis = "trunk"; |
| 346 | } |
| 347 | opt.isPrivate = json_find_option_bool("private",NULL,NULL,-1); |
| 348 | if(-1==opt.isPrivate){ |
| 349 | if(!g.isHTTP){ |
| 350 | opt.isPrivate = (NULL != find_option("private","",0)); |
| 351 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -313,10 +313,11 @@ | |
| 313 | cson_value * payV = NULL; |
| 314 | cson_object * pay = NULL; |
| 315 | int rc = 0; |
| 316 | BranchCreateOptions opt; |
| 317 | char * zUuid = NULL; |
| 318 | const char *zMainBranch = db_main_branch(); |
| 319 | int rid = 0; |
| 320 | if( !g.perm.Write ){ |
| 321 | json_set_err(FSL_JSON_E_DENIED, |
| 322 | "Requires 'i' permissions."); |
| 323 | return NULL; |
| @@ -340,11 +341,11 @@ | |
| 341 | opt.zBasis = json_find_option_cstr("basis",NULL,NULL); |
| 342 | if(!opt.zBasis && !g.isHTTP){ |
| 343 | opt.zBasis = json_command_arg(g.json.dispatchDepth+2); |
| 344 | } |
| 345 | if(!opt.zBasis){ |
| 346 | opt.zBasis = fossil_strdup(zMainBranch); |
| 347 | } |
| 348 | opt.isPrivate = json_find_option_bool("private",NULL,NULL,-1); |
| 349 | if(-1==opt.isPrivate){ |
| 350 | if(!g.isHTTP){ |
| 351 | opt.isPrivate = (NULL != find_option("private","",0)); |
| 352 |
+3
-1
| --- src/leaf.c | ||
| +++ src/leaf.c | ||
| @@ -226,14 +226,16 @@ | ||
| 226 | 226 | int leaf_ambiguity_warning(int rid, int currentCkout){ |
| 227 | 227 | char *zBr; |
| 228 | 228 | Stmt q; |
| 229 | 229 | int n = 0; |
| 230 | 230 | Blob msg; |
| 231 | + const char *zMainBranch; | |
| 231 | 232 | if( leaf_ambiguity(rid)==0 ) return 0; |
| 233 | + zMainBranch = db_main_branch(); | |
| 232 | 234 | zBr = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", |
| 233 | 235 | TAG_BRANCH, rid); |
| 234 | - if( zBr==0 ) zBr = fossil_strdup("trunk"); | |
| 236 | + if( zBr==0 ) zBr = fossil_strdup(zMainBranch); | |
| 235 | 237 | blob_init(&msg, 0, 0); |
| 236 | 238 | blob_appendf(&msg, "WARNING: multiple open leaf check-ins on %s:", zBr); |
| 237 | 239 | db_prepare(&q, |
| 238 | 240 | "SELECT" |
| 239 | 241 | " (SELECT uuid FROM blob WHERE rid=leaf.rid)," |
| 240 | 242 |
| --- src/leaf.c | |
| +++ src/leaf.c | |
| @@ -226,14 +226,16 @@ | |
| 226 | int leaf_ambiguity_warning(int rid, int currentCkout){ |
| 227 | char *zBr; |
| 228 | Stmt q; |
| 229 | int n = 0; |
| 230 | Blob msg; |
| 231 | if( leaf_ambiguity(rid)==0 ) return 0; |
| 232 | zBr = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", |
| 233 | TAG_BRANCH, rid); |
| 234 | if( zBr==0 ) zBr = fossil_strdup("trunk"); |
| 235 | blob_init(&msg, 0, 0); |
| 236 | blob_appendf(&msg, "WARNING: multiple open leaf check-ins on %s:", zBr); |
| 237 | db_prepare(&q, |
| 238 | "SELECT" |
| 239 | " (SELECT uuid FROM blob WHERE rid=leaf.rid)," |
| 240 |
| --- src/leaf.c | |
| +++ src/leaf.c | |
| @@ -226,14 +226,16 @@ | |
| 226 | int leaf_ambiguity_warning(int rid, int currentCkout){ |
| 227 | char *zBr; |
| 228 | Stmt q; |
| 229 | int n = 0; |
| 230 | Blob msg; |
| 231 | const char *zMainBranch; |
| 232 | if( leaf_ambiguity(rid)==0 ) return 0; |
| 233 | zMainBranch = db_main_branch(); |
| 234 | zBr = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", |
| 235 | TAG_BRANCH, rid); |
| 236 | if( zBr==0 ) zBr = fossil_strdup(zMainBranch); |
| 237 | blob_init(&msg, 0, 0); |
| 238 | blob_appendf(&msg, "WARNING: multiple open leaf check-ins on %s:", zBr); |
| 239 | db_prepare(&q, |
| 240 | "SELECT" |
| 241 | " (SELECT uuid FROM blob WHERE rid=leaf.rid)," |
| 242 |
+1
| --- src/path.c | ||
| +++ src/path.c | ||
| @@ -192,10 +192,11 @@ | ||
| 192 | 192 | path_reset(); |
| 193 | 193 | path.brCost = branchCost; |
| 194 | 194 | path.pStart = path_new_node(iFrom, 0, 0); |
| 195 | 195 | if( iTo==iFrom ){ |
| 196 | 196 | path.pEnd = path.pStart; |
| 197 | + path.pEnd->u.pTo = 0; | |
| 197 | 198 | return path.pStart; |
| 198 | 199 | } |
| 199 | 200 | if( oneWayOnly && directOnly ){ |
| 200 | 201 | db_prepare(&s, |
| 201 | 202 | "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim" |
| 202 | 203 |
| --- src/path.c | |
| +++ src/path.c | |
| @@ -192,10 +192,11 @@ | |
| 192 | path_reset(); |
| 193 | path.brCost = branchCost; |
| 194 | path.pStart = path_new_node(iFrom, 0, 0); |
| 195 | if( iTo==iFrom ){ |
| 196 | path.pEnd = path.pStart; |
| 197 | return path.pStart; |
| 198 | } |
| 199 | if( oneWayOnly && directOnly ){ |
| 200 | db_prepare(&s, |
| 201 | "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim" |
| 202 |
| --- src/path.c | |
| +++ src/path.c | |
| @@ -192,10 +192,11 @@ | |
| 192 | path_reset(); |
| 193 | path.brCost = branchCost; |
| 194 | path.pStart = path_new_node(iFrom, 0, 0); |
| 195 | if( iTo==iFrom ){ |
| 196 | path.pEnd = path.pStart; |
| 197 | path.pEnd->u.pTo = 0; |
| 198 | return path.pStart; |
| 199 | } |
| 200 | if( oneWayOnly && directOnly ){ |
| 201 | db_prepare(&s, |
| 202 | "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim" |
| 203 |
+4
-3
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -351,11 +351,12 @@ | ||
| 351 | 351 | /* |
| 352 | 352 | ** Check to see if the "sym-trunk" tag exists. If not, create it |
| 353 | 353 | ** and attach it to the very first check-in. |
| 354 | 354 | */ |
| 355 | 355 | static void rebuild_tag_trunk(void){ |
| 356 | - int tagid = db_int(0, "SELECT 1 FROM tag WHERE tagname='sym-trunk'"); | |
| 356 | + const char *zMainBranch = db_main_branch(); | |
| 357 | + int tagid = db_int(0, "SELECT 1 FROM tag WHERE tagname='sym-%q'",zMainBranch); | |
| 357 | 358 | int rid; |
| 358 | 359 | char *zUuid; |
| 359 | 360 | |
| 360 | 361 | if( tagid>0 ) return; |
| 361 | 362 | rid = db_int(0, "SELECT pid FROM plink AS x WHERE NOT EXISTS(" |
| @@ -363,12 +364,12 @@ | ||
| 363 | 364 | if( rid==0 ) return; |
| 364 | 365 | |
| 365 | 366 | /* Add the trunk tag to the root of the whole tree */ |
| 366 | 367 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 367 | 368 | if( zUuid==0 ) return; |
| 368 | - tag_add_artifact("sym-", "trunk", zUuid, 0, 2, 0, 0); | |
| 369 | - tag_add_artifact("", "branch", zUuid, "trunk", 2, 0, 0); | |
| 369 | + tag_add_artifact("sym-", zMainBranch, zUuid, 0, 2, 0, 0); | |
| 370 | + tag_add_artifact("", "branch", zUuid, zMainBranch, 2, 0, 0); | |
| 370 | 371 | } |
| 371 | 372 | |
| 372 | 373 | /* |
| 373 | 374 | ** Core function to rebuild the information in the derived tables of a |
| 374 | 375 | ** fossil repository from the blobs. This function is shared between |
| 375 | 376 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -351,11 +351,12 @@ | |
| 351 | /* |
| 352 | ** Check to see if the "sym-trunk" tag exists. If not, create it |
| 353 | ** and attach it to the very first check-in. |
| 354 | */ |
| 355 | static void rebuild_tag_trunk(void){ |
| 356 | int tagid = db_int(0, "SELECT 1 FROM tag WHERE tagname='sym-trunk'"); |
| 357 | int rid; |
| 358 | char *zUuid; |
| 359 | |
| 360 | if( tagid>0 ) return; |
| 361 | rid = db_int(0, "SELECT pid FROM plink AS x WHERE NOT EXISTS(" |
| @@ -363,12 +364,12 @@ | |
| 363 | if( rid==0 ) return; |
| 364 | |
| 365 | /* Add the trunk tag to the root of the whole tree */ |
| 366 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 367 | if( zUuid==0 ) return; |
| 368 | tag_add_artifact("sym-", "trunk", zUuid, 0, 2, 0, 0); |
| 369 | tag_add_artifact("", "branch", zUuid, "trunk", 2, 0, 0); |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ** Core function to rebuild the information in the derived tables of a |
| 374 | ** fossil repository from the blobs. This function is shared between |
| 375 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -351,11 +351,12 @@ | |
| 351 | /* |
| 352 | ** Check to see if the "sym-trunk" tag exists. If not, create it |
| 353 | ** and attach it to the very first check-in. |
| 354 | */ |
| 355 | static void rebuild_tag_trunk(void){ |
| 356 | const char *zMainBranch = db_main_branch(); |
| 357 | int tagid = db_int(0, "SELECT 1 FROM tag WHERE tagname='sym-%q'",zMainBranch); |
| 358 | int rid; |
| 359 | char *zUuid; |
| 360 | |
| 361 | if( tagid>0 ) return; |
| 362 | rid = db_int(0, "SELECT pid FROM plink AS x WHERE NOT EXISTS(" |
| @@ -363,12 +364,12 @@ | |
| 364 | if( rid==0 ) return; |
| 365 | |
| 366 | /* Add the trunk tag to the root of the whole tree */ |
| 367 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 368 | if( zUuid==0 ) return; |
| 369 | tag_add_artifact("sym-", zMainBranch, zUuid, 0, 2, 0, 0); |
| 370 | tag_add_artifact("", "branch", zUuid, zMainBranch, 2, 0, 0); |
| 371 | } |
| 372 | |
| 373 | /* |
| 374 | ** Core function to rebuild the information in the derived tables of a |
| 375 | ** fossil repository from the blobs. This function is shared between |
| 376 |
+4
-2
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -852,11 +852,12 @@ | ||
| 852 | 852 | ){ |
| 853 | 853 | search_init(zPattern, "<mark>", "</mark>", " ... ", |
| 854 | 854 | SRCHFLG_STATIC|SRCHFLG_HTML); |
| 855 | 855 | if( (srchFlags & SRCH_DOC)!=0 ){ |
| 856 | 856 | char *zDocGlob = db_get("doc-glob",""); |
| 857 | - char *zDocBr = db_get("doc-branch","trunk"); | |
| 857 | + const char *zMainBranch = db_main_branch(); | |
| 858 | + char *zDocBr = db_get("doc-branch", zMainBranch); | |
| 858 | 859 | if( zDocGlob && zDocGlob[0] && zDocBr && zDocBr[0] ){ |
| 859 | 860 | Glob * pGlob = glob_create(zDocBr) |
| 860 | 861 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 861 | 862 | ** tokens. We're not actually doing glob matches here. */; |
| 862 | 863 | int i; |
| @@ -1986,11 +1987,12 @@ | ||
| 1986 | 1987 | ** and if the latest check-in on doc-br is in the unindexed set of |
| 1987 | 1988 | ** check-ins, then update all 'd' entries in FTSDOCS that have |
| 1988 | 1989 | ** changed. |
| 1989 | 1990 | */ |
| 1990 | 1991 | static void search_update_doc_index(void){ |
| 1991 | - const char *zDocBranches = db_get("doc-branch","trunk"); | |
| 1992 | + const char *zMainBranch = db_main_branch(); | |
| 1993 | + const char *zDocBranches = db_get("doc-branch", zMainBranch); | |
| 1992 | 1994 | int i; |
| 1993 | 1995 | Glob * pGlob = glob_create(zDocBranches) |
| 1994 | 1996 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 1995 | 1997 | ** tokens. We're not actually doing glob matches here. */; |
| 1996 | 1998 | if( !pGlob ) return; |
| 1997 | 1999 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -852,11 +852,12 @@ | |
| 852 | ){ |
| 853 | search_init(zPattern, "<mark>", "</mark>", " ... ", |
| 854 | SRCHFLG_STATIC|SRCHFLG_HTML); |
| 855 | if( (srchFlags & SRCH_DOC)!=0 ){ |
| 856 | char *zDocGlob = db_get("doc-glob",""); |
| 857 | char *zDocBr = db_get("doc-branch","trunk"); |
| 858 | if( zDocGlob && zDocGlob[0] && zDocBr && zDocBr[0] ){ |
| 859 | Glob * pGlob = glob_create(zDocBr) |
| 860 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 861 | ** tokens. We're not actually doing glob matches here. */; |
| 862 | int i; |
| @@ -1986,11 +1987,12 @@ | |
| 1986 | ** and if the latest check-in on doc-br is in the unindexed set of |
| 1987 | ** check-ins, then update all 'd' entries in FTSDOCS that have |
| 1988 | ** changed. |
| 1989 | */ |
| 1990 | static void search_update_doc_index(void){ |
| 1991 | const char *zDocBranches = db_get("doc-branch","trunk"); |
| 1992 | int i; |
| 1993 | Glob * pGlob = glob_create(zDocBranches) |
| 1994 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 1995 | ** tokens. We're not actually doing glob matches here. */; |
| 1996 | if( !pGlob ) return; |
| 1997 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -852,11 +852,12 @@ | |
| 852 | ){ |
| 853 | search_init(zPattern, "<mark>", "</mark>", " ... ", |
| 854 | SRCHFLG_STATIC|SRCHFLG_HTML); |
| 855 | if( (srchFlags & SRCH_DOC)!=0 ){ |
| 856 | char *zDocGlob = db_get("doc-glob",""); |
| 857 | const char *zMainBranch = db_main_branch(); |
| 858 | char *zDocBr = db_get("doc-branch", zMainBranch); |
| 859 | if( zDocGlob && zDocGlob[0] && zDocBr && zDocBr[0] ){ |
| 860 | Glob * pGlob = glob_create(zDocBr) |
| 861 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 862 | ** tokens. We're not actually doing glob matches here. */; |
| 863 | int i; |
| @@ -1986,11 +1987,12 @@ | |
| 1987 | ** and if the latest check-in on doc-br is in the unindexed set of |
| 1988 | ** check-ins, then update all 'd' entries in FTSDOCS that have |
| 1989 | ** changed. |
| 1990 | */ |
| 1991 | static void search_update_doc_index(void){ |
| 1992 | const char *zMainBranch = db_main_branch(); |
| 1993 | const char *zDocBranches = db_get("doc-branch", zMainBranch); |
| 1994 | int i; |
| 1995 | Glob * pGlob = glob_create(zDocBranches) |
| 1996 | /* We're misusing a Glob as a list of comma-/space-delimited |
| 1997 | ** tokens. We're not actually doing glob matches here. */; |
| 1998 | if( !pGlob ) return; |
| 1999 |
+5
-2
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -2282,10 +2282,11 @@ | ||
| 2282 | 2282 | ** WEBPAGE: srchsetup |
| 2283 | 2283 | ** |
| 2284 | 2284 | ** Configure the search engine. Requires Admin privilege. |
| 2285 | 2285 | */ |
| 2286 | 2286 | void page_srchsetup(){ |
| 2287 | + const char *zMainBranch; | |
| 2287 | 2288 | login_check_credentials(); |
| 2288 | 2289 | if( !g.perm.Admin ){ |
| 2289 | 2290 | login_needed(0); |
| 2290 | 2291 | return; |
| 2291 | 2292 | } |
| @@ -2312,13 +2313,15 @@ | ||
| 2312 | 2313 | @ <tr><td>*<td><td>Search all checked-in files</tr> |
| 2313 | 2314 | @ <tr><td><i>(blank)</i><td> |
| 2314 | 2315 | @ <td>Search nothing. (Disables document search).</tr> |
| 2315 | 2316 | @ </table> |
| 2316 | 2317 | @ <hr> |
| 2317 | - entry_attribute("Document Branches", 20, "doc-branch", "db", "trunk", 0); | |
| 2318 | + zMainBranch = db_main_branch(); | |
| 2319 | + entry_attribute("Document Branches", 20, "doc-branch", "db", zMainBranch, 0); | |
| 2318 | 2320 | @ <p>When searching documents, use the versions of the files found at the |
| 2319 | - @ type of the "Document Branches" branch. Recommended value: "trunk". | |
| 2321 | + @ type of the "Document Branches" branch. Recommended value: the name of | |
| 2322 | + @ the main branch (usually "trunk"). | |
| 2320 | 2323 | @ Document search is disabled if blank. It may be a list of branch names |
| 2321 | 2324 | @ separated by spaces and/or commas. |
| 2322 | 2325 | @ <hr> |
| 2323 | 2326 | onoff_attribute("Search Check-in Comments", "search-ci", "sc", 0, 0); |
| 2324 | 2327 | @ <br> |
| 2325 | 2328 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -2282,10 +2282,11 @@ | |
| 2282 | ** WEBPAGE: srchsetup |
| 2283 | ** |
| 2284 | ** Configure the search engine. Requires Admin privilege. |
| 2285 | */ |
| 2286 | void page_srchsetup(){ |
| 2287 | login_check_credentials(); |
| 2288 | if( !g.perm.Admin ){ |
| 2289 | login_needed(0); |
| 2290 | return; |
| 2291 | } |
| @@ -2312,13 +2313,15 @@ | |
| 2312 | @ <tr><td>*<td><td>Search all checked-in files</tr> |
| 2313 | @ <tr><td><i>(blank)</i><td> |
| 2314 | @ <td>Search nothing. (Disables document search).</tr> |
| 2315 | @ </table> |
| 2316 | @ <hr> |
| 2317 | entry_attribute("Document Branches", 20, "doc-branch", "db", "trunk", 0); |
| 2318 | @ <p>When searching documents, use the versions of the files found at the |
| 2319 | @ type of the "Document Branches" branch. Recommended value: "trunk". |
| 2320 | @ Document search is disabled if blank. It may be a list of branch names |
| 2321 | @ separated by spaces and/or commas. |
| 2322 | @ <hr> |
| 2323 | onoff_attribute("Search Check-in Comments", "search-ci", "sc", 0, 0); |
| 2324 | @ <br> |
| 2325 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -2282,10 +2282,11 @@ | |
| 2282 | ** WEBPAGE: srchsetup |
| 2283 | ** |
| 2284 | ** Configure the search engine. Requires Admin privilege. |
| 2285 | */ |
| 2286 | void page_srchsetup(){ |
| 2287 | const char *zMainBranch; |
| 2288 | login_check_credentials(); |
| 2289 | if( !g.perm.Admin ){ |
| 2290 | login_needed(0); |
| 2291 | return; |
| 2292 | } |
| @@ -2312,13 +2313,15 @@ | |
| 2313 | @ <tr><td>*<td><td>Search all checked-in files</tr> |
| 2314 | @ <tr><td><i>(blank)</i><td> |
| 2315 | @ <td>Search nothing. (Disables document search).</tr> |
| 2316 | @ </table> |
| 2317 | @ <hr> |
| 2318 | zMainBranch = db_main_branch(); |
| 2319 | entry_attribute("Document Branches", 20, "doc-branch", "db", zMainBranch, 0); |
| 2320 | @ <p>When searching documents, use the versions of the files found at the |
| 2321 | @ type of the "Document Branches" branch. Recommended value: the name of |
| 2322 | @ the main branch (usually "trunk"). |
| 2323 | @ Document search is disabled if blank. It may be a list of branch names |
| 2324 | @ separated by spaces and/or commas. |
| 2325 | @ <hr> |
| 2326 | onoff_attribute("Search Check-in Comments", "search-ci", "sc", 0, 0); |
| 2327 | @ <br> |
| 2328 |
+12
-8
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -38,10 +38,11 @@ | ||
| 38 | 38 | ** "_" and "-". Changes are made in-place. |
| 39 | 39 | */ |
| 40 | 40 | static void sanitize_name(char *zName){ |
| 41 | 41 | int i; |
| 42 | 42 | char c; |
| 43 | + if( zName==0 ) return; | |
| 43 | 44 | for(i=0; (c = zName[i])!=0; i++){ |
| 44 | 45 | if( fossil_isupper(c) ){ |
| 45 | 46 | zName[i] = fossil_tolower(c); |
| 46 | 47 | }else if( !fossil_isalnum(c) && c!='_' && c!='-' ){ |
| 47 | 48 | if( c<=0x7f ){ |
| @@ -77,14 +78,13 @@ | ||
| 77 | 78 | } |
| 78 | 79 | zName = db_text(0, |
| 79 | 80 | "SELECT %Q||" |
| 80 | 81 | " strftime('-%%Y%%m%%d%%H%%M%%S-',event.mtime)||" |
| 81 | 82 | " substr(blob.uuid,1,10)" |
| 82 | - " FROM blob, event LEFT JOIN config" | |
| 83 | + " FROM blob, event" | |
| 83 | 84 | " WHERE blob.rid=%d" |
| 84 | - " AND event.objid=%d" | |
| 85 | - " AND config.name='project-name'", | |
| 85 | + " AND event.objid=%d", | |
| 86 | 86 | zPrefix, rid, rid); |
| 87 | 87 | fossil_free(zPrefix); |
| 88 | 88 | sanitize_name(zName); |
| 89 | 89 | return zName; |
| 90 | 90 | } |
| @@ -884,11 +884,12 @@ | ||
| 884 | 884 | ** Generate a compressed tarball for the check-in specified by VERSION. |
| 885 | 885 | ** The tarball is called NAME.tar.gz and has a top-level directory called |
| 886 | 886 | ** NAME. If TAG is provided, then VERSION must hold TAG or else an error |
| 887 | 887 | ** is returned. |
| 888 | 888 | ** |
| 889 | -** The optional VERSION element defaults to "trunk" per the r= rules below. | |
| 889 | +** The optional VERSION element defaults to the name of the main branch | |
| 890 | +** (usually "trunk") per the r= rules below. | |
| 890 | 891 | ** All of the following URLs are equivalent: |
| 891 | 892 | ** |
| 892 | 893 | ** /tarball/release/xyz.tar.gz |
| 893 | 894 | ** /tarball?r=release&name=xyz.tar.gz |
| 894 | 895 | ** /tarball/xyz.tar.gz?r=release |
| @@ -897,23 +898,26 @@ | ||
| 897 | 898 | ** Query parameters: |
| 898 | 899 | ** |
| 899 | 900 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 900 | 901 | ** identifies the check-in from which the tarball is |
| 901 | 902 | ** constructed. If CKIN is omitted and there is no |
| 902 | -** r= query parameter, then use "trunk". NAME is the | |
| 903 | +** r= query parameter, then use the name of the main | |
| 904 | +** branch (usually "trunk"). NAME is the | |
| 903 | 905 | ** name of the download file. The top-level directory |
| 904 | 906 | ** in the generated tarball is called by NAME with the |
| 905 | 907 | ** file extension removed. |
| 906 | 908 | ** |
| 907 | 909 | ** r=TAG TAG identifies the check-in that is turned into a |
| 908 | -** compressed tarball. The default value is "trunk". | |
| 910 | +** compressed tarball. The default value is the name of | |
| 911 | +** the main branch (usually "trunk"). | |
| 909 | 912 | ** If r= is omitted and if the name= query parameter |
| 910 | 913 | ** contains one "/" character then the of part the |
| 911 | 914 | ** name= value before the / becomes the TAG and the |
| 912 | 915 | ** part of the name= value after the / is the download |
| 913 | 916 | ** filename. If no check-in is specified by either |
| 914 | -** name= or r=, then "trunk" is used. | |
| 917 | +** name= or r=, then the name of the main branch | |
| 918 | +** (usually "trunk") is used. | |
| 915 | 919 | ** |
| 916 | 920 | ** in=PATTERN Only include files that match the comma-separate |
| 917 | 921 | ** list of GLOB patterns in PATTERN, as with ex= |
| 918 | 922 | ** |
| 919 | 923 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -954,11 +958,11 @@ | ||
| 954 | 958 | fossil_nice_default(); |
| 955 | 959 | zName = fossil_strdup(PD("name","")); |
| 956 | 960 | z = P("r"); |
| 957 | 961 | if( z==0 ) z = P("uuid"); |
| 958 | 962 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 959 | - if( z==0 ) z = "trunk"; | |
| 963 | + if( z==0 ) z = fossil_strdup(db_main_branch()); | |
| 960 | 964 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 961 | 965 | nRid = strlen(zRid); |
| 962 | 966 | zInclude = P("in"); |
| 963 | 967 | if( zInclude ) pInclude = glob_create(zInclude); |
| 964 | 968 | zExclude = P("ex"); |
| 965 | 969 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -38,10 +38,11 @@ | |
| 38 | ** "_" and "-". Changes are made in-place. |
| 39 | */ |
| 40 | static void sanitize_name(char *zName){ |
| 41 | int i; |
| 42 | char c; |
| 43 | for(i=0; (c = zName[i])!=0; i++){ |
| 44 | if( fossil_isupper(c) ){ |
| 45 | zName[i] = fossil_tolower(c); |
| 46 | }else if( !fossil_isalnum(c) && c!='_' && c!='-' ){ |
| 47 | if( c<=0x7f ){ |
| @@ -77,14 +78,13 @@ | |
| 77 | } |
| 78 | zName = db_text(0, |
| 79 | "SELECT %Q||" |
| 80 | " strftime('-%%Y%%m%%d%%H%%M%%S-',event.mtime)||" |
| 81 | " substr(blob.uuid,1,10)" |
| 82 | " FROM blob, event LEFT JOIN config" |
| 83 | " WHERE blob.rid=%d" |
| 84 | " AND event.objid=%d" |
| 85 | " AND config.name='project-name'", |
| 86 | zPrefix, rid, rid); |
| 87 | fossil_free(zPrefix); |
| 88 | sanitize_name(zName); |
| 89 | return zName; |
| 90 | } |
| @@ -884,11 +884,12 @@ | |
| 884 | ** Generate a compressed tarball for the check-in specified by VERSION. |
| 885 | ** The tarball is called NAME.tar.gz and has a top-level directory called |
| 886 | ** NAME. If TAG is provided, then VERSION must hold TAG or else an error |
| 887 | ** is returned. |
| 888 | ** |
| 889 | ** The optional VERSION element defaults to "trunk" per the r= rules below. |
| 890 | ** All of the following URLs are equivalent: |
| 891 | ** |
| 892 | ** /tarball/release/xyz.tar.gz |
| 893 | ** /tarball?r=release&name=xyz.tar.gz |
| 894 | ** /tarball/xyz.tar.gz?r=release |
| @@ -897,23 +898,26 @@ | |
| 897 | ** Query parameters: |
| 898 | ** |
| 899 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 900 | ** identifies the check-in from which the tarball is |
| 901 | ** constructed. If CKIN is omitted and there is no |
| 902 | ** r= query parameter, then use "trunk". NAME is the |
| 903 | ** name of the download file. The top-level directory |
| 904 | ** in the generated tarball is called by NAME with the |
| 905 | ** file extension removed. |
| 906 | ** |
| 907 | ** r=TAG TAG identifies the check-in that is turned into a |
| 908 | ** compressed tarball. The default value is "trunk". |
| 909 | ** If r= is omitted and if the name= query parameter |
| 910 | ** contains one "/" character then the of part the |
| 911 | ** name= value before the / becomes the TAG and the |
| 912 | ** part of the name= value after the / is the download |
| 913 | ** filename. If no check-in is specified by either |
| 914 | ** name= or r=, then "trunk" is used. |
| 915 | ** |
| 916 | ** in=PATTERN Only include files that match the comma-separate |
| 917 | ** list of GLOB patterns in PATTERN, as with ex= |
| 918 | ** |
| 919 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -954,11 +958,11 @@ | |
| 954 | fossil_nice_default(); |
| 955 | zName = fossil_strdup(PD("name","")); |
| 956 | z = P("r"); |
| 957 | if( z==0 ) z = P("uuid"); |
| 958 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 959 | if( z==0 ) z = "trunk"; |
| 960 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 961 | nRid = strlen(zRid); |
| 962 | zInclude = P("in"); |
| 963 | if( zInclude ) pInclude = glob_create(zInclude); |
| 964 | zExclude = P("ex"); |
| 965 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -38,10 +38,11 @@ | |
| 38 | ** "_" and "-". Changes are made in-place. |
| 39 | */ |
| 40 | static void sanitize_name(char *zName){ |
| 41 | int i; |
| 42 | char c; |
| 43 | if( zName==0 ) return; |
| 44 | for(i=0; (c = zName[i])!=0; i++){ |
| 45 | if( fossil_isupper(c) ){ |
| 46 | zName[i] = fossil_tolower(c); |
| 47 | }else if( !fossil_isalnum(c) && c!='_' && c!='-' ){ |
| 48 | if( c<=0x7f ){ |
| @@ -77,14 +78,13 @@ | |
| 78 | } |
| 79 | zName = db_text(0, |
| 80 | "SELECT %Q||" |
| 81 | " strftime('-%%Y%%m%%d%%H%%M%%S-',event.mtime)||" |
| 82 | " substr(blob.uuid,1,10)" |
| 83 | " FROM blob, event" |
| 84 | " WHERE blob.rid=%d" |
| 85 | " AND event.objid=%d", |
| 86 | zPrefix, rid, rid); |
| 87 | fossil_free(zPrefix); |
| 88 | sanitize_name(zName); |
| 89 | return zName; |
| 90 | } |
| @@ -884,11 +884,12 @@ | |
| 884 | ** Generate a compressed tarball for the check-in specified by VERSION. |
| 885 | ** The tarball is called NAME.tar.gz and has a top-level directory called |
| 886 | ** NAME. If TAG is provided, then VERSION must hold TAG or else an error |
| 887 | ** is returned. |
| 888 | ** |
| 889 | ** The optional VERSION element defaults to the name of the main branch |
| 890 | ** (usually "trunk") per the r= rules below. |
| 891 | ** All of the following URLs are equivalent: |
| 892 | ** |
| 893 | ** /tarball/release/xyz.tar.gz |
| 894 | ** /tarball?r=release&name=xyz.tar.gz |
| 895 | ** /tarball/xyz.tar.gz?r=release |
| @@ -897,23 +898,26 @@ | |
| 898 | ** Query parameters: |
| 899 | ** |
| 900 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 901 | ** identifies the check-in from which the tarball is |
| 902 | ** constructed. If CKIN is omitted and there is no |
| 903 | ** r= query parameter, then use the name of the main |
| 904 | ** branch (usually "trunk"). NAME is the |
| 905 | ** name of the download file. The top-level directory |
| 906 | ** in the generated tarball is called by NAME with the |
| 907 | ** file extension removed. |
| 908 | ** |
| 909 | ** r=TAG TAG identifies the check-in that is turned into a |
| 910 | ** compressed tarball. The default value is the name of |
| 911 | ** the main branch (usually "trunk"). |
| 912 | ** If r= is omitted and if the name= query parameter |
| 913 | ** contains one "/" character then the of part the |
| 914 | ** name= value before the / becomes the TAG and the |
| 915 | ** part of the name= value after the / is the download |
| 916 | ** filename. If no check-in is specified by either |
| 917 | ** name= or r=, then the name of the main branch |
| 918 | ** (usually "trunk") is used. |
| 919 | ** |
| 920 | ** in=PATTERN Only include files that match the comma-separate |
| 921 | ** list of GLOB patterns in PATTERN, as with ex= |
| 922 | ** |
| 923 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -954,11 +958,11 @@ | |
| 958 | fossil_nice_default(); |
| 959 | zName = fossil_strdup(PD("name","")); |
| 960 | z = P("r"); |
| 961 | if( z==0 ) z = P("uuid"); |
| 962 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 963 | if( z==0 ) z = fossil_strdup(db_main_branch()); |
| 964 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 965 | nRid = strlen(zRid); |
| 966 | zInclude = P("in"); |
| 967 | if( zInclude ) pInclude = glob_create(zInclude); |
| 968 | zExclude = P("ex"); |
| 969 |
+2
-2
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -388,11 +388,11 @@ | ||
| 388 | 388 | const char *zStyle; /* Sub-name for classes for the style */ |
| 389 | 389 | const char *zDateFmt; |
| 390 | 390 | int iTableId = timeline_tableid(); |
| 391 | 391 | int bTimestampLinksToInfo; /* True if timestamp hyperlinks go to the /info |
| 392 | 392 | ** page rather than the /timeline page */ |
| 393 | - char *zMainBranch = db_get("main-branch","trunk"); | |
| 393 | + const char *zMainBranch = db_main_branch(); | |
| 394 | 394 | |
| 395 | 395 | |
| 396 | 396 | if( cgi_is_loopback(g.zIpAddr) && db_open_local(0) ){ |
| 397 | 397 | vid = db_lget_int("checkout", 0); |
| 398 | 398 | } |
| @@ -592,11 +592,11 @@ | ||
| 592 | 592 | zBr = branch_of_rid(rid); |
| 593 | 593 | if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){ |
| 594 | 594 | /* If no background color is specified, use a color based on the |
| 595 | 595 | ** branch name */ |
| 596 | 596 | if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){ |
| 597 | - }else if( zBr==0 || strcmp(zBr,zMainBranch)==0 ){ | |
| 597 | + }else if( zBr==0 || strcmp(zBr, zMainBranch)==0 ){ | |
| 598 | 598 | zBgClr = 0; |
| 599 | 599 | }else{ |
| 600 | 600 | zBgClr = hash_color(zBr); |
| 601 | 601 | } |
| 602 | 602 | } |
| 603 | 603 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -388,11 +388,11 @@ | |
| 388 | const char *zStyle; /* Sub-name for classes for the style */ |
| 389 | const char *zDateFmt; |
| 390 | int iTableId = timeline_tableid(); |
| 391 | int bTimestampLinksToInfo; /* True if timestamp hyperlinks go to the /info |
| 392 | ** page rather than the /timeline page */ |
| 393 | char *zMainBranch = db_get("main-branch","trunk"); |
| 394 | |
| 395 | |
| 396 | if( cgi_is_loopback(g.zIpAddr) && db_open_local(0) ){ |
| 397 | vid = db_lget_int("checkout", 0); |
| 398 | } |
| @@ -592,11 +592,11 @@ | |
| 592 | zBr = branch_of_rid(rid); |
| 593 | if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){ |
| 594 | /* If no background color is specified, use a color based on the |
| 595 | ** branch name */ |
| 596 | if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){ |
| 597 | }else if( zBr==0 || strcmp(zBr,zMainBranch)==0 ){ |
| 598 | zBgClr = 0; |
| 599 | }else{ |
| 600 | zBgClr = hash_color(zBr); |
| 601 | } |
| 602 | } |
| 603 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -388,11 +388,11 @@ | |
| 388 | const char *zStyle; /* Sub-name for classes for the style */ |
| 389 | const char *zDateFmt; |
| 390 | int iTableId = timeline_tableid(); |
| 391 | int bTimestampLinksToInfo; /* True if timestamp hyperlinks go to the /info |
| 392 | ** page rather than the /timeline page */ |
| 393 | const char *zMainBranch = db_main_branch(); |
| 394 | |
| 395 | |
| 396 | if( cgi_is_loopback(g.zIpAddr) && db_open_local(0) ){ |
| 397 | vid = db_lget_int("checkout", 0); |
| 398 | } |
| @@ -592,11 +592,11 @@ | |
| 592 | zBr = branch_of_rid(rid); |
| 593 | if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){ |
| 594 | /* If no background color is specified, use a color based on the |
| 595 | ** branch name */ |
| 596 | if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){ |
| 597 | }else if( zBr==0 || strcmp(zBr, zMainBranch)==0 ){ |
| 598 | zBgClr = 0; |
| 599 | }else{ |
| 600 | zBgClr = hash_color(zBr); |
| 601 | } |
| 602 | } |
| 603 |
+1
-1
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -756,11 +756,11 @@ | ||
| 756 | 756 | |
| 757 | 757 | /* Determine the check-in manifest artifact ID. Panic on failure. */ |
| 758 | 758 | if( zRevision ){ |
| 759 | 759 | vid = name_to_typed_rid(zRevision, "ci"); |
| 760 | 760 | }else if( !g.localOpen ){ |
| 761 | - vid = name_to_typed_rid(db_get("main-branch", 0), "ci"); | |
| 761 | + vid = name_to_typed_rid(db_main_branch(), "ci"); | |
| 762 | 762 | }else{ |
| 763 | 763 | vid = db_lget_int("checkout", 0); |
| 764 | 764 | if( !is_a_version(vid) ){ |
| 765 | 765 | if( vid==0 ) return 0; |
| 766 | 766 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 767 | 767 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -756,11 +756,11 @@ | |
| 756 | |
| 757 | /* Determine the check-in manifest artifact ID. Panic on failure. */ |
| 758 | if( zRevision ){ |
| 759 | vid = name_to_typed_rid(zRevision, "ci"); |
| 760 | }else if( !g.localOpen ){ |
| 761 | vid = name_to_typed_rid(db_get("main-branch", 0), "ci"); |
| 762 | }else{ |
| 763 | vid = db_lget_int("checkout", 0); |
| 764 | if( !is_a_version(vid) ){ |
| 765 | if( vid==0 ) return 0; |
| 766 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 767 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -756,11 +756,11 @@ | |
| 756 | |
| 757 | /* Determine the check-in manifest artifact ID. Panic on failure. */ |
| 758 | if( zRevision ){ |
| 759 | vid = name_to_typed_rid(zRevision, "ci"); |
| 760 | }else if( !g.localOpen ){ |
| 761 | vid = name_to_typed_rid(db_main_branch(), "ci"); |
| 762 | }else{ |
| 763 | vid = db_lget_int("checkout", 0); |
| 764 | if( !is_a_version(vid) ){ |
| 765 | if( vid==0 ) return 0; |
| 766 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 767 |
+9
-5
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -953,11 +953,12 @@ | ||
| 953 | 953 | ** |
| 954 | 954 | ** Generate a ZIP Archive or an SQL Archive for the check-in specified by |
| 955 | 955 | ** VERSION. The archive is called NAME.zip or NAME.sqlar and has a top-level |
| 956 | 956 | ** directory called NAME. |
| 957 | 957 | ** |
| 958 | -** The optional VERSION element defaults to "trunk" per the r= rules below. | |
| 958 | +** The optional VERSION element defaults to the name of the main branch | |
| 959 | +** (usually "trunk") per the r= rules below. | |
| 959 | 960 | ** All of the following URLs are equivalent: |
| 960 | 961 | ** |
| 961 | 962 | ** /zip/release/xyz.zip |
| 962 | 963 | ** /zip?r=release&name=xyz.zip |
| 963 | 964 | ** /zip/xyz.zip?r=release |
| @@ -966,23 +967,26 @@ | ||
| 966 | 967 | ** Query parameters: |
| 967 | 968 | ** |
| 968 | 969 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 969 | 970 | ** identifies the check-in from which the archive is |
| 970 | 971 | ** constructed. If CKIN is omitted and there is no |
| 971 | -** r= query parameter, then use "trunk". NAME is the | |
| 972 | +** r= query parameter, then use the name of the main | |
| 973 | +** branch (usually "trunk"). NAME is the | |
| 972 | 974 | ** name of the download file. The top-level directory |
| 973 | 975 | ** in the generated archive is called by NAME with the |
| 974 | 976 | ** file extension removed. |
| 975 | 977 | ** |
| 976 | 978 | ** r=TAG TAG identifies the check-in that is turned into an |
| 977 | -** SQL or ZIP archive. The default value is "trunk". | |
| 979 | +** SQL or ZIP archive. The default value is the name | |
| 980 | +** of the main branch (usually "trunk"). | |
| 978 | 981 | ** If r= is omitted and if the name= query parameter |
| 979 | 982 | ** contains one "/" character then the of part the |
| 980 | 983 | ** name= value before the / becomes the TAG and the |
| 981 | 984 | ** part of the name= value after the / is the download |
| 982 | 985 | ** filename. If no check-in is specified by either |
| 983 | -** name= or r=, then "trunk" is used. | |
| 986 | +** name= or r=, then the name of the main branch | |
| 987 | +** (usually "trunk") is used. | |
| 984 | 988 | ** |
| 985 | 989 | ** in=PATTERN Only include files that match the comma-separate |
| 986 | 990 | ** list of GLOB patterns in PATTERN, as with ex= |
| 987 | 991 | ** |
| 988 | 992 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -1032,11 +1036,11 @@ | ||
| 1032 | 1036 | fossil_nice_default(); |
| 1033 | 1037 | zName = fossil_strdup(PD("name","")); |
| 1034 | 1038 | z = P("r"); |
| 1035 | 1039 | if( z==0 ) z = P("uuid"); |
| 1036 | 1040 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 1037 | - if( z==0 ) z = "trunk"; | |
| 1041 | + if( z==0 ) z = fossil_strdup(db_main_branch()); | |
| 1038 | 1042 | nName = strlen(zName); |
| 1039 | 1043 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 1040 | 1044 | nRid = strlen(zRid); |
| 1041 | 1045 | zInclude = P("in"); |
| 1042 | 1046 | if( zInclude ) pInclude = glob_create(zInclude); |
| 1043 | 1047 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -953,11 +953,12 @@ | |
| 953 | ** |
| 954 | ** Generate a ZIP Archive or an SQL Archive for the check-in specified by |
| 955 | ** VERSION. The archive is called NAME.zip or NAME.sqlar and has a top-level |
| 956 | ** directory called NAME. |
| 957 | ** |
| 958 | ** The optional VERSION element defaults to "trunk" per the r= rules below. |
| 959 | ** All of the following URLs are equivalent: |
| 960 | ** |
| 961 | ** /zip/release/xyz.zip |
| 962 | ** /zip?r=release&name=xyz.zip |
| 963 | ** /zip/xyz.zip?r=release |
| @@ -966,23 +967,26 @@ | |
| 966 | ** Query parameters: |
| 967 | ** |
| 968 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 969 | ** identifies the check-in from which the archive is |
| 970 | ** constructed. If CKIN is omitted and there is no |
| 971 | ** r= query parameter, then use "trunk". NAME is the |
| 972 | ** name of the download file. The top-level directory |
| 973 | ** in the generated archive is called by NAME with the |
| 974 | ** file extension removed. |
| 975 | ** |
| 976 | ** r=TAG TAG identifies the check-in that is turned into an |
| 977 | ** SQL or ZIP archive. The default value is "trunk". |
| 978 | ** If r= is omitted and if the name= query parameter |
| 979 | ** contains one "/" character then the of part the |
| 980 | ** name= value before the / becomes the TAG and the |
| 981 | ** part of the name= value after the / is the download |
| 982 | ** filename. If no check-in is specified by either |
| 983 | ** name= or r=, then "trunk" is used. |
| 984 | ** |
| 985 | ** in=PATTERN Only include files that match the comma-separate |
| 986 | ** list of GLOB patterns in PATTERN, as with ex= |
| 987 | ** |
| 988 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -1032,11 +1036,11 @@ | |
| 1032 | fossil_nice_default(); |
| 1033 | zName = fossil_strdup(PD("name","")); |
| 1034 | z = P("r"); |
| 1035 | if( z==0 ) z = P("uuid"); |
| 1036 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 1037 | if( z==0 ) z = "trunk"; |
| 1038 | nName = strlen(zName); |
| 1039 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 1040 | nRid = strlen(zRid); |
| 1041 | zInclude = P("in"); |
| 1042 | if( zInclude ) pInclude = glob_create(zInclude); |
| 1043 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -953,11 +953,12 @@ | |
| 953 | ** |
| 954 | ** Generate a ZIP Archive or an SQL Archive for the check-in specified by |
| 955 | ** VERSION. The archive is called NAME.zip or NAME.sqlar and has a top-level |
| 956 | ** directory called NAME. |
| 957 | ** |
| 958 | ** The optional VERSION element defaults to the name of the main branch |
| 959 | ** (usually "trunk") per the r= rules below. |
| 960 | ** All of the following URLs are equivalent: |
| 961 | ** |
| 962 | ** /zip/release/xyz.zip |
| 963 | ** /zip?r=release&name=xyz.zip |
| 964 | ** /zip/xyz.zip?r=release |
| @@ -966,23 +967,26 @@ | |
| 967 | ** Query parameters: |
| 968 | ** |
| 969 | ** name=[CKIN/]NAME The optional CKIN component of the name= parameter |
| 970 | ** identifies the check-in from which the archive is |
| 971 | ** constructed. If CKIN is omitted and there is no |
| 972 | ** r= query parameter, then use the name of the main |
| 973 | ** branch (usually "trunk"). NAME is the |
| 974 | ** name of the download file. The top-level directory |
| 975 | ** in the generated archive is called by NAME with the |
| 976 | ** file extension removed. |
| 977 | ** |
| 978 | ** r=TAG TAG identifies the check-in that is turned into an |
| 979 | ** SQL or ZIP archive. The default value is the name |
| 980 | ** of the main branch (usually "trunk"). |
| 981 | ** If r= is omitted and if the name= query parameter |
| 982 | ** contains one "/" character then the of part the |
| 983 | ** name= value before the / becomes the TAG and the |
| 984 | ** part of the name= value after the / is the download |
| 985 | ** filename. If no check-in is specified by either |
| 986 | ** name= or r=, then the name of the main branch |
| 987 | ** (usually "trunk") is used. |
| 988 | ** |
| 989 | ** in=PATTERN Only include files that match the comma-separate |
| 990 | ** list of GLOB patterns in PATTERN, as with ex= |
| 991 | ** |
| 992 | ** ex=PATTERN Omit any file that match PATTERN. PATTERN is a |
| @@ -1032,11 +1036,11 @@ | |
| 1036 | fossil_nice_default(); |
| 1037 | zName = fossil_strdup(PD("name","")); |
| 1038 | z = P("r"); |
| 1039 | if( z==0 ) z = P("uuid"); |
| 1040 | if( z==0 ) z = tar_uuid_from_name(&zName); |
| 1041 | if( z==0 ) z = fossil_strdup(db_main_branch()); |
| 1042 | nName = strlen(zName); |
| 1043 | g.zOpenRevision = zRid = fossil_strdup(z); |
| 1044 | nRid = strlen(zRid); |
| 1045 | zInclude = P("in"); |
| 1046 | if( zInclude ) pInclude = glob_create(zInclude); |
| 1047 |
+31
-7
| --- tools/email-sender.tcl | ||
| +++ tools/email-sender.tcl | ||
| @@ -3,11 +3,11 @@ | ||
| 3 | 3 | # Monitor the database file named by the DBFILE variable |
| 4 | 4 | # looking for email messages sent by Fossil. Forward each |
| 5 | 5 | # to /usr/sbin/sendmail. |
| 6 | 6 | # |
| 7 | 7 | set POLLING_INTERVAL 10000 ;# milliseconds |
| 8 | -set DBFILE /home/www/fossil/emailqueue.db | |
| 8 | +set DBFILE /home/www/data/emailqueue.db | |
| 9 | 9 | set PIPE "/usr/sbin/sendmail -ti" |
| 10 | 10 | |
| 11 | 11 | package require sqlite3 |
| 12 | 12 | # puts "SQLite version [sqlite3 -version]" |
| 13 | 13 | sqlite3 db $DBFILE |
| @@ -16,26 +16,50 @@ | ||
| 16 | 16 | db eval { |
| 17 | 17 | CREATE TABLE IF NOT EXISTS email( |
| 18 | 18 | emailid INTEGER PRIMARY KEY, |
| 19 | 19 | msg TXT |
| 20 | 20 | ); |
| 21 | + CREATE TABLE IF NOT EXISTS sentlog( | |
| 22 | + mtime INT, | |
| 23 | + xto TEXT, | |
| 24 | + xfrom TEXT, | |
| 25 | + xsubject TEXT, | |
| 26 | + xsize INT | |
| 27 | + ); | |
| 21 | 28 | } |
| 29 | +set ctr 0 | |
| 22 | 30 | while {1} { |
| 31 | + set n 0 | |
| 23 | 32 | db transaction immediate { |
| 24 | - set n 0 | |
| 25 | - db eval {SELECT msg FROM email} { | |
| 33 | + set emailid 0 | |
| 34 | + db eval {SELECT emailid, msg FROM email LIMIT 1} { | |
| 26 | 35 | set pipe $PIPE |
| 27 | - if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all addr]} { | |
| 28 | - append pipe " -f $addr" | |
| 36 | + set to unk | |
| 37 | + set subject none | |
| 38 | + set size [string length $msg] | |
| 39 | + regexp {To:[^\n]*<([^>]+)>} $msg all to | |
| 40 | + regexp {\nSubject:[ ]*([^\r\n]+)} $msg all subject | |
| 41 | + set subject [string trim $subject] | |
| 42 | + if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all from]} { | |
| 43 | + append pipe " -f $from" | |
| 29 | 44 | } |
| 30 | 45 | set out [open |$pipe w] |
| 31 | 46 | puts -nonewline $out $msg |
| 32 | 47 | flush $out |
| 33 | 48 | close $out |
| 34 | 49 | incr n |
| 50 | + incr ctr | |
| 35 | 51 | } |
| 36 | 52 | if {$n>0} { |
| 37 | - db eval {DELETE FROM email} | |
| 53 | + db eval {DELETE FROM email WHERE emailid=$emailid} | |
| 54 | + db eval {INSERT INTO sentlog(mtime,xto,xfrom,xsubject,xsize) | |
| 55 | + VALUES(unixepoch(),$to,$from,$subject,$size)} | |
| 38 | 56 | } |
| 39 | 57 | } |
| 40 | - after $POLLING_INTERVAL | |
| 58 | + if {$n==0} { | |
| 59 | + if {$ctr>100} { | |
| 60 | + db eval {DELETE FROM sentlog WHERE mtime<unixepoch('now','-30 days')} | |
| 61 | + set ctr 0 | |
| 62 | + } | |
| 63 | + after $POLLING_INTERVAL | |
| 64 | + } | |
| 41 | 65 | } |
| 42 | 66 |
| --- tools/email-sender.tcl | |
| +++ tools/email-sender.tcl | |
| @@ -3,11 +3,11 @@ | |
| 3 | # Monitor the database file named by the DBFILE variable |
| 4 | # looking for email messages sent by Fossil. Forward each |
| 5 | # to /usr/sbin/sendmail. |
| 6 | # |
| 7 | set POLLING_INTERVAL 10000 ;# milliseconds |
| 8 | set DBFILE /home/www/fossil/emailqueue.db |
| 9 | set PIPE "/usr/sbin/sendmail -ti" |
| 10 | |
| 11 | package require sqlite3 |
| 12 | # puts "SQLite version [sqlite3 -version]" |
| 13 | sqlite3 db $DBFILE |
| @@ -16,26 +16,50 @@ | |
| 16 | db eval { |
| 17 | CREATE TABLE IF NOT EXISTS email( |
| 18 | emailid INTEGER PRIMARY KEY, |
| 19 | msg TXT |
| 20 | ); |
| 21 | } |
| 22 | while {1} { |
| 23 | db transaction immediate { |
| 24 | set n 0 |
| 25 | db eval {SELECT msg FROM email} { |
| 26 | set pipe $PIPE |
| 27 | if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all addr]} { |
| 28 | append pipe " -f $addr" |
| 29 | } |
| 30 | set out [open |$pipe w] |
| 31 | puts -nonewline $out $msg |
| 32 | flush $out |
| 33 | close $out |
| 34 | incr n |
| 35 | } |
| 36 | if {$n>0} { |
| 37 | db eval {DELETE FROM email} |
| 38 | } |
| 39 | } |
| 40 | after $POLLING_INTERVAL |
| 41 | } |
| 42 |
| --- tools/email-sender.tcl | |
| +++ tools/email-sender.tcl | |
| @@ -3,11 +3,11 @@ | |
| 3 | # Monitor the database file named by the DBFILE variable |
| 4 | # looking for email messages sent by Fossil. Forward each |
| 5 | # to /usr/sbin/sendmail. |
| 6 | # |
| 7 | set POLLING_INTERVAL 10000 ;# milliseconds |
| 8 | set DBFILE /home/www/data/emailqueue.db |
| 9 | set PIPE "/usr/sbin/sendmail -ti" |
| 10 | |
| 11 | package require sqlite3 |
| 12 | # puts "SQLite version [sqlite3 -version]" |
| 13 | sqlite3 db $DBFILE |
| @@ -16,26 +16,50 @@ | |
| 16 | db eval { |
| 17 | CREATE TABLE IF NOT EXISTS email( |
| 18 | emailid INTEGER PRIMARY KEY, |
| 19 | msg TXT |
| 20 | ); |
| 21 | CREATE TABLE IF NOT EXISTS sentlog( |
| 22 | mtime INT, |
| 23 | xto TEXT, |
| 24 | xfrom TEXT, |
| 25 | xsubject TEXT, |
| 26 | xsize INT |
| 27 | ); |
| 28 | } |
| 29 | set ctr 0 |
| 30 | while {1} { |
| 31 | set n 0 |
| 32 | db transaction immediate { |
| 33 | set emailid 0 |
| 34 | db eval {SELECT emailid, msg FROM email LIMIT 1} { |
| 35 | set pipe $PIPE |
| 36 | set to unk |
| 37 | set subject none |
| 38 | set size [string length $msg] |
| 39 | regexp {To:[^\n]*<([^>]+)>} $msg all to |
| 40 | regexp {\nSubject:[ ]*([^\r\n]+)} $msg all subject |
| 41 | set subject [string trim $subject] |
| 42 | if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all from]} { |
| 43 | append pipe " -f $from" |
| 44 | } |
| 45 | set out [open |$pipe w] |
| 46 | puts -nonewline $out $msg |
| 47 | flush $out |
| 48 | close $out |
| 49 | incr n |
| 50 | incr ctr |
| 51 | } |
| 52 | if {$n>0} { |
| 53 | db eval {DELETE FROM email WHERE emailid=$emailid} |
| 54 | db eval {INSERT INTO sentlog(mtime,xto,xfrom,xsubject,xsize) |
| 55 | VALUES(unixepoch(),$to,$from,$subject,$size)} |
| 56 | } |
| 57 | } |
| 58 | if {$n==0} { |
| 59 | if {$ctr>100} { |
| 60 | db eval {DELETE FROM sentlog WHERE mtime<unixepoch('now','-30 days')} |
| 61 | set ctr 0 |
| 62 | } |
| 63 | after $POLLING_INTERVAL |
| 64 | } |
| 65 | } |
| 66 |
+2
-3
| --- www/alerts.md | ||
| +++ www/alerts.md | ||
| @@ -390,13 +390,12 @@ | ||
| 390 | 390 | |
| 391 | 391 | When you configure a Fossil server this way, it adds outgoing email |
| 392 | 392 | messages to an SQLite database file. A separate daemon process can then |
| 393 | 393 | extract those messages for further disposition. |
| 394 | 394 | |
| 395 | -Fossil includes a copy of [the daemon](/file/tools/email-sender.tcl) | |
| 396 | -used on `fossil-scm.org`: it is just a short Tcl script that | |
| 397 | -continuously monitors this database for new messages and hands any that | |
| 395 | +Fossil uses a short TCL script (seen at [](/file/tools/email-sender.tcl)) | |
| 396 | +that continuously monitors this database for new messages and hands any that | |
| 398 | 397 | it finds off to a local MTA using the same [pipe to MTA protocol](#pipe) |
| 399 | 398 | as above. |
| 400 | 399 | |
| 401 | 400 | In this way, outbound email alerts escape the chroot jail without |
| 402 | 401 | requiring that we insert a separate MTA configuration inside that jail. |
| 403 | 402 |
| --- www/alerts.md | |
| +++ www/alerts.md | |
| @@ -390,13 +390,12 @@ | |
| 390 | |
| 391 | When you configure a Fossil server this way, it adds outgoing email |
| 392 | messages to an SQLite database file. A separate daemon process can then |
| 393 | extract those messages for further disposition. |
| 394 | |
| 395 | Fossil includes a copy of [the daemon](/file/tools/email-sender.tcl) |
| 396 | used on `fossil-scm.org`: it is just a short Tcl script that |
| 397 | continuously monitors this database for new messages and hands any that |
| 398 | it finds off to a local MTA using the same [pipe to MTA protocol](#pipe) |
| 399 | as above. |
| 400 | |
| 401 | In this way, outbound email alerts escape the chroot jail without |
| 402 | requiring that we insert a separate MTA configuration inside that jail. |
| 403 |
| --- www/alerts.md | |
| +++ www/alerts.md | |
| @@ -390,13 +390,12 @@ | |
| 390 | |
| 391 | When you configure a Fossil server this way, it adds outgoing email |
| 392 | messages to an SQLite database file. A separate daemon process can then |
| 393 | extract those messages for further disposition. |
| 394 | |
| 395 | Fossil uses a short TCL script (seen at [](/file/tools/email-sender.tcl)) |
| 396 | that continuously monitors this database for new messages and hands any that |
| 397 | it finds off to a local MTA using the same [pipe to MTA protocol](#pipe) |
| 398 | as above. |
| 399 | |
| 400 | In this way, outbound email alerts escape the chroot jail without |
| 401 | requiring that we insert a separate MTA configuration inside that jail. |
| 402 |