From: larrybr Date: Thu, 18 May 2023 23:42:43 +0000 (+0000) Subject: CLI resmanage use to 100% by commands, 84% by LOC. WIP X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=529e842a18a90c6696ad8ccbfd687070649e7c2e;p=thirdparty%2Fsqlite.git CLI resmanage use to 100% by commands, 84% by LOC. WIP FossilOrigin-Name: 48f81d8fc650bf85028c729968f5de894f9c7e96b6ea1ec58cab31a39cb78417 --- diff --git a/manifest b/manifest index 1502b3acee..57797f450e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C More\sCLI\sresmanage\suse\s(75%\sLOC) -D 2023-05-17T15:22:17.870 +C CLI\sresmanage\suse\sto\s100%\sby\scommands,\s84%\sby\sLOC.\sWIP +D 2023-05-18T23:42:43.540 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -643,7 +643,7 @@ F src/resmanage.h e210da1810bb3e3ff000b4e6aa317cd5bc42a9e027ee5991144d9a998bee8b F src/resolve.c 3e53e02ce87c9582bd7e7d22f13f4094a271678d9dc72820fa257a2abb5e4032 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 738c3a3d6929f8be66c319bad17f6b297bd60a4eb14006075c48a28487dc7786 -F src/shell.c.in df0b2965b3fea71ff4a4bc03a099c3d145ee0f343b43d0ce7059f2bc4650b6b0 +F src/shell.c.in a3d2cd270c5b7525811d984840406f7739cd46329dc43ed1132552ae4616bd5f F src/shext_linkage.h 27dcf7624df05b2a7a6d367834339a6db3636f3035157f641f7db2ec499f8f6d F src/sqlite.h.in c14a4471fcd897a03631ac7ad3d05505e895e7b6419ec5b96cae9bc4df7a9fc6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -2081,8 +2081,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c010e1a7b2120d44c096b7d4216a8a51601972581f232d537b577617dfa6195a -R bb1e7d9087e2e9880da47ae6212d55b1 +P 3428ce82476e996c0bf06b623c93e6d5ba1a4542e1384350321405f8bd0d0e74 +R 4c4f46d47ea8ae2acb4edb9aaf04a323 U larrybr -Z 3b7afacf0d05d6b1d7df00452922197f +Z 3ba5774db546cb7251b89a558e4743f3 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 958564f6b5..ed1eda97c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3428ce82476e996c0bf06b623c93e6d5ba1a4542e1384350321405f8bd0d0e74 \ No newline at end of file +48f81d8fc650bf85028c729968f5de894f9c7e96b6ea1ec58cab31a39cb78417 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 3d5885073a..7ae7543d19 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -883,11 +883,8 @@ static void shell_check_ooms(const void *p){ } } #else -# define shell_check_ooms(p) shell_check_oom(p) -# define shell_check_oomm(p) shell_check_oom(p) -static void shell_check_oom(const void *p){ - if( p==0 ) shell_out_of_memory(); -} +# define shell_check_ooms(p) do{ if((p)==0) shell_out_of_memory(); }while 0 +# define shell_check_oomm(p) do{ if((p)==0) shell_out_of_memory(); }while 0 #endif /* Check a SQLite result code for out-of-memory indication. @@ -5261,15 +5258,18 @@ static int shell_exec( } /* -** Release memory previously allocated by tableColumnList(). +** Release memory previously allocated by tableColumnList() and others. +** The *azCol object is a zero-terminated sequence of char pointers, +** all but first of which is to be sqlite3_free()'ed, after which the +** azCol object is to be sqlite3_free()'ed. */ -static void freeColumnList(char **azCol){ +static void freeNameList(char **azCol){ int i; if( azCol!=0 ){ + /* azCol[0] is a static string, not to be freed. */ for(i=1; azCol[i]; i++){ sqlite3_free(azCol[i]); } - /* azCol[0] is a static string */ sqlite3_free(azCol); } } @@ -5278,7 +5278,7 @@ static void freeColumnList(char **azCol){ ** Return a list of pointers to strings which are the names of all ** columns in table zTab. The memory to hold the names is dynamically ** allocated and must be released by the caller using a subsequent call -** to freeColumnList(). +** to freeNameList(). ** ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid ** value that needs to be preserved, then azCol[0] is filled in with the @@ -5286,7 +5286,7 @@ static void freeColumnList(char **azCol){ ** ** The first regular column in the table is azCol[1]. The list is terminated ** by an entry with azCol[i]==0 for i>0. This is an invariant, maintained -** as the list is grown so that freeColumnList() can always deal with it. +** as the list is grown so that freeNameList() can always deal with it. ** ** This function can exit abruptly under OOM conditions. */ @@ -5299,7 +5299,7 @@ static char **tableColumnList(sqlite3 *db, const char *zTab, int preserveRowid){ int nPK = 0; /* Number of PRIMARY KEY columns seen */ int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */ ResourceMark mark = holder_mark(); - AnyResourceHolder arh = { 0, (GenericFreer)freeColumnList }; + AnyResourceHolder arh = { 0, (GenericFreer)freeNameList }; int rc; zSql = smprintf("PRAGMA table_info=%Q", zTab); @@ -5459,7 +5459,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){ } if( cli_strcmp(zType, "table")==0 ){ - AnyResourceHolder arh = { 0, (GenericFreer)freeColumnList }; + AnyResourceHolder arh = { 0, (GenericFreer)freeNameList }; ShellText sSelect; ShellText sTable; char **azCol; @@ -12772,7 +12772,7 @@ DISPATCHABLE_COMMAND( session 3 2 0 ){ FILE *cs_out = 0; if( failIfSafeMode (p, "cannot run \".session %s\" in safe mode", azCmd[0]) ){ - rc = DCR_AbortError; + return DCR_AbortError; }else{ if( nCmd!=2 ) goto session_syntax_error; if( pSession->p==0 ) goto session_not_open; @@ -12789,12 +12789,13 @@ DISPATCHABLE_COMMAND( session 3 2 0 ){ rc = sqlite3session_patchset(pSession->p, &szChng, &pChng); } if( rc ){ - fprintf(out, "Error: error code %d\n", rc); + fprintf(out, "Error: error code %d (swallowed)\n", rc); rc = 0; } if( pChng && fwrite(pChng, szChng, 1, cs_out)!=1 ){ raw_printf(STD_ERR, "ERROR: Failed to write entire %d-byte output\n", szChng); + rc = 1; } sqlite3_free(pChng); fclose(cs_out); @@ -12898,7 +12899,7 @@ DISPATCHABLE_COMMAND( session 3 2 0 ){ for(i=0; inSession; i++){ if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){ utf8_printf(STD_ERR, "Session \"%s\" already exists\n", zName); - return rc; + return DCR_Error; } } if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){ @@ -12925,7 +12926,7 @@ DISPATCHABLE_COMMAND( session 3 2 0 ){ showHelp(out, "session", p); return DCR_CmdErred; } - return DCR_Ok; + return DCR_Ok|(rc!=0); } DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){ @@ -12940,6 +12941,8 @@ DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){ char *zSep; /* Separator */ ShellText sSql; /* Complete SQL for the query to run the hash */ ShellText sQuery; /* Set of queries used to read all content */ + RESOURCE_MARK(mark); + open_db(p, 0); for(i=1; iout, "%s\n", zSql); }else{ shell_exec(p, zSql, 0); } + release_holder(); /* 0 */ #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE) { int lrc; @@ -13045,8 +13051,8 @@ DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){ "WHERE type='table' AND coalesce(rootpage,0)>1\n" "AND name NOT LIKE 'sqlite_%%'%s\n" "ORDER BY 1 collate nocase"; - zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : ""); - zRevText = sqlite3_mprintf( + zRevText = smprintf(zRevText, zLike? " AND name LIKE $tspec" : ""); + zRevText = smprintf( /* lower-case query is first run, producing upper-case query. */ "with tabcols as materialized(\n" "select tname, cname\n" @@ -13062,22 +13068,25 @@ DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){ "' OR ') as query, tname from tabcols group by tname)" , zRevText); shell_check_ooms(zRevText); + sstr_holder(zRevText); /* +1 */ if( bDebug ) utf8_printf(ISS(p)->out, "%s\n", zRevText); - lrc = sqlite3_prepare_v2(DBX(p), zRevText, -1, &pStmt, 0); + lrc = shell_check_nomem(sqlite3_prepare_v2(DBX(p), zRevText,-1,&pStmt,0)); if( lrc!=SQLITE_OK ){ - sqlite3_free(zRevText); + release_holders_mark(mark); return DCR_Error; } + stmt_holder(pStmt); /* +2 */ if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC); - lrc = SQLITE_ROW==sqlite3_step(pStmt); + lrc = SQLITE_ROW==shell_check_nomem(sqlite3_step(pStmt)); if( lrc ){ const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0); sqlite3_stmt *pCheckStmt; lrc = sqlite3_prepare_v2(DBX(p), zGenQuery, -1, &pCheckStmt, 0); + shell_check_nomem(lrc); if( bDebug ) utf8_printf(ISS(p)->out, "%s\n", zGenQuery); + stmt_holder(pCheckStmt); /* +3 */ if( SQLITE_OK!=lrc ){ - sqlite3_finalize(pStmt); - sqlite3_free(zRevText); + release_holders_mark(mark); return DCR_Error; }else{ if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){ @@ -13089,14 +13098,11 @@ DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){ sz, (sz>1)? "s": ""); } } - sqlite3_finalize(pCheckStmt); } - sqlite3_finalize(pStmt); } - sqlite3_free(zRevText); } #endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */ - sqlite3_free(zSql); + release_holders_mark(mark); return DCR_Ok; } @@ -13143,7 +13149,8 @@ DISPATCHABLE_COMMAND( selftest 4 0 0 ){ int i, k; /* Loop counters */ int nTest = 0; /* Number of tests runs */ int nErr = 0; /* Number of errors seen */ - ShellText str; /* Answer for a query */ + RESOURCE_MARK(mark); + ShellText str = {0}; /* Answer for a query */ sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ for(i=1; i=0; k--){ if( k==1 ){ rc = sqlite3_prepare_v2(DBX(p), @@ -13188,10 +13197,10 @@ DISPATCHABLE_COMMAND( selftest 4 0 0 ){ } if( rc ){ *pzErr = smprintf("Error querying the selftest table\n"); - sqlite3_finalize(pStmt); + release_holders_mark(mark); return DCR_Error; } - for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ + for(i=1; shell_check_nomem(sqlite3_step(pStmt))==SQLITE_ROW; i++){ int tno = sqlite3_column_int(pStmt, 0); const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); @@ -13207,6 +13216,7 @@ DISPATCHABLE_COMMAND( selftest 4 0 0 ){ utf8_printf(psi->out, "%s\n", zSql); }else if( cli_strcmp(zOp,"run")==0 ){ char *zErrMsg = 0; + sstr_ptr_holder(&zErrMsg); str.n = 0; str.z[0] = 0; rc = sqlite3_exec(DBX(p), zSql, captureOutputCallback, &str, &zErrMsg); @@ -13217,14 +13227,15 @@ DISPATCHABLE_COMMAND( selftest 4 0 0 ){ if( rc || zErrMsg ){ nErr++; rc = 1; - utf8_printf(psi->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); - sqlite3_free(zErrMsg); + utf8_printf(psi->out, "%d: error-code-%d: %s\n", tno, rc, + (zErrMsg)? zErrMsg : ""); }else if( cli_strcmp(zAns,str.z)!=0 ){ nErr++; rc = 1; utf8_printf(psi->out, "%d: Expected: [%s]\n", tno, zAns); utf8_printf(psi->out, "%d: Got: [%s]\n", tno, str.z); } + release_holder(); }else{ *pzErr = smprintf ("Unknown operation \"%s\" on selftest line %d\n", zOp, tno); @@ -13232,9 +13243,8 @@ DISPATCHABLE_COMMAND( selftest 4 0 0 ){ break; } } /* End loop over rows of content from SELFTEST */ - sqlite3_finalize(pStmt); } /* End loop over k */ - freeText(&str); + release_holders_mark(mark); utf8_printf(psi->out, "%d errors out of %d tests\n", nErr, nTest); return rc > 0; } @@ -13257,7 +13267,7 @@ COLLECT_HELP_TEXT[ #if SHELLOUT_ENABLE static DotCmdRC shellOut(char *azArg[], int nArg, ShellExState *psx, char **pzErr){ - char *zCmd; + char *zCmd = 0; int i, x; if( ISS(psx)->bSafeMode ) return DCR_AbortError; zCmd = smprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); @@ -13266,8 +13276,9 @@ static DotCmdRC shellOut(char *azArg[], int nArg, zCmd, azArg[i]); } shell_check_ooms(zCmd); + sstr_holder(zCmd); x = system(zCmd); - sqlite3_free(zCmd); + release_holder(); if( x ) raw_printf(STD_ERR, "%s command returns %d\n", azArg[0], x); return DCR_Ok; } @@ -13366,7 +13377,7 @@ DISPATCHABLE_COMMAND( shxopts 3 0 0 ){ } return DCR_Ok; moan_error: - raw_printf(STD_ERR, "Error: %s %s\n", zAbout, zMoan); + *pzErr = smprintf("Error: %s %s\n", zAbout, zMoan); return DCR_CmdErred; } @@ -13463,16 +13474,22 @@ COLLECT_HELP_TEXT[ static int showTableLike(char *azArg[], int nArg, ShellExState *p, char **pzErr, char ot){ int rc; - sqlite3_stmt *pStmt; + sqlite3_stmt *pStmt = 0; + ShellText s = {0}; + AnyResourceHolder arh = { 0, (GenericFreer)freeNameList }; char **azResult; int nRow, nAlloc; int ii; - ShellText s; + RESOURCE_MARK(mark); + initText(&s); + text_ref_holder(&s); open_db(p, 0); rc = sqlite3_prepare_v2(DBX(p), "PRAGMA database_list", -1, &pStmt, 0); - if( rc ){ - sqlite3_finalize(pStmt); + stmt_ptr_holder(&pStmt); + if( shell_check_nomem(rc) ){ + db_err_bail: + release_holders_mark(mark); return shellDatabaseError(DBX(p)); } @@ -13481,7 +13498,7 @@ static int showTableLike(char *azArg[], int nArg, ShellExState *p, ** when called with the wrong number of arguments whereas the .tables ** command does not. */ *pzErr = smprintf("Usage: .indexes ?LIKE-PATTERN?\n"); - sqlite3_finalize(pStmt); + release_holders_mark(mark); return DCR_SayUsage; } for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ @@ -13526,15 +13543,16 @@ static int showTableLike(char *azArg[], int nArg, ShellExState *p, appendText(&s, zSystem, 0); } rc = sqlite3_finalize(pStmt); + pStmt = 0; if( rc==SQLITE_OK ){ appendText(&s, " ORDER BY 1", 0); - rc = sqlite3_prepare_v2(DBX(p), s.z, -1, &pStmt, 0); + rc = shell_check_nomem(sqlite3_prepare_v2(DBX(p), s.z, -1, &pStmt, 0)); } - freeText(&s); - if( rc ) return shellDatabaseError(DBX(p)); + if( rc ) goto db_err_bail; /* Run the SQL statement prepared by the above block. Store the results - ** as an array of nul-terminated strings in azResult[]. */ + ** as an array of nul-terminated strings in azResult[]. The 0th element + ** of azResult[] is not used so that freeNameList() can free it. */ nRow = nAlloc = 0; azResult = 0; if( nArg>1 ){ @@ -13542,47 +13560,49 @@ static int showTableLike(char *azArg[], int nArg, ShellExState *p, }else{ sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); } - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - if( nRow>=nAlloc ){ + while( shell_check_nomem(sqlite3_step(pStmt))==SQLITE_ROW ){ + if( nRow+2 > nAlloc ){ char **azNew; int n2 = nAlloc*2 + 10; azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); shell_check_ooms(azNew); + /* Keep the object usable by freeNameList at all times. */ + memset(azNew+nAlloc, 0, (n2-nAlloc)*sizeof(azResult[0])); nAlloc = n2; + arh.pAny = azNew; azResult = azNew; } + ++nRow; azResult[nRow] = smprintf("%s", sqlite3_column_text(pStmt, 0)); shell_check_ooms(azResult[nRow]); - nRow++; } if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ - rc = shellDatabaseError(DBX(p)); + pStmt = 0; + goto db_err_bail; } - + pStmt = 0; /* Pretty-print the contents of array azResult[] to the output */ if( rc==0 && nRow>0 ){ int len, maxlen = 0; int i, j; int nPrintCol, nPrintRow; - for(i=0; imaxlen ) maxlen = len; } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; - for(i=0; iout, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:""); } raw_printf(ISS(p)->out, "\n"); } } - - for(ii=0; iibSafeMode ){ - utf8_printf(STD_ERR, - "line %d: \".testctrl %s\" may not be used in safe mode\n", - ISS(p)->pInSource->lineno, aCtrl[iCtrl].zCtrlName); - exit(1); + }else if( aCtrl[iCtrl].unSafe + && failIfSafeMode(p,"line %d: \".testctrl %s\" " + "may not be used in safe mode\n", + ISS(p)->pInSource->lineno, + aCtrl[iCtrl].zCtrlName) ){ + return DCR_Abort; }else{ switch(testctrl){ @@ -14136,14 +14157,17 @@ DISPATCHABLE_COMMAND( vars 2 1 0 ){ if( (nArg>2 || zCmd[0]=='c') ){ sqlite3_str *sbZap = sqlite3_str_new(dbs); char *zSql; + sqst_ptr_holder(&sbZap); sqlite3_str_appendf (sbZap, "DELETE FROM "SHVAR_TABLE_SNAME" WHERE key "); append_in_clause(sbZap, (const char **)&azArg[2], (const char **)&azArg[nArg]); zSql = sqlite3_str_finish(sbZap); + drop_holder(); shell_check_ooms(zSql); + sstr_holder(zSql); rc = sqlite3_exec(dbs, zSql, 0, 0, 0); - sqlite3_free(zSql); + release_holder(); } #ifndef SQLITE_NOHAVE_SYSTEM }else if( SUBCMD("edit") ){ @@ -14297,10 +14321,12 @@ DISPATCHABLE_COMMAND( vfsname ? 0 0 ){ */ static void setColumnWidths(ShellExState *p, char *azWidths[], int nWidths){ int j; + int *pSW = p->pSpecWidths; p->numWidths = nWidths; - p->pSpecWidths = realloc(p->pSpecWidths, (nWidths+1)*sizeof(int)*2); + pSW = realloc(pSW, (nWidths+1)*sizeof(int)*2);; + shell_check_oomm(pSW); + p->pSpecWidths = pSW; if( nWidths>0 ){ - shell_check_oomm(p->pSpecWidths); p->pHaveWidths = &p->pSpecWidths[nWidths]; for(j=0; jpSpecWidths[j] = (int)integerValue(azWidths[j]); @@ -14410,35 +14436,31 @@ DISPATCHABLE_COMMAND( eval 3 1 0 ){ DISPATCHABLE_COMMAND( read 3 2 2 ){ DotCmdRC rc = DCR_Ok; ShellInState *psi = ISS(p); - FILE *inUse = 0; - int (*fCloser)(FILE *) = 0; + InSource inSourceRedir + = INSOURCE_FILE_REDIR(0, azArg[1], psi->pInSource); + if( psi->bSafeMode ) return DCR_AbortError; if( azArg[1][0]=='|' ){ #ifdef SQLITE_OMIT_POPEN *pzErr = smprintf("pipes are not supported in this OS\n"); rc = DCR_Error; - /* p->out = STD_OUT; This was likely not needed. To be investigated. */ #else - inUse = popen(azArg[1]+1, "r"); - if( inUse==0 ){ + if( (inSourceRedir.inFile = popen(azArg[1]+1, "r"))==0 ){ *pzErr = smprintf("cannot open \"%s\"\n", azArg[1]); rc = DCR_Error; }else{ - fCloser = pclose; + inSourceRedir.closer.stream = pclose; } #endif - }else if( (inUse = openChrSource(azArg[1]))==0 ){ + }else if( (inSourceRedir.inFile = openChrSource(azArg[1]))==0 ){ *pzErr = smprintf("cannot open \"%s\"\n", azArg[1]); rc = DCR_Error; }else{ - fCloser = fclose; + inSourceRedir.closer.stream = fclose; } - if( inUse!=0 ){ - InSource inSourceRedir - = INSOURCE_FILE_REDIR(inUse, azArg[1], psi->pInSource); + if( inSourceRedir.inFile!=0 ){ AnyResourceHolder arh = { &(psi->pInSource),(GenericFreer)finish_InSource }; psi->pInSource = &inSourceRedir; - inSourceRedir.closer.stream = fCloser; any_ref_holder(&arh); rc = process_input(psi); /* If error(s) occured during process, leave complaining to them. */