unsigned char eEsc; /* How to escape control characters in text */
unsigned char eText; /* Quoting style for text */
unsigned char eBlob; /* Quoting style for BLOBs */
- unsigned char bColumnNames; /* True to show column names */
+ unsigned char bColumnNames; /* QRF_SW_On to show column names */
unsigned char bWordWrap; /* Try to wrap on word boundaries */
unsigned char bTextJsonb; /* Render JSONB blobs as JSON text */
short int mxWidth; /* Maximum width of any column */
### 2.4 Show Column Names (bColumnNames)
-The sqlite3_qrf_spec.bColumnNames field is a boolean. If true, then column
-names appear in the output. If false, column names are omitted.
+The sqlite3_qrf_spec.bColumnNames field can be either QRF_SW_Auto,
+QRF_SW_On, or QRF_SW_Off.
+
+> ~~~
+#define QRF_SW_Auto 0 /* Let QRF choose the best value */
+#define QRF_SW_Off 1 /* This setting is forced off */
+#define QRF_SW_On 2 /* This setting is forced on */
+~~~
+
+If the value is QRF_SW_On, then column names appear in the output.
+If the value is QRF_SW_Off, column names are omitted. If the
+value is QRF_SW_Auto, then an appropriate default is chosen.
### 2.5 Control Character Escapes (eEsc)
### 2.7 How to display BLOB values (eBlob and bTextJsonb)
-If the sqlite3_qrf_spec.bTextJsonb flag is true and if the value to be
+If the sqlite3_qrf_spec.bTextJsonb flag is QRF_SW_On and if the value to be
displayed is JSONB, then the JSONB is translated into text JSON and the
text is shown according to the sqlite3_qrf_spec.eText setting as
described in the previous section.
-If the bTextJsonb flag is false (the usual case) or if the BLOB value to
+If the bTextJsonb flag is QRF_SW_Off (the usual case) or if the BLOB value to
be displayed is not JSONB, then the sqlite3_qrf_spec.eBlob field determines
how the BLOB value is formatted. The following options are available;
width of the text on a fixed-pitch font. The code takes into account
zero-width and double-width characters when comput the display width.
-If the sqlite3_qrf_spec.bWordWrap flag is set, then the formatter
-attempts to split lines at whitespace or word boundaries.
-If the bWorkWrap flag is zero, then long lines can be split in the middle
-of words.
+If the sqlite3_qrf_spec.bWordWrap flag is set to QRF_SW_On,
+then the formatter attempts to split lines at whitespace or word boundaries.
+If the bWorkWrap flag is set QRF_SW_Off, then long lines can be split in
+the middle of words.
### 2.9 Column width and alignment (nWidth and aWidth)
+++ /dev/null
-/*
-** 2025-10-20
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** A simple command-line program for testing the Result-Format or "resfmt"
-** utility library for SQLite.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include "sqlite3.h"
-#include "qrf.h"
-
-#define COUNT(X) (sizeof(X)/sizeof(X[0]))
-
-/* Report out-of-memory and die if the argument is NULL */
-static void checkOOM(void *p){
- if( p==0 ){
- fprintf(stdout, "out-of-memory\n");
- exit(1);
- }
-}
-
-/* A block of memory */
-typedef struct memblock memblock;
-struct memblock {
- memblock *pNext;
-};
-
-/* List of all memory to be freed */
-static memblock *pToFree = 0;
-
-/* Free all memory at exit */
-static void tempFreeAll(void){
- while( pToFree ){
- memblock *pNext = pToFree->pNext;
- sqlite3_free(pToFree);
- pToFree = pNext;
- }
-}
-
-/* Allocate memory that will be freed all at once by freeall() */
-static void *tempMalloc(size_t n){
- memblock *p;
- if( n>0x10000000 ) checkOOM(0);
- p = sqlite3_malloc64( n+sizeof(memblock) );
- checkOOM(p);
- p->pNext = pToFree;
- pToFree = p;
- return (void*)&pToFree[1];
-}
-
-/* Make a copy of a string using tempMalloc() */
-static char *tempStrdup(char *zIn){
- size_t n;
- char *z;
- if( zIn==0 ) zIn = "";
- n = strlen(zIn);
- if( n>0x10000000 ) checkOOM(0);
- z = tempMalloc( n+1 );
- checkOOM(z);
- memcpy(z, zIn, n+1);
- return z;
-}
-
-/* Function used for writing to the console */
-static sqlite3_int64 testWriter(
- void *pContext,
- const unsigned char *p,
- sqlite3_int64 n
-){
- return fwrite(p,1,n,stdout);
-}
-
-/* Render BLOB values as "(%d-byte-blob)". */
-static char *testBlobRender(void *pNotUsed, sqlite3_value *pVal){
- if( sqlite3_value_type(pVal)!=SQLITE_BLOB ) return 0;
- return sqlite3_mprintf("(%d-byte-blob)",sqlite3_value_bytes(pVal));
-}
-
-int main(int argc, char **argv){
- char *zSrc;
- FILE *pSrc;
- sqlite3_str *pBuf;
- sqlite3 *db = 0;
- sqlite3_stmt *pStmt;
- int rc;
- int lineNum = 0;
- int bUseWriter = 1;
- short int aWidth[100];
- sqlite3_qrf_spec spec;
- char zLine[1000];
-
- if( argc<2 ){
- zSrc = "<stdin>";
- pSrc = stdin;
- }else{
- zSrc = argv[1];
- pSrc = fopen(zSrc, "rb");
- if( pSrc==0 ){
- fprintf(stderr, "cannot open \"%s\" for reading\n", zSrc);
- exit(1);
- }
- }
- memset(&spec, 0, sizeof(spec));
- spec.iVersion = 1;
- spec.eStyle = QRF_STYLE_List;
- spec.xWrite = testWriter;
- pBuf = sqlite3_str_new(0);
- rc = sqlite3_open(":memory:", &db);
- if( rc ){
- fprintf(stderr, "unable to open an in-memory database: %s\n",
- sqlite3_errmsg(db));
- exit(1);
- }
- while( fgets(zLine, sizeof(zLine), pSrc) ){
- size_t n = strlen(zLine);
- lineNum++;
- while( n>0 && zLine[n-1]>0 && zLine[n-1]<=' ' ) n--;
- zLine[n] = 0;
- printf("%s\n", zLine);
- if( strncmp(zLine, "--open=", 7)==0 ){
- if( db ) sqlite3_close(db);
- db = 0;
- rc = sqlite3_open(&zLine[7], &db);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "%s:%d: cannot open \"%s\": %s\n",
- zSrc, lineNum, &zLine[7],
- sqlite3_errmsg(db));
- exit(1);
- }
- }else
- if( strcmp(zLine, "--go")==0 ){
- const char *zSql, *zTail;
- char *zErr = 0;
- int n;
- if( db==0 ){
- fprintf(stderr, "%s:%d: database not open\n", zSrc, lineNum);
- exit(1);
- }
- zSql = sqlite3_str_value(pBuf);
- pStmt = 0;
- while( zSql[0] ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zTail);
- if( rc || pStmt==0 ){
- fprintf(stderr, "%s:%d: sqlite3_prepare() fails: %s\n",
- zSrc, lineNum, sqlite3_errmsg(db));
- sqlite3_finalize(pStmt);
- break;
- }
- zSql = sqlite3_sql(pStmt);
- while( isspace(zSql[0]) ) zSql++;
- n = (int)strlen(zSql);
- while( n>0 && isspace(zSql[n-1]) ) n--;
- if( n>0 ){
- char *zOut = 0;
- printf("/* %.*s */\n", n, zSql);
- if( bUseWriter ){
- spec.pzOutput = 0;
- spec.xWrite = testWriter;
- }else{
- spec.pzOutput = &zOut;
- spec.xWrite = 0;
- }
- rc = sqlite3_format_query_result(pStmt, &spec, &zErr);
- if( rc!=SQLITE_OK ){
- fprintf(stderr, "%s:%d: Error %d: %s\n", zSrc, lineNum,
- rc, zErr);
- }else{
- if( !bUseWriter && zOut ){
- fputs(zOut, stdout);
- sqlite3_free(zOut);
- }
- }
- sqlite3_free(zErr);
- }
- sqlite3_finalize(pStmt);
- pStmt = 0;
- zSql = zTail;
- }
- sqlite3_str_reset(pBuf);
- }else
- if( strncmp(zLine, "--eStyle=", 9)==0 ){
- const struct { const char *z; int e; } aStyle[] = {
- { "box", QRF_STYLE_Box, },
- { "csv", QRF_STYLE_Csv, },
- { "column", QRF_STYLE_Column, },
- { "count", QRF_STYLE_Count, },
- { "eqp", QRF_STYLE_EQP, },
- { "explain", QRF_STYLE_Explain, },
- { "html", QRF_STYLE_Html, },
- { "insert", QRF_STYLE_Insert, },
- { "json", QRF_STYLE_Json, },
- { "line", QRF_STYLE_Line, },
- { "list", QRF_STYLE_List, },
- { "markdown", QRF_STYLE_Markdown, },
- { "off", QRF_STYLE_Off, },
- { "quote", QRF_STYLE_Quote, },
- { "table", QRF_STYLE_Table, },
- { "scanexp", QRF_STYLE_ScanExp, },
- };
- int i;
- for(i=0; i<COUNT(aStyle); i++){
- if( strcmp(aStyle[i].z,&zLine[9])==0 ){
- spec.eStyle = aStyle[i].e;
- break;
- }
- }
- if( i>=COUNT(aStyle) ){
- sqlite3_str *pMsg = sqlite3_str_new(0);
- for(i=0; i<COUNT(aStyle); i++){
- sqlite3_str_appendf(pMsg, " %s", aStyle[i].z);
- }
- fprintf(stderr, "%s:%d: no such style: \"%s\"\nChoices: %s\n",
- zSrc, lineNum, &zLine[9], sqlite3_str_value(pMsg));
- sqlite3_free(sqlite3_str_finish(pMsg));
- }
- }else
- if( strncmp(zLine, "--eText=", 8)==0 ){
- const struct { const char *z; int e; } aQuote[] = {
- { "csv", QRF_TEXT_Csv },
- { "html", QRF_TEXT_Html },
- { "json", QRF_TEXT_Json },
- { "off", QRF_TEXT_Off },
- { "sql", QRF_TEXT_Sql },
- { "tcl", QRF_TEXT_Tcl },
- };
- int i;
- for(i=0; i<COUNT(aQuote); i++){
- if( strcmp(aQuote[i].z,&zLine[8])==0 ){
- spec.eText = aQuote[i].e;
- break;
- }
- }
- if( i>=COUNT(aQuote) ){
- sqlite3_str *pMsg = sqlite3_str_new(0);
- for(i=0; i<COUNT(aQuote); i++){
- sqlite3_str_appendf(pMsg, " %s", aQuote[i].z);
- }
- fprintf(stderr, "%s:%d: no such text-style: \"%s\"\nChoices: %s\n",
- zSrc, lineNum, &zLine[8], sqlite3_str_value(pMsg));
- sqlite3_free(sqlite3_str_finish(pMsg));
- }
- }else
- if( strncmp(zLine, "--eBlob=", 8)==0 ){
- const struct { const char *z; int e; } aBlob[] = {
- { "auto", QRF_BLOB_Auto },
- { "hex", QRF_BLOB_Hex },
- { "json", QRF_BLOB_Json },
- { "tcl", QRF_BLOB_Tcl },
- { "text", QRF_BLOB_Text },
- { "sql", QRF_BLOB_Sql },
- };
- int i;
- for(i=0; i<COUNT(aBlob); i++){
- if( strcmp(aBlob[i].z,&zLine[8])==0 ){
- spec.eBlob = aBlob[i].e;
- break;
- }
- }
- if( i>=COUNT(aBlob) ){
- sqlite3_str *pMsg = sqlite3_str_new(0);
- for(i=0; i<COUNT(aBlob); i++){
- sqlite3_str_appendf(pMsg, " %s", aBlob[i].z);
- }
- fprintf(stderr, "%s:%d: no such blob-style: \"%s\"\nChoices: %s\n",
- zSrc, lineNum, &zLine[8], sqlite3_str_value(pMsg));
- sqlite3_free(sqlite3_str_finish(pMsg));
- }
- }else
- if( strncmp(zLine, "--eEsc=", 7)==0 ){
- const struct { const char *z; int e; } aEscape[] = {
- { "ascii", QRF_ESC_Ascii },
- { "off", QRF_ESC_Off },
- { "symbol", QRF_ESC_Symbol },
- };
- int i;
- for(i=0; i<COUNT(aEscape); i++){
- if( strcmp(aEscape[i].z,&zLine[7])==0 ){
- spec.eEsc = aEscape[i].e;
- break;
- }
- }
- if( i>=COUNT(aEscape) ){
- sqlite3_str *pMsg = sqlite3_str_new(0);
- for(i=0; i<COUNT(aEscape); i++){
- sqlite3_str_appendf(pMsg, " %s", aEscape[i].z);
- }
- fprintf(stderr, "%s:%d: no such escape mode: \"%s\"\nChoices: %s\n",
- zSrc, lineNum, &zLine[10], sqlite3_str_value(pMsg));
- sqlite3_free(sqlite3_str_finish(pMsg));
- }
- }else
- if( strncmp(zLine, "--bColumnNames=", 15)==0 ){
- spec.bColumnNames = atoi(&zLine[15])!=0;
- }else
- if( strncmp(zLine, "--bTextJsonb=", 13)==0 ){
- spec.bTextJsonb = atoi(&zLine[13])!=0;
- }else
- if( strncmp(zLine, "--zNull=", 8)==0 ){
- spec.zNull = tempStrdup(&zLine[8]);
- }else
- if( strncmp(zLine, "--zColumnSep=", 13)==0 ){
- spec.zColumnSep = tempStrdup(&zLine[13]);
- }else
- if( strncmp(zLine, "--zRowSep=", 10)==0 ){
- spec.zRowSep = tempStrdup(&zLine[10]);
- }else
- if( strncmp(zLine, "--mxWidth=", 10)==0 ){
- spec.mxWidth = (short int)atoi(&zLine[10]);
- }else
- if( strncmp(zLine, "--aWidth=", 9)==0 ){
- const char *zArg = &zLine[9];
- int n = 0;
- while( isspace(zArg[0]) ) zArg++;
- while( zArg[0]!=0 && n<COUNT(aWidth) ){
- int w = atoi(zArg);
- if( w>QRF_MX_WIDTH ){
- w = QRF_MX_WIDTH;
- }else if( w<QRF_MN_WIDTH ){
- w = QRF_MN_WIDTH;
- }else if( w==0 && zArg[0]=='-' ){
- w = QRF_MINUS_ZERO;
- }
- aWidth[n++] = w;
- while( zArg[0] && !isspace(zArg[0]) ) zArg++;
- while( isspace(zArg[0]) ) zArg++;
- }
- spec.aWidth = aWidth;
- spec.nWidth = n;
- }else
- if( strcmp(zLine, "--exit")==0 ){
- break;
- }else
- if( strncmp(zLine, "--use-writer=",13)==0 ){
- bUseWriter = atoi(&zLine[13])!=0;
- }else
- if( strncmp(zLine, "--use-render=",13)==0 ){
- spec.xRender = (atoi(&zLine[13])!=0) ? testBlobRender : 0;
- }else
- if( strncmp(zLine, "--",2)==0 && !isspace(zLine[2]) ){
- fprintf(stderr, "%s:%d: Unrecognized command: \"%s\"\n",
- zSrc, lineNum, zLine);
- }else
- {
- if( sqlite3_str_length(pBuf) ) sqlite3_str_append(pBuf, "\n", 1);
- sqlite3_str_appendall(pBuf, zLine);
- }
- }
- if( db ) sqlite3_close(db);
- sqlite3_free(sqlite3_str_finish(pBuf));
- tempFreeAll();
- if( pSrc!=stdin ) fclose(pSrc);
- return 0;
-}
break;
}
case SQLITE_BLOB: {
- if( p->spec.bTextJsonb ){
+ if( p->spec.bTextJsonb==QRF_SW_On ){
const char *zJson = qrfJsonbToJson(p, iCol);
if( zJson ){
qrfEncodeText(p, pOut, zJson);
const unsigned char **azNextLine = 0;
int bNextLine = 0;
int bMultiLineRowExists = 0;
- int bw = p->spec.bWordWrap;
+ int bw = p->spec.bWordWrap==QRF_SW_On;
int nColumn = p->nCol;
rc = sqlite3_step(p->pStmt);
case QRF_STYLE_Column: {
colSep = " ";
rowSep = "\n";
- if( p->spec.bColumnNames ){
+ if( p->spec.bColumnNames==QRF_SW_On ){
for(i=0; i<nColumn; i++){
w = p->actualWidth[i];
if( i<p->spec.nWidth && p->spec.aWidth[i]<0 ) w = -w;
** not an EQP statement.
*/
p->spec.eStyle = QRF_STYLE_Quote;
- p->spec.bColumnNames = 1;
+ p->spec.bColumnNames = QRF_SW_On;
p->spec.eText = QRF_TEXT_Sql;
p->spec.eBlob = QRF_BLOB_Sql;
p->spec.zColumnSep = ",";
** statement is not an EXPLAIN statement.
*/
p->spec.eStyle = QRF_STYLE_Quote;
- p->spec.bColumnNames = 1;
+ p->spec.bColumnNames = QRF_SW_On;
p->spec.eText = QRF_TEXT_Sql;
p->spec.eBlob = QRF_BLOB_Sql;
p->spec.zColumnSep = ",";
default: p->spec.eBlob = QRF_BLOB_Text; break;
}
}
+ if( p->spec.bColumnNames==QRF_SW_Auto ){
+ switch( p->spec.eStyle ){
+ case QRF_STYLE_Box:
+ case QRF_STYLE_Csv:
+ case QRF_STYLE_Column:
+ case QRF_STYLE_Table:
+ case QRF_STYLE_Markdown:
+ p->spec.bColumnNames = QRF_SW_On;
+ break;
+ default:
+ p->spec.bColumnNames = QRF_SW_Off;
+ break;
+ }
+ }
+ if( p->spec.bWordWrap==QRF_SW_Auto ){
+ p->spec.bWordWrap = QRF_SW_On;
+ }
+ if( p->spec.bTextJsonb==QRF_SW_Auto ){
+ p->spec.bTextJsonb = QRF_SW_Off;
+ }
+}
+
+/*
+** Attempt to determine if identifier zName needs to be quoted, either
+** because it contains non-alphanumeric characters, or because it is an
+** SQLite keyword. Be conservative in this estimate: When in doubt assume
+** that quoting is required.
+**
+** Return 1 if quoting is required. Return 0 if no quoting is required.
+*/
+
+static int qrf_need_quote(const char *zName){
+ int i;
+ const unsigned char *z = (const unsigned char*)zName;
+ if( z==0 ) return 1;
+ if( !isalpha(z[0]) && z[0]!='_' ) return 1;
+ for(i=0; z[i]; i++){
+ if( !isalnum(z[i]) && z[i]!='_' ) return 1;
+ }
+ return sqlite3_keyword_check(zName, i)!=0;
}
/*
break;
}
case QRF_STYLE_Html: {
- if( p->nRow==0 && p->spec.bColumnNames ){
+ if( p->nRow==0 && p->spec.bColumnNames==QRF_SW_On ){
sqlite3_str_append(p->pOut, "<TR>", 4);
for(i=0; i<p->nCol; i++){
const char *zCName = sqlite3_column_name(p->pStmt, i);
break;
}
case QRF_STYLE_Insert: {
- sqlite3_str_appendf(p->pOut,"INSERT INTO %s VALUES(",p->spec.zTableName);
+ if( qrf_need_quote(p->spec.zTableName) ){
+ sqlite3_str_appendf(p->pOut,"INSERT INTO \"%w\"",p->spec.zTableName);
+ }else{
+ sqlite3_str_appendf(p->pOut,"INSERT INTO %s",p->spec.zTableName);
+ }
+ if( p->spec.bColumnNames==QRF_SW_On ){
+ for(i=0; i<p->nCol; i++){
+ const char *zCName = sqlite3_column_name(p->pStmt, i);
+ if( qrf_need_quote(zCName) ){
+ sqlite3_str_appendf(p->pOut, "%c\"%w\"",
+ i==0 ? '(' : ',', zCName);
+ }else{
+ sqlite3_str_appendf(p->pOut, "%c%s",
+ i==0 ? '(' : ',', zCName);
+ }
+ }
+ sqlite3_str_append(p->pOut, ")", 1);
+ }
+ sqlite3_str_append(p->pOut," VALUES(", 8);
for(i=0; i<p->nCol; i++){
if( i>0 ) sqlite3_str_append(p->pOut, ",", 1);
qrfRenderValue(p, p->pOut, i);
break;
}
default: { /* QRF_STYLE_List */
- if( p->nRow==0 && p->spec.bColumnNames ){
+ if( p->nRow==0 && p->spec.bColumnNames==QRF_SW_On ){
for(i=0; i<p->nCol; i++){
const char *zCName = sqlite3_column_name(p->pStmt, i);
if( i>0 ) sqlite3_str_appendall(p->pOut, p->spec.zColumnSep);
#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 */
+/*
+** Allowed values for "boolean" fields, such as "bColumnNames", "bWordWrap",
+** and "bTextJsonb". There is an extra "auto" variants so these are actually
+** tri-state settings, not booleans.
+*/
+#define QRF_SW_Auto 0 /* Let QRF choose the best value */
+#define QRF_SW_Off 1 /* This setting is forced off */
+#define QRF_SW_On 2 /* This setting is forced on */
+
#endif /* !defined(SQLITE_QRF_H) */
-C A\sfew\ssimple\stest\scases\sadded.
-D 2025-11-05T16:29:06.224
+C The\sTCL\sinterface\sfor\sQRF\sis\snow\sfeature\scomplete\s(at\sleast\suntil\sI\sthink\nof\snew\sfeatures\sto\sadd).\s\sThere\sis\sstill\sa\slot\sof\stesting,\sbug-fixing,\nand\sdocumentation\sto\sbe\sdone,\showever.
+D 2025-11-05T18:27:18.151
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6292e60c
F ext/misc/zipfile.c 09e6e3a3ff40a99677de3c0bc6569bd5f4709b1844ac3d1c1452a456c5a62f1c
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
-F ext/qrf/README.md 6bfe3047478b8901694cab91ccc98b35a8e14678f38475dc726be485190d4433
-F ext/qrf/qrf-tester.c 3a733b25a25ba7390cd3df055edd76ac72f488a9c5d9eb523a7508b0b8ac8900
-F ext/qrf/qrf.c e45c181d031f71da73c7d605f56ff62640985a9bbb154f0221c5324bbc1b1167
-F ext/qrf/qrf.h 4542c723805550b48ca81ed53e3beea95e793ecc7d2b01d34a780fbea366323f
+F ext/qrf/README.md 5f12f91104d5df8ba8783e2240635698569ce54935e721b3a4e93abf4e00ddcb
+F ext/qrf/qrf.c 8dd8f3245f86686ddacdf92354655dd290e5ed7668f6cf7d6bcf1f9453160062
+F ext/qrf/qrf.h 98e02eded10848c42053d37e56bd15ab69cb6fe9fc1f1ca05823d9047e9c8509
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363
F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c bb00869df54bdbb8f214d37e915eaa3033df4db7c758eed58e6f706a97714fd9
+F src/tclsqlite.c 45476ca0b3088504c7e296ce52b4ab0b6b9af57132abeca2867fbcf1a50f84af
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c f880ab766eeedf2c063662bd9538b923fd42c4341b7bfc2150a6d93ab8b9341c
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd
-F test/qrf01.test 6b912e5ceb34fb288d47ade071249b8dcd6df40735ee3a7733af99e77e504c25
+F test/qrf01.test 84699d3a41d371dda947a9ca994e8bc19cbc3e43b83d6716c6b43b1b6a7c1b6f
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 468ba188f034b23398e1f07b915cf7c8b337dcf7f56a13511947c5322ae98722
-R 83d792277e49d25b00c0094481fa71d7
+P 7200372ed2424d1ac4c88644e0b17a224539f170b9111ced9c88774edbd75261
+R c08f61440d4d487375dc477b759daec9
U drh
-Z 7f22080d0311b852cf62e1bdb7405410
+Z 6f4e493d857d3f3fb51f0ded7bd78aca
# Remove this line to create a well-formed Fossil manifest.
-7200372ed2424d1ac4c88644e0b17a224539f170b9111ced9c88774edbd75261
+633fe4fe584ae14ed6ced1ae137bf96a434a012423d70f0f93876737b0ca075c
qrf.pzOutput = &zResult;
for(i=2; i<objc; i++){
const char *zArg = Tcl_GetString(objv[i]);
- if( zArg[0]!='-' && zSql==0 ){
+ const char *azBool[] = { "auto", "off", "on", 0 };
+ if( zArg[0]!='-' ){
+ if( zSql ){
+ Tcl_AppendResult(pDb->interp, "unknown argument: ", zArg, (char*)0);
+ rc = TCL_ERROR;
+ goto format_failed;
+ }
zSql = zArg;
- }else if( strcmp(zArg,"-style")==0 && i<objc-1 ){
+ }else if( i==objc-1 ){
+ Tcl_AppendResult(pDb->interp, "option has no argument: ", zArg, (char*)0);
+ rc = TCL_ERROR;
+ goto format_failed;
+ }else if( strcmp(zArg,"-style")==0 ){
static const char *azStyles[] = {
"auto", "box", "column",
"count", "csv", "eqp",
"explain", "html", "insert",
"json", "line", "list",
"markdown", "quote", "scanexp",
- "table"
+ "table", 0
};
static unsigned char aStyleMap[] = {
QRF_STYLE_Auto, QRF_STYLE_Box, QRF_STYLE_Column,
QRF_STYLE_Table
};
int style;
- if( Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azStyles,
- "format style", 0, &style) ) return SQLITE_ERROR;
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azStyles,
+ "format style", 0, &style);
+ if( rc ) goto format_failed;
qrf.eStyle = aStyleMap[style];
i++;
+ }else if( strcmp(zArg,"-null")==0 ){
+ qrf.zNull = Tcl_GetString(objv[i+1]);
+ i++;
+ }else if( strcmp(zArg,"-rowsep")==0 ){
+ qrf.zRowSep = Tcl_GetString(objv[i+1]);
+ i++;
+ }else if( strcmp(zArg,"-columnsep")==0 ){
+ qrf.zColumnSep = Tcl_GetString(objv[i+1]);
+ i++;
+ }else if( strcmp(zArg,"-tablename")==0 ){
+ qrf.zTableName = Tcl_GetString(objv[i+1]);
+ i++;
+ }else if( strcmp(zArg,"-columnnames")==0 ){
+ int v = 0;
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
+ "-columnnames", 0, &v);
+ if( rc ) goto format_failed;
+ qrf.bColumnNames = v;
+ i++;
+ }else if( strcmp(zArg,"-wordwrap")==0 ){
+ int v = 0;
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
+ "-wordwrap", 0, &v);
+ if( rc ) goto format_failed;
+ qrf.bWordWrap = v;
+ i++;
+ }else if( strcmp(zArg,"-testjsonb")==0 ){
+ int v = 0;
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
+ "-testjsonb", 0, &v);
+ if( rc ) goto format_failed;
+ qrf.bTextJsonb = v;
+ i++;
+ }else if( strcmp(zArg,"-maxwidth")==0 ){
+ int v = 0;
+ rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
+ if( rc ) goto format_failed;
+ if( v<0 ){
+ v = 0;
+ }else if( v>QRF_MX_WIDTH ){
+ v = QRF_MX_WIDTH;
+ }
+ qrf.mxWidth = v;
+ i++;
+ }else if( strcmp(zArg,"-widths")==0 ){
+ int n = 0;
+ int jj;
+ rc = Tcl_ListObjLength(pDb->interp, objv[i+1], &n);
+ if( rc ) goto format_failed;
+ sqlite3_free(qrf.aWidth);
+ qrf.aWidth = sqlite3_malloc64( (n+1)*sizeof(qrf.aWidth[0]) );
+ if( qrf.aWidth==0 ){
+ Tcl_AppendResult(pDb->interp, "out of memory", (char*)0);
+ rc = TCL_ERROR;
+ goto format_failed;
+ }
+ memset(qrf.aWidth, 0, (n+1)*sizeof(qrf.aWidth[0]));
+ qrf.nWidth = n;
+ for(jj=0; jj<n; jj++){
+ Tcl_Obj *pTerm;
+ const char *zTerm;
+ rc = Tcl_ListObjIndex(pDb->interp, objv[i+1], jj, &pTerm);
+ if( rc ) goto format_failed;
+ zTerm = Tcl_GetString(pTerm);
+ if( strcmp(zTerm, "-0")==0 ){
+ qrf.aWidth[jj] = QRF_MINUS_ZERO;
+ }else{
+ int v = atoi(zTerm);
+ if( v<QRF_MN_WIDTH ){
+ v = QRF_MN_WIDTH;
+ }else if( v>QRF_MX_WIDTH ){
+ v = QRF_MX_WIDTH;
+ }
+ qrf.aWidth[jj] = v;
+ }
+ }
+ i++;
}else{
- Tcl_AppendResult(pDb->interp, "unknown argument: ", zArg, (char*)0);
- return TCL_ERROR;
+ Tcl_AppendResult(pDb->interp, "unknown option: ", zArg, (char*)0);
+ rc = TCL_ERROR;
+ goto format_failed;
}
}
while( zSql && zSql[0] ){
}
}
Tcl_SetResult(pDb->interp, zResult, TCL_VOLATILE);
- sqlite3_free(zResult);
- return TCL_OK;
-
+ rc = TCL_OK;
+ /* Fall through...*/
+
format_failed:
+ sqlite3_free(qrf.aWidth);
sqlite3_free(zResult);
return rc;
** text and return that text.
*/
case DB_FORMAT: {
- dbQrf(pDb, objc, objv);
+ rc = dbQrf(pDb, objc, objv);
break;
}
do_test 1.40 {
set result "\n[db format -style column {SELECT * FROM t1}]"
} {
+a b c
+---- --- -----
+1 2.5 three
+BLOB Ἀμήν
+}
+do_test 1.41 {
+ set result "\n[db format -style column -columnnames off {SELECT * FROM t1}]"
+} {
1 2.5 three
BLOB Ἀμήν
}
do_test 1.60 {
db format -style csv {SELECT * FROM t1}
} "1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
+do_test 1.61 {
+ db format -style csv -columnnames on {SELECT * FROM t1}
+} "a,b,c\r\n1,2.5,three\r\n\"\\102\\114\\117\\102\",,\"Ἀμήν\"\r\n"
do_test 1.70 {
set result "\n[db format -style html {SELECT * FROM t1}]"
<TD>Ἀμήν
</TR>
}
+do_test 1.71 {
+ set result "\n[db format -style html -columnnames on {SELECT * FROM t1}]"
+} {
+<TR>
+<TH>a
+<TH>b
+<TH>c
+</TR>
+<TR>
+<TD>1
+<TD>2.5
+<TD>three
+</TR>
+<TR>
+<TD>BLOB
+<TD>null
+<TD>Ἀμήν
+</TR>
+}
do_test 1.80 {
set result "\n[db format -style insert {SELECT * FROM t1}]"
INSERT INTO tab VALUES(1,2.5,'three');
INSERT INTO tab VALUES(x'424c4f42',NULL,'Ἀμήν');
}
+do_test 1.81 {
+ set result "\n[db format -style insert -tablename t1 {SELECT * FROM t1}]"
+} {
+INSERT INTO t1 VALUES(1,2.5,'three');
+INSERT INTO t1 VALUES(x'424c4f42',NULL,'Ἀμήν');
+}
+do_test 1.82 {
+ set result "\n[db format -style insert -tablename t1 -columnnames on \
+ {SELECT * FROM t1}]"
+} {
+INSERT INTO t1(a,b,c) VALUES(1,2.5,'three');
+INSERT INTO t1(a,b,c) VALUES(x'424c4f42',NULL,'Ἀμήν');
+}
+do_test 1.83 {
+ set result "\n[db format -style insert -tablename drop -columnnames on \
+ {SELECT a AS "a-b", b, c AS "123" FROM t1}]"
+} {
+INSERT INTO "drop"("a-b",b,"123") VALUES(1,2.5,'three');
+INSERT INTO "drop"("a-b",b,"123") VALUES(x'424c4f42',NULL,'Ἀμήν');
+}
do_test 1.90 {
set result "\n[db format -style json {SELECT * FROM t1}]"
b =
c = Ἀμήν
}
+do_test 1.101 {
+ set result "\n[db format -style line -null (NULL) {SELECT * FROM t1}]"
+} {
+a = 1
+b = 2.5
+c = three
+
+a = BLOB
+b = (NULL)
+c = Ἀμήν
+}
do_test 1.110 {
set result "\n[db format -style list {SELECT * FROM t1}]"
1|2.5|three
BLOB||Ἀμήν
}
+do_test 1.111 {
+ set result "\n[db format -style list -columnnames on {SELECT * FROM t1}]"
+} {
+a|b|c
+1|2.5|three
+BLOB||Ἀμήν
+}
+do_test 1.112 {
+ set rc [catch {db format -style list -columnnames unk {SELECT * FROM t1}} res]
+ lappend rc $res
+} {1 {bad -columnnames "unk": must be auto, off, or on}}
+
do_test 1.120 {
set result "\n[db format -style markdown {SELECT * FROM t1}]"
1,2.5,'three'
x'424c4f42',NULL,'Ἀμήν'
}
+do_test 1.131 {
+ set result "\n[db format -style quote -columnnames on {SELECT * FROM t1}]"
+} {
+'a','b','c'
+1,2.5,'three'
+x'424c4f42',NULL,'Ἀμήν'
+}
+
+
+do_execsql_test 2.0 {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(1,2,'The quick fox jumps over the lazy brown dog.');
+}
+do_test 2.1 {
+ set result "\n[db format -widths {10 -10 22} -wordwrap off \
+ {SELECT * FROM t1}]"
+} {
+┌────────────┬────────────┬────────────────────────┐
+│ a │ b │ c │
+├────────────┼────────────┼────────────────────────┤
+│ 1 │ 2 │ The quick fox jumps ov │
+│ │ │ er the lazy brown dog. │
+└────────────┴────────────┴────────────────────────┘
+}
finish_test