From: drh <> Date: Tue, 28 Oct 2025 22:25:24 +0000 (+0000) Subject: Add support for the bTxtJsonb flag in sqlite3_qrf_spec, which if true causes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a73fb2b23344026369720f1e9ae3e3b3584150e8;p=thirdparty%2Fsqlite.git Add support for the bTxtJsonb flag in sqlite3_qrf_spec, which if true causes JSONB blobs to be displayed as JSON text. FossilOrigin-Name: 3fcf9ecb039a903cefcf4eeaf43974de0cbd48d899dc189b8f70c3745addc11a --- diff --git a/ext/qrf/README.md b/ext/qrf/README.md index ece06b60bc..000709efd1 100644 --- a/ext/qrf/README.md +++ b/ext/qrf/README.md @@ -44,6 +44,7 @@ struct sqlite3_qrf_spec { unsigned char eQuote; /* Quoting style for text */ unsigned char eBlob; /* Quoting style for BLOBs */ unsigned char bWordWrap; /* Try to wrap on word boundaries */ + unsigned char bTxtJsonb; /* Render JSONB blobs as JSON text */ short int mxWidth; /* Maximum width of any column */ int nWidth; /* Number of column width parameters */ short int *aWidth; /* Column widths */ @@ -170,10 +171,16 @@ A value of QRF_TXT_Json gives similar results as QRF_TXT_Tcl except that the rules are adjusted so that the displayed string is strictly conforming the JSON specification. -### 2.7 How to escape BLOB values +### 2.7 How to escape BLOB values (eBlob and bTxtJsonb) -The sqlite3_qrf_spec.eBlob field determines out BLOB values are formatted -for display. This field can have one of the following values: +If the sqlite3_qrf_spec.bTxtJsonb flag is true 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.eQuote setting as +described in the previous section. + +If the bTxtJsonb flag is false (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; > ~~~ #define QRF_BLOB_Auto 0 /* Determine BLOB quoting using eQuote */ diff --git a/ext/qrf/qrf-tester.c b/ext/qrf/qrf-tester.c index d264a7a7e9..4226782daf 100644 --- a/ext/qrf/qrf-tester.c +++ b/ext/qrf/qrf-tester.c @@ -297,6 +297,9 @@ int main(int argc, char **argv){ if( strncmp(zLine, "--bShowCNames=", 14)==0 ){ spec.bShowCNames = atoi(&zLine[14])!=0; }else + if( strncmp(zLine, "--bTxtJsonb=", 12)==0 ){ + spec.bTxtJsonb = atoi(&zLine[12])!=0; + }else if( strncmp(zLine, "--zNull=", 8)==0 ){ spec.zNull = tempStrdup(&zLine[8]); }else diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index 437b5e5c6c..7768d31674 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -44,6 +44,7 @@ typedef struct Qrf Qrf; struct Qrf { sqlite3_stmt *pStmt; /* The statement whose output is to be rendered */ sqlite3 *db; /* The corresponding database connection */ + sqlite3_stmt *pJTrans; /* JSONB to JSON translator statement */ char **pzErr; /* Write error message here, if not NULL */ sqlite3_str *pOut; /* Accumulated output */ int iErr; /* Error code */ @@ -574,6 +575,48 @@ static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){ } } +/* +** The current iCol-th column of p->pStmt is known to be a BLOB. Check +** to see if that BLOB is really a JSONB blob. If it is, then translate +** it into a text JSON representation and return a pointer to that text JSON. +** +** The memory used to hold the JSON text is managed internally by the +** "p" object and is overwritten and/or deallocated upon the next call +** to this routine (with the same p argument) or when the p object is +** finailized. +*/ +static const char *qrfJsonbToJson(Qrf *p, int iCol){ + int nByte; + const void *pBlob; + int rc; + if( p->pJTrans==0 ){ + sqlite3 *db; + rc = sqlite3_open(":memory:",&db); + if( rc ){ + sqlite3_close(db); + return 0; + } + rc = sqlite3_prepare_v2(db, "SELECT json(?1)", -1, &p->pJTrans, 0); + if( rc ){ + sqlite3_finalize(p->pJTrans); + p->pJTrans = 0; + sqlite3_close(db); + return 0; + } + }else{ + sqlite3_reset(p->pJTrans); + } + nByte = sqlite3_column_bytes(p->pStmt, iCol); + pBlob = sqlite3_column_blob(p->pStmt, iCol); + sqlite3_bind_blob(p->pJTrans, 1, (void*)pBlob, nByte, SQLITE_STATIC); + rc = sqlite3_step(p->pJTrans); + if( rc==SQLITE_ROW ){ + return (const char*)sqlite3_column_text(p->pJTrans, 0); + }else{ + return 0; + } +} + /* ** Render value pVal into pOut */ @@ -601,6 +644,13 @@ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){ break; } case SQLITE_BLOB: { + if( p->spec.bTxtJsonb ){ + const char *zJson = qrfJsonbToJson(p, iCol); + if( zJson ){ + qrfEncodeText(p, pOut, zJson); + break; + } + } switch( p->spec.eBlob ){ case QRF_BLOB_Hex: case QRF_BLOB_Sql: { @@ -1222,6 +1272,7 @@ qrf_column_end: sqlite3_free(azData[i]); } sqlite3_free(azData); + sqlite3_free(abRowDiv); return; } @@ -1675,6 +1726,11 @@ static void qrfFinalize(Qrf *p){ sqlite3_free(sqlite3_str_finish(p->pOut)); } if( p->actualWidth ) sqlite3_free(p->actualWidth); + if( p->pJTrans ){ + sqlite3 *db = sqlite3_db_handle(p->pJTrans); + sqlite3_finalize(p->pJTrans); + sqlite3_close(db); + } } /* diff --git a/ext/qrf/qrf.h b/ext/qrf/qrf.h index 0cf5d01c82..f4e8a42e3c 100644 --- a/ext/qrf/qrf.h +++ b/ext/qrf/qrf.h @@ -27,6 +27,7 @@ struct sqlite3_qrf_spec { unsigned char eQuote; /* Quoting style for text */ unsigned char eBlob; /* Quoting style for BLOBs */ unsigned char bWordWrap; /* Try to wrap on word boundaries */ + unsigned char bTxtJsonb; /* Render JSONB blobs as JSON text */ short int mxWidth; /* Maximum width of any column */ int nWidth; /* Number of column width parameters */ short int *aWidth; /* Column widths */ diff --git a/manifest b/manifest index d463706e6f..fbbc68b341 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sharmless\scompiler\swarning. -D 2025-10-28T19:37:18.472 +C Add\ssupport\sfor\sthe\sbTxtJsonb\sflag\sin\ssqlite3_qrf_spec,\swhich\sif\strue\scauses\nJSONB\sblobs\sto\sbe\sdisplayed\sas\sJSON\stext. +D 2025-10-28T22:25:24.967 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 f98f1777446c7ae96c9a60f7d2042e3e8c8f80db75c4aa69f7314b1d27fb1814 -F ext/qrf/qrf-tester.c 7d72e3268db31a348c2e8002b174eac9a25d1f93350d845e1ef5f60dfddd95a9 -F ext/qrf/qrf.c 2522d8a938875badb499e199c13fc68eaa9b9141ce4f4acf843e00e8d0d64d20 -F ext/qrf/qrf.h 68c7d03ece46d329d0df90e2bae2d08771bba32bb9affc368691249b7b605158 +F ext/qrf/README.md 8e0763e34c97c288c8e913f8984c89c270aa9f681a9fc389320b3e36cdf7ea4f +F ext/qrf/qrf-tester.c 25b5c71fecde6053d7c49e91de578b15b09f370cc9d2db0de3bc55251da9fe45 +F ext/qrf/qrf.c 221937b10e5ced56a4bbdeae940b75f4c71776827910a34cd0b3168374e4eaec +F ext/qrf/qrf.h 70d3e5b24c22bb14a19cdc2121aeff6a4054e29541e14dcb4750c0cfba6078c2 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 F ext/rbu/rbu10.test 7c22caa32c2ff26983ca8320779a31495a6555737684af7aba3daaf762ef3363 @@ -2175,8 +2175,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fa5661ea8b6b5ca368d719477bd82a954d2f979f4ab85fff2720cf7bb7cc427d -R cd4e401ce66ee9cb501533b05e6c9f99 +P d00c549126ca96b061e537dfabb93b02824e3a9b8fa0c9135a96cf060262206e +R eb84edc720870a58624028e0ab77bb61 U drh -Z d0bb32d0a0ee6a7455bdbcfecd272cc9 +Z 008d48891a8df1ef5b5f2498f9433818 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 25f14a6950..83386db706 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d00c549126ca96b061e537dfabb93b02824e3a9b8fa0c9135a96cf060262206e +3fcf9ecb039a903cefcf4eeaf43974de0cbd48d899dc189b8f70c3745addc11a