1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Extend the carray extension to allow the use of BLOB values to be bound

as an array of "struct iovec" objects.

FossilOrigin-Name: e117a03ca6560e958884f277db827c51ae337a970c17143a0a5f9b150f52f87a
This commit is contained in:
drh
2023-01-20 21:00:03 +00:00
parent 42d652c047
commit a96cd076fe
5 changed files with 145 additions and 48 deletions

View File

@ -28,7 +28,7 @@
**
** There is an optional third parameter to determine the datatype of
** the C-language array. Allowed values of the third parameter are
** 'int32', 'int64', 'double', 'char*'. Example:
** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example:
**
** SELECT * FROM carray($ptr,10,'char*');
**
@ -56,6 +56,14 @@
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#ifdef _WIN32
struct iovec {
void *iov_base;
size_t iov_len;
};
#else
# include <sys/uio.h>
#endif
/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
** Must exactly match the definitions in carray.h.
@ -65,6 +73,7 @@ SQLITE_EXTENSION_INIT1
# define CARRAY_INT64 1 /* Data is 64-bit signed integers */
# define CARRAY_DOUBLE 2 /* Data is doubles */
# define CARRAY_TEXT 3 /* Data is char* */
# define CARRAY_BLOB 4 /* Data is struct iovec* */
#endif
#ifndef SQLITE_API
@ -80,7 +89,8 @@ SQLITE_EXTENSION_INIT1
/*
** Names of allowed datatypes
*/
static const char *azType[] = { "int32", "int64", "double", "char*" };
static const char *azType[] = { "int32", "int64", "double", "char*",
"struct iovec" };
/*
** Structure used to hold the sqlite3_carray_bind() information
@ -224,6 +234,12 @@ static int carrayColumn(
sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
return SQLITE_OK;
}
case CARRAY_BLOB: {
const struct iovec *p = (struct iovec*)pCur->pPtr;
sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base,
(int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT);
return SQLITE_OK;
}
}
}
}
@ -268,7 +284,7 @@ static int carrayFilter(
if( pBind==0 ) break;
pCur->pPtr = pBind->aData;
pCur->iCnt = pBind->nData;
pCur->eType = pBind->mFlags & 0x03;
pCur->eType = pBind->mFlags & 0x07;
break;
}
case 2:
@ -431,24 +447,29 @@ SQLITE_API int sqlite3_carray_bind(
pNew->mFlags = mFlags;
if( xDestroy==SQLITE_TRANSIENT ){
sqlite3_int64 sz = nData;
switch( mFlags & 0x03 ){
case CARRAY_INT32: sz *= 4; break;
case CARRAY_INT64: sz *= 8; break;
case CARRAY_DOUBLE: sz *= 8; break;
case CARRAY_TEXT: sz *= sizeof(char*); break;
switch( mFlags & 0x07 ){
case CARRAY_INT32: sz *= 4; break;
case CARRAY_INT64: sz *= 8; break;
case CARRAY_DOUBLE: sz *= 8; break;
case CARRAY_TEXT: sz *= sizeof(char*); break;
case CARRAY_BLOB: sz *= sizeof(struct iovec); break;
}
if( (mFlags & 0x03)==CARRAY_TEXT ){
if( (mFlags & 0x07)==CARRAY_TEXT ){
for(i=0; i<nData; i++){
const char *z = ((char**)aData)[i];
if( z ) sz += strlen(z) + 1;
}
}else if( (mFlags & 0x07)==CARRAY_BLOB ){
for(i=0; i<nData; i++){
sz += ((struct iovec*)aData)[i].iov_len;
}
}
pNew->aData = sqlite3_malloc64( sz );
if( pNew->aData==0 ){
sqlite3_free(pNew);
return SQLITE_NOMEM;
}
if( (mFlags & 0x03)==CARRAY_TEXT ){
if( (mFlags & 0x07)==CARRAY_TEXT ){
char **az = (char**)pNew->aData;
char *z = (char*)&az[nData];
for(i=0; i<nData; i++){
@ -463,6 +484,16 @@ SQLITE_API int sqlite3_carray_bind(
memcpy(z, zData, n+1);
z += n+1;
}
}else if( (mFlags & 0x07)==CARRAY_BLOB ){
struct iovec *p = (struct iovec*)pNew->aData;
unsigned char *z = (unsigned char*)&p[nData];
for(i=0; i<nData; i++){
size_t n = ((struct iovec*)aData)[i].iov_len;
p[i].iov_len = n;
p[i].iov_base = z;
z += n;
memcpy(p[i].iov_base, ((struct iovec*)aData)[i].iov_base, n);
}
}else{
memcpy(pNew->aData, aData, sz);
}