1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-11 01:42:22 +03:00

Code and comment cleanup. Everything should work the same.

FossilOrigin-Name: c640754df0d3ffdad994745f0d0e10c8f19f424b87f6a6e6e269491a0350b950
This commit is contained in:
drh
2023-12-02 20:25:36 +00:00
parent 53c2160db0
commit c1e85742da
3 changed files with 125 additions and 90 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sharmless\scompiler\swarnings.\s\sRefactor\ssome\sidentifier\snames\sfor\nclearer\spresentation. C Code\sand\scomment\scleanup.\s\sEverything\sshould\swork\sthe\ssame.
D 2023-12-02T18:17:38.516 D 2023-12-02T20:25:36.578
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -688,7 +688,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276 F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c b67328611c8ebc5aca49e2d73b1bad9962948aa5c952f3d96c44eb74ee3d0010 F src/json.c 5ad1a1be6199359b09bb4eca690789b77375e00f17c55697b6288f1b0fbbe8b0
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9 F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
@@ -2145,8 +2145,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1304534001e9ef66c6b12752b69d790bfa3427cc803f87cc48ca22ae12df0fdf P 7e3941502789c5afaf19b08112f464abf5e3cba7f92fc9290af2a0f96127ad9a
R 1b492fad564bbccdff370d30a804d641 R 9f984966a856d28c36c8f0d6d69732a4
U drh U drh
Z f1274565e5b6e1f5da018a4ab14dfe40 Z ea3e13091dceb571341f1dccf0e97828
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
7e3941502789c5afaf19b08112f464abf5e3cba7f92fc9290af2a0f96127ad9a c640754df0d3ffdad994745f0d0e10c8f19f424b87f6a6e6e269491a0350b950

View File

@@ -133,12 +133,13 @@
#define JSONB_ARRAY 11 /* An array */ #define JSONB_ARRAY 11 /* An array */
#define JSONB_OBJECT 12 /* An object */ #define JSONB_OBJECT 12 /* An object */
/* Human-readable names for the JSONB values: /* Human-readable names for the JSONB values. The index for each
** string must correspond to the JSONB_* integer above.
*/ */
static const char * const jsonbType[] = { static const char * const jsonbType[] = {
"null", "true", "false", "integer", "integer", "null", "true", "false", "integer", "integer",
"real", "real", "text", "text", "text", "real", "real", "text", "text", "text",
"text", "array", "object" "text", "array", "object", "", "", "", ""
}; };
/* /*
@@ -168,7 +169,7 @@ static const char jsonIsSpace[] = {
#define jsonIsspace(x) (jsonIsSpace[(unsigned char)x]) #define jsonIsspace(x) (jsonIsSpace[(unsigned char)x])
/* /*
** Characters that are special to JSON. Control charaters, ** Characters that are special to JSON. Control characters,
** '"' and '\\'. ** '"' and '\\'.
*/ */
static const char jsonIsOk[256] = { static const char jsonIsOk[256] = {
@@ -204,7 +205,6 @@ typedef struct JsonCache JsonCache;
typedef struct JsonString JsonString; typedef struct JsonString JsonString;
typedef struct JsonParse JsonParse; typedef struct JsonParse JsonParse;
/* /*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata() ** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/ */
@@ -213,8 +213,14 @@ typedef struct JsonParse JsonParse;
/* A cache mapping JSON text into JSONB blobs. /* A cache mapping JSON text into JSONB blobs.
** **
** All content, both JSON text and the JSONB blobs, is stored as RCStr ** Each cache entry is a JsonParse object with the following restrictions:
** objects. **
** * The bReadOnly flag must be set
**
** * The aBlob[] array must be owned by the JsonParse object. In other
** words, nBlobAlloc must be non-zero.
**
** * zJson must be an RCStr. In other words bJsonIsRCStr must be true.
*/ */
struct JsonCache { struct JsonCache {
sqlite3 *db; /* Database connection */ sqlite3 *db; /* Database connection */
@@ -225,6 +231,10 @@ struct JsonCache {
/* An instance of this object represents a JSON string /* An instance of this object represents a JSON string
** under construction. Really, this is a generic string accumulator ** under construction. Really, this is a generic string accumulator
** that can be and is used to create strings other than JSON. ** that can be and is used to create strings other than JSON.
**
** If the generated string is longer than will fit into the zSpace[] buffer,
** then it will be an RCStr string. This aids with caching of large
** JSON strings.
*/ */
struct JsonString { struct JsonString {
sqlite3_context *pCtx; /* Function context - put error messages here */ sqlite3_context *pCtx; /* Function context - put error messages here */
@@ -260,18 +270,17 @@ struct JsonString {
/* A parsed JSON value. Lifecycle: /* A parsed JSON value. Lifecycle:
** **
** 1. JSON comes in and is parsed into a JSONB value in aBlob. The ** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
** original text is stored in zJson. ** original text is stored in zJson. This step is skipped if the
** input is JSONB instead of text JSON.
** **
** 2. The aBlob is searched using the JSON path notation, if needed. ** 2. The aBlob[] array is searched using the JSON path notation, if needed.
** **
** 3. Zero or more changes are made to aBlob (via json_remove() or ** 3. Zero or more changes are made to aBlob[] (via json_remove() or
** json_replace() or similar). ** json_replace() or json_patch() or similar).
** **
** 4. New JSON text is generated from the aBlob for output. ** 4. New JSON text is generated from the aBlob[] for output. This step
** ** is skipped the function is one of the jsonb_* functions that returns
** Step 1 is omitted if the input is a BLOB in the JSONB format. Step 4 ** JSONB instead of text JSON.
** is omitted if the output is JSONB or some other value that is not
** JSON text.
*/ */
struct JsonParse { struct JsonParse {
u8 *aBlob; /* JSONB representation of JSON value */ u8 *aBlob; /* JSONB representation of JSON value */
@@ -326,7 +335,6 @@ static void jsonReturnParse(sqlite3_context*,JsonParse*);
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
static void jsonParseFree(JsonParse*); static void jsonParseFree(JsonParse*);
/************************************************************************** /**************************************************************************
** Utility routines for dealing with JsonCache objects ** Utility routines for dealing with JsonCache objects
**************************************************************************/ **************************************************************************/
@@ -346,11 +354,11 @@ static void jsonCacheDeleteGeneric(void *p){
} }
/* /*
** Insert a new entry into the cache. If the cache is full, expell ** Insert a new entry into the cache. If the cache is full, expel
** the least recently used entry. Return SQLITE_OK on success or a ** the least recently used entry. Return SQLITE_OK on success or a
** result code otherwise. ** result code otherwise.
** **
** Both the input JSON and JSONB must be RCStr objects. ** Cache entries are stored in age order, oldest first.
*/ */
static int jsonCacheInsert( static int jsonCacheInsert(
sqlite3_context *ctx, /* The SQL statement context holding the cache */ sqlite3_context *ctx, /* The SQL statement context holding the cache */
@@ -386,7 +394,14 @@ static int jsonCacheInsert(
/* /*
** Search for a cached translation the json text supplied by pArg. Return ** Search for a cached translation the json text supplied by pArg. Return
** the JsonParse object if found. ** the JsonParse object if found. Return NULL if not found.
**
** When a match if found, the matching entry is moved to become the
** most-recently used entry if it isn't so already.
**
** The JsonParse object returned still belongs to the Cache and might
** be deleted at any moment. If the caller whants the JsonParse to
** linger, it needs to increment the nPJRef reference counter.
*/ */
static JsonParse *jsonCacheSearch( static JsonParse *jsonCacheSearch(
sqlite3_context *ctx, /* The SQL statement context holding the cache */ sqlite3_context *ctx, /* The SQL statement context holding the cache */
@@ -419,6 +434,7 @@ static JsonParse *jsonCacheSearch(
} }
if( i<p->nUsed ){ if( i<p->nUsed ){
if( i<p->nUsed-1 ){ if( i<p->nUsed-1 ){
/* Make the matching entry the most recently used entry */
JsonParse *tmp = p->a[i]; JsonParse *tmp = p->a[i];
memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp)); memmove(&p->a[i], &p->a[i+1], (p->nUsed-i-1)*sizeof(tmp));
p->a[p->nUsed-1] = tmp; p->a[p->nUsed-1] = tmp;
@@ -561,7 +577,9 @@ static void jsonStringTerminate(JsonString *p){
} }
} }
/* Try to force the string to be a zero-terminated RCStr string. /* Try to force the string to be a zero-terminated RCStr string. In other
** words, make sure it is not still using the internal zSpace[] static
** buffer.
** **
** Return true on success. Return false if an OOM prevents this ** Return true on success. Return false if an OOM prevents this
** from happening. ** from happening.
@@ -591,9 +609,12 @@ static void jsonAppendSeparator(JsonString *p){
} }
/* Append the N-byte string in zIn to the end of the JsonString string /* Append the N-byte string in zIn to the end of the JsonString string
** under construction. Enclose the string in "..." and escape ** under construction. Enclose the string in double-quotes ("...") and
** any double-quotes or backslash characters contained within the ** escape any double-quotes or backslash characters contained within the
** string. ** string.
**
** This routine is a high-runner. There is a measurable performance
** increase associated with unwinding the jsonIsOk[] loop.
*/ */
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 k; u32 k;
@@ -604,8 +625,8 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
p->zBuf[p->nUsed++] = '"'; p->zBuf[p->nUsed++] = '"';
while( 1 /*exit-by-break*/ ){ while( 1 /*exit-by-break*/ ){
k = 0; k = 0;
while( k+1<N && jsonIsOk[z[k]] && jsonIsOk[z[k+1]] ){ k += 2; } while( k+1<N && jsonIsOk[z[k]] && jsonIsOk[z[k+1]] ){ k += 2; } /* <--, */
while( k<N && jsonIsOk[z[k]] ){ k++; } while( k<N && jsonIsOk[z[k]] ){ k++; } /* <-- loop unwound for speed */
if( k>=N ){ if( k>=N ){
if( k>0 ){ if( k>0 ){
memcpy(&p->zBuf[p->nUsed], z, k); memcpy(&p->zBuf[p->nUsed], z, k);
@@ -783,12 +804,8 @@ static void jsonParseReset(JsonParse *pParse){
} }
/* /*
** Free a JsonParse object that was obtained from sqlite3_malloc(). ** Decrement the reference count on the JsonParse object. When the
** ** count reaches zero, free the object.
** Note that destroying JsonParse might call sqlite3RCStrUnref() to
** destroy the zJson value. The RCStr object might recursively invoke
** JsonParse to destroy this pParse object again. Take care to ensure
** that this recursive destructor sequence terminates harmlessly.
*/ */
static void jsonParseFree(JsonParse *pParse){ static void jsonParseFree(JsonParse *pParse){
if( pParse ){ if( pParse ){
@@ -1010,7 +1027,6 @@ static void jsonWrongNumArgs(
** Utility routines for dealing with the binary BLOB representation of JSON ** Utility routines for dealing with the binary BLOB representation of JSON
****************************************************************************/ ****************************************************************************/
/* /*
** Expand pParse->aBlob so that it holds at least N bytes. ** Expand pParse->aBlob so that it holds at least N bytes.
** **
@@ -2068,7 +2084,8 @@ static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){
} }
/* /*
** Edit the size of the element at iRoot by the amount in pParse->delta. ** Edit the payload size of the element at iRoot by the amount in
** pParse->delta.
*/ */
static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){ static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){
u32 sz = 0; u32 sz = 0;
@@ -2126,6 +2143,55 @@ static void jsonBlobEdit(
#define JSON_LOOKUP_PATHERROR 0xfffffffd #define JSON_LOOKUP_PATHERROR 0xfffffffd
#define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) #define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR)
/* Forward declaration */
static u32 jsonLookupStep(JsonParse*,u32,const char*,u32);
/* This helper routine for jsonLookupStep() populates pIns with
** binary data that is to be inserted into pParse.
**
** In the common case, pIns just points to pParse->aIns and pParse->nIns.
** But if the zPath of the original edit operation includes path elements
** that go deeper, additional substructure must be created.
**
** For example:
**
** json_insert('{}', '$.a.b.c', 123);
**
** The search stops at '$.a' But additional substructure must be
** created for the ".b.c" part of the patch so that the final result
** is: {"a":{"b":{"c"::123}}}. This routine populates pIns with
** the binary equivalent of {"b":{"c":123}} so that it can be inserted.
**
** The caller is responsible for resetting pIns when it has finished
** using the substructure.
*/
static u32 jsonCreateEditSubstructure(
JsonParse *pParse, /* The original JSONB that is being edited */
JsonParse *pIns, /* Populate this with the blob data to insert */
const char *zTail /* Tail of the path that determins substructure */
){
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
int rc;
memset(pIns, 0, sizeof(*pIns));
if( zTail[0]==0 ){
/* No substructure. Just insert what is given in pParse. */
pIns->aBlob = pParse->aIns;
pIns->nBlob = pParse->nIns;
rc = 0;
}else{
/* Construct the binary substructure */
pIns->nBlob = 1;
pIns->aBlob = (u8*)&emptyObject[zTail[0]=='.'];
pIns->eEdit = pParse->eEdit;
pIns->nIns = pParse->nIns;
pIns->aIns = pParse->aIns;
rc = jsonLookupStep(pIns, 0, zTail, 0);
pParse->oom |= pIns->oom;
}
return rc; /* Error code only */
}
/* /*
** Search along zPath to find the Json element specified. Return an ** Search along zPath to find the Json element specified. Return an
** index into pParse->aBlob[] for the start of that element's value. ** index into pParse->aBlob[] for the start of that element's value.
@@ -2135,6 +2201,13 @@ static void jsonBlobEdit(
** label, before returning. ** label, before returning.
** **
** Return one of the JSON_LOOKUP error codes if problems are seen. ** Return one of the JSON_LOOKUP error codes if problems are seen.
**
** This routine will also modify the blob. If pParse->eEdit is one of
** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be
** made to the selected value. If an edit is performed, then the return
** value does not necessarily point to the select element. If an edit
** is performed, the return value is only useful for detecting error
** conditions.
*/ */
static u32 jsonLookupStep( static u32 jsonLookupStep(
JsonParse *pParse, /* The JSON to search */ JsonParse *pParse, /* The JSON to search */
@@ -2145,7 +2218,6 @@ static u32 jsonLookupStep(
u32 i, j, k, nKey, sz, n, iEnd, rc; u32 i, j, k, nKey, sz, n, iEnd, rc;
const char *zKey; const char *zKey;
u8 x; u8 x;
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
if( zPath[0]==0 ){ if( zPath[0]==0 ){
if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){ if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){
@@ -2224,26 +2296,12 @@ static u32 jsonLookupStep(
testcase( pParse->eEdit==JEDIT_SET ); testcase( pParse->eEdit==JEDIT_SET );
memset(&ix, 0, sizeof(ix)); memset(&ix, 0, sizeof(ix));
jsonBlobAppendNode(&ix,JSONB_TEXTRAW, nKey, 0); jsonBlobAppendNode(&ix,JSONB_TEXTRAW, nKey, 0);
memset(&v, 0, sizeof(v));
if( zPath[i]==0 ){
v.nBlob = pParse->nIns;
v.aBlob = pParse->aIns;
}else{
v.nBlob = 1;
v.aBlob = (u8*)&emptyObject[zPath[i]=='.'];
v.eEdit = pParse->eEdit;
v.nIns = pParse->nIns;
v.aIns = pParse->aIns;
rc = jsonLookupStep(&v, 0, &zPath[i], 0);
if( JSON_LOOKUP_ISERROR(rc) || v.oom ){
pParse->oom |= v.oom;
jsonParseReset(&v);
jsonParseReset(&ix);
return rc;
}
}
pParse->oom |= ix.oom; pParse->oom |= ix.oom;
if( jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob) ){ rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
if( !JSON_LOOKUP_ISERROR(rc)
&& jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob)
){
assert( !pParse->oom );
nIns = ix.nBlob + nKey + v.nBlob; nIns = ix.nBlob + nKey + v.nBlob;
jsonBlobEdit(pParse, j, 0, 0, nIns); jsonBlobEdit(pParse, j, 0, 0, nIns);
if( !pParse->oom ){ if( !pParse->oom ){
@@ -2257,7 +2315,7 @@ static u32 jsonLookupStep(
} }
jsonParseReset(&v); jsonParseReset(&v);
jsonParseReset(&ix); jsonParseReset(&ix);
return j; return rc;
} }
}else if( zPath[0]=='[' ){ }else if( zPath[0]=='[' ){
x = pParse->aBlob[iRoot] & 0x0f; x = pParse->aBlob[iRoot] & 0x0f;
@@ -2309,29 +2367,16 @@ static u32 jsonLookupStep(
JsonParse v; JsonParse v;
testcase( pParse->eEdit==JEDIT_INS ); testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET ); testcase( pParse->eEdit==JEDIT_SET );
memset(&v, 0, sizeof(v)); rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]);
if( zPath[i+1]==0 ){ if( !JSON_LOOKUP_ISERROR(rc)
v.aBlob = pParse->aIns; && jsonBlobMakeEditable(pParse, v.nBlob)
v.nBlob = pParse->nIns; ){
}else{ assert( !pParse->oom );
v.nBlob = 1;
v.aBlob = (u8*)&emptyObject[zPath[i+1]=='.'];
v.eEdit = pParse->eEdit;
v.nIns = pParse->nIns;
v.aIns = pParse->aIns;
rc = jsonLookupStep(&v, 0, &zPath[i+1], 0);
if( JSON_LOOKUP_ISERROR(rc) || v.oom ){
pParse->oom |= v.oom;
jsonParseReset(&v);
return rc;
}
}
if( jsonBlobMakeEditable(pParse, v.nBlob) ){
jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob); jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob);
} }
jsonParseReset(&v); jsonParseReset(&v);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot); if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return j; return rc;
} }
}else{ }else{
return JSON_LOOKUP_PATHERROR; return JSON_LOOKUP_PATHERROR;
@@ -3169,17 +3214,7 @@ static void jsonArrayLengthFunc(
i = 0; i = 0;
} }
if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){ if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){
u32 n, sz = 0, iEnd; cnt = jsonbArrayCount(p, i);
n = jsonbPayloadSize(p, i, &sz);
if( n==0 ) eErr = 2;
iEnd = i+n+sz;
i += n;
while( eErr==0 && i<iEnd ){
cnt++;
n = jsonbPayloadSize(p, i, &sz);
if( n==0 ) eErr = 2;
i += n+sz;
}
} }
if( eErr ){ if( eErr ){
if( eErr==2 ) sqlite3_result_error(ctx, "malformed JSON", -1); if( eErr==2 ) sqlite3_result_error(ctx, "malformed JSON", -1);