#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <zlib.h>
#include <assert.h>
static void sqlarCompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
const Bytef *pData = sqlite3_value_blob(argv[0]);
uLong nData = sqlite3_value_bytes(argv[0]);
uLongf nOut = compressBound(nData);
Bytef *pOut;
pOut = (Bytef*)sqlite3_malloc(nOut);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
return;
}else{
if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
sqlite3_result_error(context, "error in compress()", -1);
}else if( nOut<nData ){
sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
}else{
sqlite3_result_value(context, argv[0]);
}
sqlite3_free(pOut);
}
}else{
sqlite3_result_value(context, argv[0]);
}
}
static void sqlarUncompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
uLong nData;
uLongf sz;
assert( argc==2 );
sz = sqlite3_value_int(argv[1]);
if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
sqlite3_result_value(context, argv[0]);
}else{
const Bytef *pData= sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
}else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}else{
sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
}
sqlite3_free(pOut);
}
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_sqlar_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg;
rc = sqlite3_create_function(db, "sqlar_compress", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
sqlarCompressFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
sqlarUncompressFunc, 0, 0);
}
return rc;
}