From: drh <> Date: Wed, 5 Nov 2025 15:44:11 +0000 (+0000) Subject: New style setting QRF_STYLE_Auto which chooses box, explain, or EQP depending X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a354a157176f09f4203a4fe21914a6be869744e1;p=thirdparty%2Fsqlite.git New style setting QRF_STYLE_Auto which chooses box, explain, or EQP depending on the statement to be rendered. Improvements to memory management. Updates to the documentation. FossilOrigin-Name: 468ba188f034b23398e1f07b915cf7c8b337dcf7f56a13511947c5322ae98722 --- diff --git a/ext/qrf/README.md b/ext/qrf/README.md index 123e549934..0379b5f3b8 100644 --- a/ext/qrf/README.md +++ b/ext/qrf/README.md @@ -15,14 +15,22 @@ prepared statement, use code similar to the following: > ~~~ sqlite3_qrf_spec spec; /* Format specification */ char *zErrMsg; /* Text error message (optional) */ +char *zResult = 0; /* Formatted output written here */ int rc; /* Result code */ memset(&spec, 0, sizeof(spec)); -// Fill out the spec object to describe the desired output format +spec.iVersion = 1; +spec.pzOutput = &zResult; +// Optionally fill other settings in spec, as needed zErrMsg = 0; rc = sqlite3_format_query_result(pStmt, &spec, &zErrMsg); -if( rc ) printf("Error (%d): %s\n", rc, zErrMsg); -sqlite3_free(zErrMsg); +if( rc ){ + printf("Error (%d): %s\n", rc, zErrMsg); + sqlite3_free(zErrMsg); +}else{ + printf("%s", zResult); + sqlite3_free(zResult); +} ~~~ The `sqlite3_qrf_spec` object describes the desired output format @@ -62,7 +70,12 @@ struct sqlite3_qrf_spec { ~~~ The sqlite3_qrf_spec object must be fully initialized prior -to calling `sqlite3_format_query_result()`. +to calling `sqlite3_format_query_result()`. Initialization can be mostly +accomplished using memset() to zero the spec object, as most fields +use a zero value as a reasonable default. However, the iVersion +field must be set to 1 and one of either the pzOutput or xWrite fields +must be initialized to a non-NULL value to tell QRF where to send +its output. ### 2.1 Structure Version Number @@ -75,12 +88,15 @@ than 1. Thus the iVersion field is used to support upgradability. The formatted output can either be sent to a callback function or accumulated into an output buffer in memory obtained -from system malloc(). If the sqlite3_qrf_spec.xWrite column is not NULL, +from sqlite3_malloc(). If the sqlite3_qrf_spec.xWrite column is not NULL, then that function is invoked (using sqlite3_qrf_spec.xWriteArg as its first argument) to transmit the formatted output. Or, if sqlite3_qrf_spec.pzOutput points to a pointer to a character, then that pointer is made to point to memory obtained from sqlite3_malloc() that -contains the complete text of the formatted output. +contains the complete text of the formatted output. If spec.pzOutput\[0\] +is initially non-NULL, then it is assumed to point to memory obtained +from sqlite3_malloc(). In that case, the buffer is resized using +sqlite3_realloc() and the new text is appended. One of sqlite3_qrf_spec.xWrite and sqlite3_qrf_spec.pzOutput must be non-NULL and the other must be NULL. @@ -106,25 +122,29 @@ formatted when displaying TEXT values in the result. These are the allowed values: > ~~~ -#define QRF_ESC_Ascii 0 /* Unix-style escapes. Ex: U+0007 shows ^G */ -#define QRF_ESC_Symbol 1 /* Unicode escapes. Ex: U+0007 shows U+2407 */ -#define QRF_ESC_Off 2 /* Do not escape control characters */ +#define QRF_ESC_Auto 0 /* Choose the ctrl-char escape automatically */ +#define QRF_ESC_Off 1 /* Do not escape control characters */ +#define QRF_ESC_Ascii 2 /* Unix-style escapes. Ex: U+0007 shows ^G */ +#define QRF_ESC_Symbol 3 /* Unicode escapes. Ex: U+0007 shows U+2407 */ ~~~ -If the value of eEsc is zero, then the control character +If the value of eEsc is QRF_ESC_Ascii, then the control character with value X is displayed as ^Y where Y is X+0x40. Hence, a -backspace character (U+0008) is shown as "^H". This is the -default. +backspace character (U+0008) is shown as "^H". -If eEsc is one, then control characters in the range of U+0001 +If eEsc is QRF_ESC_Symbol, then control characters in the range of U+0001 through U+001f are mapped into U+2401 through U+241f, respectively. -If the value of eEsc is two, then no translation occurs +If the value of eEsc is QRF_ESC_Off, then no translation occurs and control characters that appear in TEXT string are transmitted to the formatted output as-is. This an be dangerous in applications, since an adversary who can control TEXT values might be able to inject ANSI cursor movement sequences to hide nefarious values. +The QRF_ESC_Auto value for eEsc means that the query result formatter +gets to pick whichever control-character encoding it things is best for +the situation. This will usually be QRF_ESC_Ascii. + The TAB (U+0009), LF (U+000a) and CR-LF (U+000d,U+000a) character sequence are always output literally and are not mapped to alternative display values, regardless of this setting. @@ -134,14 +154,18 @@ display values, regardless of this setting. The sqlite3_qrf_spec.eText field can have one of the following values: > ~~~ -#define QRF_TEXT_Off 0 /* Literal text */ -#define QRF_TEXT_Sql 1 /* Quote as an SQL literal */ -#define QRF_TEXT_Csv 2 /* CSV-style quoting */ -#define QRF_TEXT_Html 3 /* HTML-style quoting */ -#define QRF_TEXT_Tcl 4 /* C/Tcl quoting */ -#define QRF_TEXT_Json 5 /* JSON quoting */ +#define QRF_TEXT_Auto 0 /* Choose text encoding automatically */ +#define QRF_TEXT_Off 1 /* Literal text */ +#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */ +#define QRF_TEXT_Csv 3 /* CSV-style quoting */ +#define QRF_TEXT_Html 4 /* HTML-style quoting */ +#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ +#define QRF_TEXT_Json 6 /* JSON quoting */ ~~~ +A value of QRF_TEXT_Auto means that the query result formatter will choose +what it things will be the best text encoding. + A value of QRF_TEXT_Off means that text value appear in the output exactly as they are found in the database file, with no translation. @@ -331,22 +355,23 @@ might increase in future versions. The following output modes are currently defined: > ~~~ -#define QRF_STYLE_List 0 /* One record per line with a separator */ -#define QRF_STYLE_Line 1 /* One column per line. */ -#define QRF_STYLE_Html 2 /* Generate an XHTML table */ -#define QRF_STYLE_Json 3 /* Output is a list of JSON objects */ -#define QRF_STYLE_Insert 4 /* Generate SQL "insert" statements */ -#define QRF_STYLE_Csv 5 /* Comma-separated-value */ -#define QRF_STYLE_Quote 6 /* SQL-quoted, comma-separated */ -#define QRF_STYLE_Explain 7 /* EXPLAIN output */ -#define QRF_STYLE_ScanExp 8 /* EXPLAIN output with vm stats */ -#define QRF_STYLE_EQP 9 /* Format EXPLAIN QUERY PLAN output */ -#define QRF_STYLE_Markdown 10 /* Markdown formatting */ -#define QRF_STYLE_Column 11 /* One record per line in neat columns */ -#define QRF_STYLE_Table 12 /* MySQL-style table formatting */ -#define QRF_STYLE_Box 13 /* Unicode box-drawing characters */ -#define QRF_STYLE_Count 14 /* Output only a count of the rows of output */ -#define QRF_STYLE_Off 15 /* No query output shown */ +#define QRF_STYLE_Auto 0 /* Choose a style automatically */ +#define QRF_STYLE_List 1 /* One record per line with a separator */ +#define QRF_STYLE_Line 2 /* One column per line. */ +#define QRF_STYLE_Html 3 /* Generate an XHTML table */ +#define QRF_STYLE_Json 4 /* Output is a list of JSON objects */ +#define QRF_STYLE_Insert 5 /* Generate SQL "insert" statements */ +#define QRF_STYLE_Csv 6 /* Comma-separated-value */ +#define QRF_STYLE_Quote 7 /* SQL-quoted, comma-separated */ +#define QRF_STYLE_Explain 8 /* EXPLAIN output */ +#define QRF_STYLE_ScanExp 9 /* EXPLAIN output with vm stats */ +#define QRF_STYLE_EQP 10 /* Format EXPLAIN QUERY PLAN output */ +#define QRF_STYLE_Markdown 11 /* Markdown formatting */ +#define QRF_STYLE_Column 12 /* One record per line in neat columns */ +#define QRF_STYLE_Table 13 /* MySQL-style table formatting */ +#define QRF_STYLE_Box 14 /* Unicode box-drawing characters */ +#define QRF_STYLE_Count 15 /* Output only a count of the rows of output */ +#define QRF_STYLE_Off 16 /* No query output shown */ ~~~ ### 5.0 Source Code Files diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index 2e4916db76..0facd658b5 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -1480,7 +1480,16 @@ static void qrfInitialize( sz = sizeof(sqlite3_qrf_spec); memcpy(&p->spec, pSpec, sz); if( p->spec.zNull==0 ) p->spec.zNull = ""; +qrf_reinit: switch( p->spec.eStyle ){ + case QRF_STYLE_Auto: { + switch( sqlite3_stmt_isexplain(pStmt) ){ + case 0: p->spec.eStyle = QRF_STYLE_Box; break; + case 1: p->spec.eStyle = QRF_STYLE_Explain; break; + default: p->spec.eStyle = QRF_STYLE_EQP; break; + } + goto qrf_reinit; + } case QRF_STYLE_List: { if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|"; if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; @@ -1561,20 +1570,19 @@ static void qrfInitialize( break; } } + if( p->spec.eEsc==QRF_ESC_Auto ){ + p->spec.eEsc = QRF_ESC_Ascii; + } + if( p->spec.eText==QRF_TEXT_Auto ){ + p->spec.eText = QRF_TEXT_Off; + } if( p->spec.eBlob==QRF_BLOB_Auto ){ switch( p->spec.eText ){ case QRF_TEXT_Sql: p->spec.eBlob = QRF_BLOB_Sql; break; case QRF_TEXT_Csv: p->spec.eBlob = QRF_BLOB_Tcl; break; case QRF_TEXT_Tcl: p->spec.eBlob = QRF_BLOB_Tcl; break; case QRF_TEXT_Json: p->spec.eBlob = QRF_BLOB_Json; break; - default: p->spec.eBlob = QRF_BLOB_Text; break; - } - } - switch( p->spec.eStyle ){ - case QRF_STYLE_List: { - if( p->spec.zColumnSep==0 ) p->spec.zColumnSep = "|"; - if( p->spec.zRowSep==0 ) p->spec.zRowSep = "\n"; - break; + default: p->spec.eBlob = QRF_BLOB_Text; break; } } } @@ -1722,7 +1730,24 @@ static void qrfFinalize(Qrf *p){ } } if( p->spec.pzOutput ){ - *p->spec.pzOutput = sqlite3_str_finish(p->pOut); + if( p->spec.pzOutput[0] ){ + sqlite3_int64 n, sz; + char *zCombined; + sz = strlen(p->spec.pzOutput[0]); + n = sqlite3_str_length(p->pOut); + zCombined = sqlite3_realloc(p->spec.pzOutput[0], sz+n+1); + if( zCombined==0 ){ + sqlite3_free(p->spec.pzOutput[0]); + p->spec.pzOutput[0] = 0; + qrfOom(p); + }else{ + p->spec.pzOutput[0] = zCombined; + memcpy(zCombined+sz, sqlite3_str_value(p->pOut), n+1); + } + sqlite3_free(sqlite3_str_finish(p->pOut)); + }else{ + p->spec.pzOutput[0] = sqlite3_str_finish(p->pOut); + } }else if( p->pOut ){ sqlite3_free(sqlite3_str_finish(p->pOut)); } diff --git a/ext/qrf/qrf.h b/ext/qrf/qrf.h index 208863f0d7..8a81cb6500 100644 --- a/ext/qrf/qrf.h +++ b/ext/qrf/qrf.h @@ -64,33 +64,35 @@ int sqlite3_format_query_result( /* ** Output styles: */ -#define QRF_STYLE_List 0 /* One record per line with a separator */ -#define QRF_STYLE_Line 1 /* One column per line. */ -#define QRF_STYLE_Html 2 /* Generate an XHTML table */ -#define QRF_STYLE_Json 3 /* Output is a list of JSON objects */ -#define QRF_STYLE_Insert 4 /* Generate SQL "insert" statements */ -#define QRF_STYLE_Csv 5 /* Comma-separated-value */ -#define QRF_STYLE_Quote 6 /* SQL-quoted, comma-separated */ -#define QRF_STYLE_Explain 7 /* EXPLAIN output */ -#define QRF_STYLE_ScanExp 8 /* EXPLAIN output with vm stats */ -#define QRF_STYLE_EQP 9 /* Format EXPLAIN QUERY PLAN output */ -#define QRF_STYLE_Markdown 10 /* Markdown formatting */ -#define QRF_STYLE_Column 11 /* One record per line in neat columns */ -#define QRF_STYLE_Table 12 /* MySQL-style table formatting */ -#define QRF_STYLE_Box 13 /* Unicode box-drawing characters */ -#define QRF_STYLE_Count 14 /* Output only a count of the rows of output */ -#define QRF_STYLE_Off 15 /* No query output shown */ +#define QRF_STYLE_Auto 0 /* Choose a style automatically */ +#define QRF_STYLE_List 1 /* One record per line with a separator */ +#define QRF_STYLE_Line 2 /* One column per line. */ +#define QRF_STYLE_Html 3 /* Generate an XHTML table */ +#define QRF_STYLE_Json 4 /* Output is a list of JSON objects */ +#define QRF_STYLE_Insert 5 /* Generate SQL "insert" statements */ +#define QRF_STYLE_Csv 6 /* Comma-separated-value */ +#define QRF_STYLE_Quote 7 /* SQL-quoted, comma-separated */ +#define QRF_STYLE_Explain 8 /* EXPLAIN output */ +#define QRF_STYLE_ScanExp 9 /* EXPLAIN output with vm stats */ +#define QRF_STYLE_EQP 10 /* Format EXPLAIN QUERY PLAN output */ +#define QRF_STYLE_Markdown 11 /* Markdown formatting */ +#define QRF_STYLE_Column 12 /* One record per line in neat columns */ +#define QRF_STYLE_Table 13 /* MySQL-style table formatting */ +#define QRF_STYLE_Box 14 /* Unicode box-drawing characters */ +#define QRF_STYLE_Count 15 /* Output only a count of the rows of output */ +#define QRF_STYLE_Off 16 /* No query output shown */ /* ** Quoting styles for text. ** Allowed values for sqlite3_qrf_spec.eText */ -#define QRF_TEXT_Off 0 /* Literal text */ -#define QRF_TEXT_Sql 1 /* Quote as an SQL literal */ -#define QRF_TEXT_Csv 2 /* CSV-style quoting */ -#define QRF_TEXT_Html 3 /* HTML-style quoting */ -#define QRF_TEXT_Tcl 4 /* C/Tcl quoting */ -#define QRF_TEXT_Json 5 /* JSON quoting */ +#define QRF_TEXT_Auto 0 /* Choose text encoding automatically */ +#define QRF_TEXT_Off 1 /* Literal text */ +#define QRF_TEXT_Sql 2 /* Quote as an SQL literal */ +#define QRF_TEXT_Csv 3 /* CSV-style quoting */ +#define QRF_TEXT_Html 4 /* HTML-style quoting */ +#define QRF_TEXT_Tcl 5 /* C/Tcl quoting */ +#define QRF_TEXT_Json 6 /* JSON quoting */ /* ** Quoting styles for BLOBs @@ -107,8 +109,9 @@ int sqlite3_format_query_result( ** Control-character escape modes. ** Allowed values for sqlite3_qrf_spec.eEscape */ -#define QRF_ESC_Off 0 /* Do not escape control characters */ -#define QRF_ESC_Ascii 1 /* Unix-style escapes. Ex: U+0007 shows ^G */ -#define QRF_ESC_Symbol 2 /* Unicode escapes. Ex: U+0007 shows U+2407 */ +#define QRF_ESC_Auto 0 /* Choose the ctrl-char escape automatically */ +#define QRF_ESC_Off 1 /* Do not escape control characters */ +#define QRF_ESC_Ascii 2 /* Unix-style escapes. Ex: U+0007 shows ^G */ +#define QRF_ESC_Symbol 3 /* Unicode escapes. Ex: U+0007 shows U+2407 */ #endif /* !defined(SQLITE_QRF_H) */ diff --git a/manifest b/manifest index 0fb2d18ad8..65737981cd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\snew\s"format"\smethod\sin\sthe\sTCL\sinterface\sis\snow\spartially\sfunctional. -D 2025-11-05T14:07:16.182 +C New\sstyle\ssetting\sQRF_STYLE_Auto\swhich\schooses\sbox,\sexplain,\sor\sEQP\sdepending\non\sthe\sstatement\sto\sbe\srendered.\s\sImprovements\sto\smemory\smanagement.\nUpdates\sto\sthe\sdocumentation. +D 2025-11-05T15:44:11.056 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -416,10 +416,10 @@ F ext/misc/wholenumber.c 0fa0c082676b7868bf2fa918e911133f2b349bcdceabd1198bba5f6 F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c F ext/misc/zipfile.c 09e6e3a3ff40a99677de3c0bc6569bd5f4709b1844ac3d1c1452a456c5a62f1c F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee -F ext/qrf/README.md 1aa6f58a9442d329eff1d890dd33f565df636a47d8d0e878dbbf5c0ecba3b4c3 +F ext/qrf/README.md 6bfe3047478b8901694cab91ccc98b35a8e14678f38475dc726be485190d4433 F ext/qrf/qrf-tester.c 3a733b25a25ba7390cd3df055edd76ac72f488a9c5d9eb523a7508b0b8ac8900 -F ext/qrf/qrf.c 02b67fdd18903ff31ee6df545cc6816d55405c53deaec8c193afb7d9435a49db -F ext/qrf/qrf.h 701ddceb12e6b7957eeb4d77d057fddb66328840c189514b35daf27d1edb3a0e +F ext/qrf/qrf.c 75cbdde120e336b10190d7d1a90aa4855e25eb2e733bbdd44321b489167a816b +F ext/qrf/qrf.h 4542c723805550b48ca81ed53e3beea95e793ecc7d2b01d34a780fbea366323f F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363 @@ -744,7 +744,7 @@ F src/sqliteInt.h 88f7fc9ce1630d9a5f7e0a8e1f3287cdc63882fba985c18e7eee1b9f457f59 F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 -F src/tclsqlite.c dbf58baacccc93ad413f6afbd10436c99c737ad9613fd04d4d6d3fcab1895166 +F src/tclsqlite.c bb00869df54bdbb8f214d37e915eaa3033df4db7c758eed58e6f706a97714fd9 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a F src/test1.c f880ab766eeedf2c063662bd9538b923fd42c4341b7bfc2150a6d93ab8b9341c F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff @@ -2172,8 +2172,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e08d21fe1365176f268f1dcca4048fb5ff043356e5817c8622b4ed9a1a5a58cf -R 396eb99826668e7bea68d6dbddbadb5d +P ace1ebda08740bb248c009cc4a6c99da318a2bba3e43ef20bd0c365c5021705f +R c324dd72d4cef65f02505ddc83f97922 U drh -Z 00c395c0339b4e9e4eacf1741e0dac01 +Z 32bacd6d63b86433ef5068a18f2ed528 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index de69168d96..ba92ccfbbd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ace1ebda08740bb248c009cc4a6c99da318a2bba3e43ef20bd0c365c5021705f +468ba188f034b23398e1f07b915cf7c8b337dcf7f56a13511947c5322ae98722 diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 844fbe533e..73d7931c18 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -2059,13 +2059,11 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){ char *zResult = 0; /* Result to be returned */ const char *zSql = 0; /* SQL to run */ int i; /* Loop counter */ - sqlite3_str *pPrior = 0; /* Prior results */ int rc; /* Result code */ sqlite3_qrf_spec qrf; /* Formatting spec */ memset(&qrf, 0, sizeof(qrf)); qrf.iVersion = 1; - qrf.eStyle = QRF_STYLE_Box; qrf.pzOutput = &zResult; for(i=2; iinterp, objv[i+1], azStyles, @@ -2097,20 +2097,12 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){ } } while( zSql && zSql[0] ){ - const char *zNext; /* Next statement after current */ SqlPreparedStmt *pStmt = 0; /* Next statement to run */ char *zErr = 0; /* Error message from QRF */ - rc = dbPrepareAndBind(pDb, zSql, &zNext, &pStmt); + rc = dbPrepareAndBind(pDb, zSql, &zSql, &pStmt); if( rc ) goto format_failed; - if( zResult ){ - if( pPrior==0 ){ - pPrior = sqlite3_str_new(pDb->db); - if( pPrior==0 ) goto format_oom; - } - sqlite3_str_appendall(pPrior, zResult); - zResult = 0; - } + if( pStmt==0 ) continue; rc = sqlite3_format_query_result(pStmt->pStmt, &qrf, &zErr); dbReleaseStmt(pDb, pStmt, 0); if( rc ){ @@ -2119,25 +2111,13 @@ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){ rc = TCL_ERROR; goto format_failed; } - zSql = zNext; - } - - if( pPrior ){ - sqlite3_str_appendall(pPrior, zResult); - sqlite3_free(zResult); - zResult = sqlite3_str_finish(pPrior); - pPrior = 0; } Tcl_SetResult(pDb->interp, zResult, TCL_VOLATILE); sqlite3_free(zResult); return TCL_OK; -format_oom: - Tcl_AppendResult(pDb->interp, "out of memory", (char*)0); - format_failed: - if( zResult ) sqlite3_free(zResult); - if( pPrior ) sqlite3_free(sqlite3_str_finish(pPrior)); + sqlite3_free(zResult); return rc; #endif