| | @@ -19886,20 +19886,21 @@ |
| 19886 | 19886 | sqlite3_value **argv |
| 19887 | 19887 | ){ |
| 19888 | 19888 | int rc; |
| 19889 | 19889 | sqlite3_stmt *pStmt; |
| 19890 | 19890 | int n; |
| 19891 | | - sqlite3_int64 i64; |
| 19891 | + sqlite3_int64 ii; |
| 19892 | 19892 | sqlite3_int64 pgsz; |
| 19893 | 19893 | sqlite3_int64 nPage; |
| 19894 | 19894 | sqlite3_int64 nPageInUse; |
| 19895 | 19895 | sqlite3_int64 nFreeList; |
| 19896 | 19896 | sqlite3_int64 nIndex; |
| 19897 | 19897 | sqlite3_int64 nWORowid; |
| 19898 | 19898 | Analysis s; |
| 19899 | 19899 | sqlite3_uint64 r[2]; |
| 19900 | 19900 | |
| 19901 | + (void)argc; |
| 19901 | 19902 | memset(&s, 0, sizeof(s)); |
| 19902 | 19903 | s.db = sqlite3_context_db_handle(context); |
| 19903 | 19904 | s.context = context; |
| 19904 | 19905 | s.pOut = sqlite3_str_new(0); |
| 19905 | 19906 | if( sqlite3_str_errcode(s.pOut) ){ |
| | @@ -19912,14 +19913,14 @@ |
| 19912 | 19913 | }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){ |
| 19913 | 19914 | analysisReset(&s); |
| 19914 | 19915 | sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC); |
| 19915 | 19916 | return; |
| 19916 | 19917 | } |
| 19917 | | - i64 = 0; |
| 19918 | | - rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list" |
| 19918 | + ii = 0; |
| 19919 | + rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list" |
| 19919 | 19920 | " WHERE name=%Q COLLATE nocase",s.zSchema); |
| 19920 | | - if( rc || i64==0 ){ |
| 19921 | + if( rc || ii==0 ){ |
| 19921 | 19922 | analysisReset(&s); |
| 19922 | 19923 | sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC); |
| 19923 | 19924 | return; |
| 19924 | 19925 | } |
| 19925 | 19926 | sqlite3_randomness(sizeof(r), &r); |
| | @@ -20037,61 +20038,61 @@ |
| 20037 | 20038 | rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema); |
| 20038 | 20039 | if( rc ) return; |
| 20039 | 20040 | analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList); |
| 20040 | 20041 | analysisPercent(&s, (nFreeList*100.0)/(double)nPage); |
| 20041 | 20042 | |
| 20042 | | - i64 = 0; |
| 20043 | | - rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema); |
| 20043 | + ii = 0; |
| 20044 | + rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema); |
| 20044 | 20045 | if( rc ) return; |
| 20045 | | - if( i64==0 || nPage<=1 ){ |
| 20046 | | - i64 = 0; |
| 20046 | + if( ii==0 || nPage<=1 ){ |
| 20047 | + ii = 0; |
| 20047 | 20048 | }else{ |
| 20048 | 20049 | double rPtrsPerPage = pgsz/5; |
| 20049 | 20050 | double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0); |
| 20050 | | - i64 = (sqlite3_int64)ceil(rAvPage); |
| 20051 | + ii = (sqlite3_int64)ceil(rAvPage); |
| 20051 | 20052 | } |
| 20052 | | - analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64); |
| 20053 | | - analysisPercent(&s, (i64*100.0)/(double)nPage); |
| 20053 | + analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii); |
| 20054 | + analysisPercent(&s, (ii*100.0)/(double)nPage); |
| 20054 | 20055 | |
| 20055 | | - i64 = 0; |
| 20056 | | - rc = analysisSqlInt(&s, &i64, |
| 20056 | + ii = 0; |
| 20057 | + rc = analysisSqlInt(&s, &ii, |
| 20057 | 20058 | "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'", |
| 20058 | 20059 | s.zSchema); |
| 20059 | 20060 | if( rc ) return; |
| 20060 | | - analysisLine(&s, "Number of tables", "%lld\n", i64); |
| 20061 | + analysisLine(&s, "Number of tables", "%lld\n", ii); |
| 20061 | 20062 | nWORowid = 0; |
| 20062 | 20063 | rc = analysisSqlInt(&s, &nWORowid, |
| 20063 | 20064 | "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr", |
| 20064 | 20065 | s.zSchema); |
| 20065 | 20066 | if( rc ) return; |
| 20066 | 20067 | if( nWORowid>0 ){ |
| 20067 | 20068 | analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid); |
| 20068 | | - analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid); |
| 20069 | + analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid); |
| 20069 | 20070 | } |
| 20070 | 20071 | nIndex = 0; |
| 20071 | 20072 | rc = analysisSqlInt(&s, &nIndex, |
| 20072 | 20073 | "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'", |
| 20073 | 20074 | s.zSchema); |
| 20074 | 20075 | if( rc ) return; |
| 20075 | 20076 | analysisLine(&s, "Number of indexes", "%lld\n", nIndex); |
| 20076 | | - i64 = 0; |
| 20077 | | - rc = analysisSqlInt(&s, &i64, |
| 20077 | + ii = 0; |
| 20078 | + rc = analysisSqlInt(&s, &ii, |
| 20078 | 20079 | "SELECT count(*) FROM \"%w\".sqlite_schema" |
| 20079 | 20080 | " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'", |
| 20080 | 20081 | s.zSchema); |
| 20081 | 20082 | if( rc ) return; |
| 20082 | | - analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - i64); |
| 20083 | | - analysisLine(&s, "Number of implied indexes", "%lld\n", i64); |
| 20083 | + analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii); |
| 20084 | + analysisLine(&s, "Number of implied indexes", "%lld\n", ii); |
| 20084 | 20085 | analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage); |
| 20085 | | - i64 = 0; |
| 20086 | | - rc = analysisSqlInt(&s, &i64, |
| 20086 | + ii = 0; |
| 20087 | + rc = analysisSqlInt(&s, &ii, |
| 20087 | 20088 | "SELECT sum(payload) FROM temp.%s" |
| 20088 | 20089 | " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'", |
| 20089 | 20090 | s.zSU); |
| 20090 | 20091 | if( rc ) return; |
| 20091 | | - analysisLine(&s, "Bytes of payload", "%-11lld ", i64); |
| 20092 | | - analysisPercent(&s, i64*100.0/(double)(pgsz*nPage)); |
| 20092 | + analysisLine(&s, "Bytes of payload", "%-11lld ", ii); |
| 20093 | + analysisPercent(&s, ii*100.0/(double)(pgsz*nPage)); |
| 20093 | 20094 | |
| 20094 | 20095 | analysisTitle(&s, "Page counts for all tables with their indexes"); |
| 20095 | 20096 | pStmt = analysisPrepare(&s, |
| 20096 | 20097 | "SELECT upper(tblname),\n" |
| 20097 | 20098 | " sum(int_pages+leaf_pages+ovfl_pages)\n" |
| | @@ -24900,10 +24901,14 @@ |
| 24900 | 24901 | return rc; |
| 24901 | 24902 | } |
| 24902 | 24903 | static int cli_write(FILE *out, const char *zData, int nData){ |
| 24903 | 24904 | if( cli_output_capture && (out==stdout || out==stderr) ){ |
| 24904 | 24905 | sqlite3_str_append(cli_output_capture, zData, nData); |
| 24906 | +#ifdef _WIN32 |
| 24907 | + }else if( out==stdout || out==stderr ){ |
| 24908 | + nData = sqlite3_fprintf(out, "%.*s", nData, zData); |
| 24909 | +#endif |
| 24905 | 24910 | }else{ |
| 24906 | 24911 | nData = (int)fwrite(zData, 1, nData, out); |
| 24907 | 24912 | } |
| 24908 | 24913 | return nData; |
| 24909 | 24914 | } |
| | @@ -25099,50 +25104,80 @@ |
| 25099 | 25104 | } |
| 25100 | 25105 | return zLine; |
| 25101 | 25106 | } |
| 25102 | 25107 | |
| 25103 | 25108 | /* |
| 25104 | | -** The default prompts. |
| 25105 | | -*/ |
| 25106 | | -#ifndef SQLITE_PS1 |
| 25107 | | -# define SQLITE_PS1 "/A /f> " |
| 25108 | | -#endif |
| 25109 | | -#ifndef SQLITE_PS2 |
| 25110 | | -# define SQLITE_PS2 "/B.../H> " |
| 25111 | | -#endif |
| 25112 | | - |
| 25113 | | -/* |
| 25114 | | -** Redefinable name of a function that is used to find the text for |
| 25115 | | -** some prompt expansions: /A /V /v |
| 25116 | | -*/ |
| 25117 | | -#ifndef SQLITE_PS_APPDEF |
| 25118 | | -# define SQLITE_PS_APPDEF shellPromptAppDef |
| 25119 | | -#else |
| 25109 | +** The SQLITE_PS_APPDEF macro should be set to the name of a function |
| 25110 | +** that accepts a single "int" argument and returns a "const char *" |
| 25111 | +** that is guaranteed to be non-NULL. The value returned depends on the |
| 25112 | +** argument: |
| 25113 | +** |
| 25114 | +** 1 Default main prompt. |
| 25115 | +** 2 Default continuation prompt. |
| 25116 | +** 3 Environment variable to override main prompt ("SQLITE_PS1") |
| 25117 | +** 4 Environment variable to override continuatio ("SQLITE_PS2") |
| 25118 | +** 'A' The name of the application. (Nominally "SQLite") |
| 25119 | +** 'V' Version number including patch. (ex: "3.54.1") |
| 25120 | +** 'v' Version number without patch. (ex: "3.54") |
| 25121 | +** |
| 25122 | +*/ |
| 25123 | +#ifdef SQLITE_PS_APPDEF |
| 25120 | 25124 | extern const char *SQLITE_PS_APPDEF(int); |
| 25121 | | -#endif |
| 25122 | | - |
| 25123 | | -/* |
| 25124 | | -** Return a string appropriate for various prompt expansion characters. |
| 25125 | | -** Return an empty string at least. Always return a valid string pointer. |
| 25126 | | -*/ |
| 25125 | +#else |
| 25126 | +# define SQLITE_PS_APPDEF shellPromptAppDef |
| 25127 | 25127 | static const char *shellPromptAppDef(int c){ |
| 25128 | | - if( c=='A' ) return "SQLite"; |
| 25129 | | - if( c=='V' ) return sqlite3_libversion(); |
| 25130 | | - if( c=='v' ){ |
| 25131 | | - static char zRel[16]; |
| 25132 | | - const char *zF = sqlite3_libversion(); |
| 25133 | | - const char *zD = strrchr(zF,'.'); |
| 25134 | | - if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){ |
| 25135 | | - memcpy(zRel,zF,(size_t)(zD-zF)); |
| 25136 | | - zRel[(size_t)(zD-zF)] = 0; |
| 25137 | | - return zRel; |
| 25138 | | - }else{ |
| 25139 | | - return zF; |
| 25128 | + switch( c ){ |
| 25129 | + /* The default main prompt string */ |
| 25130 | + case 1: |
| 25131 | +#if defined(SQLITE_PS1) |
| 25132 | + return SQLITE_PS1; |
| 25133 | +#elif defined(SQLITE_PS_NOANSI) |
| 25134 | + return "/A-/v /~> "; |
| 25135 | +#else |
| 25136 | + return "/e[1;/x33/:36/;m/A-/v /~>/e[0m "; |
| 25137 | +#endif |
| 25138 | + |
| 25139 | + /* The default continuation prompt string */ |
| 25140 | + case 2: |
| 25141 | +#if defined(SQLITE_PS2) |
| 25142 | + return SQLITE_PS2; |
| 25143 | +#elif defined(SQLITE_PS_NOANSI) |
| 25144 | + return "/B/C> "; |
| 25145 | +#else |
| 25146 | + return "/B/e[1;/x33/:36/;m/C>/e[0m "; |
| 25147 | +#endif |
| 25148 | + |
| 25149 | + /* Name of environment variables that override the prompt strings |
| 25150 | + ** of cases 1 and 2 */ |
| 25151 | + case 3: return "SQLITE_PS1"; |
| 25152 | + case 4: return "SQLITE_PS2"; |
| 25153 | + |
| 25154 | + /* Name of the application */ |
| 25155 | + case 'A': return "SQLite"; |
| 25156 | + |
| 25157 | + /* Full version number of the application, including patch level */ |
| 25158 | + case 'V': return sqlite3_libversion(); |
| 25159 | + |
| 25160 | + /* Version number without the patch level */ |
| 25161 | + case 'v': { |
| 25162 | + static char zRel[16]; |
| 25163 | + const char *zF = sqlite3_libversion(); |
| 25164 | + const char *zD = strrchr(zF,'.'); |
| 25165 | + if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){ |
| 25166 | + memcpy(zRel,zF,(size_t)(zD-zF)); |
| 25167 | + zRel[(size_t)(zD-zF)] = 0; |
| 25168 | + return zRel; |
| 25169 | + }else{ |
| 25170 | + return zF; |
| 25171 | + } |
| 25140 | 25172 | } |
| 25141 | 25173 | } |
| 25142 | 25174 | return ""; |
| 25143 | 25175 | } |
| 25176 | +#endif /* !defined(SQLITE_PS_APPDEF) */ |
| 25177 | + |
| 25178 | + |
| 25144 | 25179 | |
| 25145 | 25180 | /* |
| 25146 | 25181 | ** Return the raw (unexpanded) prompt string. This will be the |
| 25147 | 25182 | ** first of the following that exist: |
| 25148 | 25183 | ** |
| | @@ -25158,18 +25193,14 @@ |
| 25158 | 25193 | assert( bContinue==0 || bContinue==1 ); |
| 25159 | 25194 | if( p->azPrompt[bContinue] ){ |
| 25160 | 25195 | return p->azPrompt[bContinue]; |
| 25161 | 25196 | } |
| 25162 | 25197 | #ifndef SQLITE_SHELL_FIDDLE |
| 25163 | | - zPS = getenv(bContinue ? "SQLITE_PS2" : "SQLITE_PS1"); |
| 25198 | + zPS = getenv(SQLITE_PS_APPDEF(3+bContinue)); |
| 25164 | 25199 | if( zPS ) return zPS; |
| 25165 | 25200 | #endif |
| 25166 | | - if( bContinue ){ |
| 25167 | | - return SQLITE_PS2; |
| 25168 | | - }else{ |
| 25169 | | - return SQLITE_PS1; |
| 25170 | | - } |
| 25201 | + return SQLITE_PS_APPDEF(1+bContinue); |
| 25171 | 25202 | } |
| 25172 | 25203 | |
| 25173 | 25204 | /* |
| 25174 | 25205 | ** Return the name of the open database file, to be used for prompt |
| 25175 | 25206 | ** expansion purposes. |
| | @@ -25188,10 +25219,49 @@ |
| 25188 | 25219 | zFN = "in-memory"; |
| 25189 | 25220 | } |
| 25190 | 25221 | } |
| 25191 | 25222 | return zFN; |
| 25192 | 25223 | } |
| 25224 | + |
| 25225 | +/* |
| 25226 | +** Return the name of the computer on which we are running. |
| 25227 | +*/ |
| 25228 | +static const char *prompt_hostname(int bFull){ |
| 25229 | +#ifdef _WIN32 |
| 25230 | + const char *z = getenv("COMPUTERNAME"); |
| 25231 | + if( z==0 || z[0]==0 ) z = "?"; |
| 25232 | + return z; |
| 25233 | +#else |
| 25234 | + static char zHost[256]; |
| 25235 | + if( gethostname(zHost, sizeof(zHost)) ){ |
| 25236 | + zHost[0] = '?'; |
| 25237 | + zHost[1] = 0; |
| 25238 | + } |
| 25239 | + if( !bFull ){ |
| 25240 | + char *p = strchr(zHost,'.'); |
| 25241 | + if( p ) p[0] = 0; |
| 25242 | + } |
| 25243 | + return zHost; |
| 25244 | +#endif |
| 25245 | +} |
| 25246 | + |
| 25247 | +/* |
| 25248 | +** Return the username. This is taken from an environment variable |
| 25249 | +** and can thus be forged. Do not depend on it. |
| 25250 | +*/ |
| 25251 | +static const char *prompt_user(void){ |
| 25252 | + const char *z; |
| 25253 | +#ifdef _WIN32 |
| 25254 | + z = getenv("USERNAME"); |
| 25255 | + if( z==0 || z[0]==0 ) z = "?"; |
| 25256 | +#else |
| 25257 | + z = getenv("USER"); |
| 25258 | + if( z==0 || z[0]==0 ) z = getenv("LOGNAME"); |
| 25259 | + if( z==0 || z[0]==0 ) z = "?"; |
| 25260 | +#endif |
| 25261 | + return z; |
| 25262 | +} |
| 25193 | 25263 | |
| 25194 | 25264 | /* |
| 25195 | 25265 | ** Expand escapes in the given input prompt string. Return the |
| 25196 | 25266 | ** expanded prompt in memory obtained from sqlite3_malloc(). The |
| 25197 | 25267 | ** caller is responsible for freeing the memory. |
| | @@ -25334,12 +25404,32 @@ |
| 25334 | 25404 | zPrompt += 2; |
| 25335 | 25405 | i = -1; |
| 25336 | 25406 | continue; |
| 25337 | 25407 | } |
| 25338 | 25408 | |
| 25339 | | - if( c=='H' ){ |
| 25340 | | - /* /H becomes text needed to terminate current input */ |
| 25409 | + if( c=='h' || c=='H' ){ |
| 25410 | + /* /h becomes hostname up to the first '.' */ |
| 25411 | + /* /H is the full hostname */ |
| 25412 | + if( !mOff ){ |
| 25413 | + sqlite3_str_appendall(pOut, prompt_hostname(c=='H')); |
| 25414 | + } |
| 25415 | + zPrompt += 2; |
| 25416 | + i = -1; |
| 25417 | + continue; |
| 25418 | + } |
| 25419 | + if( c=='u' ){ |
| 25420 | + /* /u becomes the username (taken from environment variables) */ |
| 25421 | + if( !mOff ){ |
| 25422 | + sqlite3_str_appendall(pOut, prompt_user()); |
| 25423 | + } |
| 25424 | + zPrompt += 2; |
| 25425 | + i = -1; |
| 25426 | + continue; |
| 25427 | + } |
| 25428 | + |
| 25429 | + if( c=='C' ){ |
| 25430 | + /* /C becomes text needed to terminate current input */ |
| 25341 | 25431 | if( !mOff ){ |
| 25342 | 25432 | sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0; |
| 25343 | 25433 | int cc = (R>>16)&0xff; |
| 25344 | 25434 | int nParen = R>>32; |
| 25345 | 25435 | int eSemi = (R>>8)&0xff; |
| | @@ -37972,11 +38062,11 @@ |
| 37972 | 38062 | vfstrace_register("trace",0,vfstraceOut, &data, 1); |
| 37973 | 38063 | } |
| 37974 | 38064 | #ifndef SQLITE_SHELL_FIDDLE |
| 37975 | 38065 | sqlite3_appendvfs_init(0,0,0); |
| 37976 | 38066 | #ifdef SQLITE_DEBUG |
| 37977 | | - sqlite3_auto_extension( (void (*)())auto_ext_leak_tester ); |
| 38067 | + sqlite3_auto_extension( (void(*)(void))auto_ext_leak_tester ); |
| 37978 | 38068 | #endif |
| 37979 | 38069 | #endif |
| 37980 | 38070 | modeDefault(&data); |
| 37981 | 38071 | |
| 37982 | 38072 | /* Go ahead and open the database file if it already exists. If the |
| 37983 | 38073 | |