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

Further improvements to large string handling in relation to JSON.

FossilOrigin-Name: 1e5df0aa3dae5cadbf1d07c718ae2a5212543300b68e49d35e8c96855a7f619c
This commit is contained in:
drh
2023-07-21 18:09:07 +00:00
parent eee8687a9f
commit 569700a72e
6 changed files with 44 additions and 22 deletions

View File

@@ -501,8 +501,8 @@ static void jsonAppendValue(
*/
static void jsonResult(JsonString *p){
if( p->bErr==0 ){
if( p->nAlloc>=p->nUsed+1 ) p->zBuf[p->nUsed] = 0;
sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
jsonAppendChar(p, 0);
sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed-1,
p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
SQLITE_UTF8);
jsonZero(p);

View File

@@ -611,6 +611,7 @@ int sqlite3VdbeMemSetZeroBlob(Mem*,int);
int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
int sqlite3VdbeMemSetRowSet(Mem*);
void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemStringify(Mem*, u8, u8);
int sqlite3IntFloatCompare(i64,double);

View File

@@ -514,15 +514,7 @@ void sqlite3_result_text64(
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, enc, xDel);
if( xDel==sqlite3_free && enc==SQLITE_UTF8 ){
Mem *pOut = pCtx->pOut;
if( pOut->z==z
&& sqlite3_msize(pOut->z) >= (sqlite3_uint64)(pOut->n+1)
&& pOut->z[n]==0
){
pOut->flags |= MEM_Term;
}
}
sqlite3VdbeMemZeroTerminateIfAble(pCtx->pOut);
}
}
#ifndef SQLITE_OMIT_UTF16

View File

@@ -314,6 +314,32 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
return SQLITE_OK;
}
/*
** If pMem is already a string, detect if it is a zero-terminated
** string, or make it into one if possible, and mark it as such.
**
** This is an optimization. Correct operation continues even if
** this routine is a no-op.
*/
void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Term))!=MEM_Str ) return;
if( pMem->enc!=SQLITE_UTF8 ) return;
if( pMem->z==0 ) return;
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
&& sqlite3_msize(pMem->z) >= pMem->n+1
&& pMem->z[pMem->n]==0
){
pMem->flags |= MEM_Term;
return;
}
}else if( pMem->szMalloc>0 && pMem->szMalloc >= pMem->n+1 ){
pMem->z[pMem->n] = 0;
pMem->flags |= MEM_Term;
return;
}
}
/*
** It is already known that pMem contains an unterminated string.
** Add the zero terminator.
@@ -803,6 +829,7 @@ int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
break;
}
default: {
int rc;
assert( aff==SQLITE_AFF_TEXT );
assert( MEM_Str==(MEM_Blob>>3) );
pMem->flags |= (pMem->flags&MEM_Blob)>>3;
@@ -810,7 +837,9 @@ int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1;
return sqlite3VdbeChangeEncoding(pMem, encoding);
rc = sqlite3VdbeChangeEncoding(pMem, encoding);
if( rc ) return rc;
sqlite3VdbeMemZeroTerminateIfAble(pMem);
}
}
return SQLITE_OK;