1 /* 2 ** 2017-12-17 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful 14 ** for working with sqlar archives and used by the shell tool's built-in 15 ** sqlar support. 16 */ 17 #include "sqlite3ext.h" 18 SQLITE_EXTENSION_INIT1 19 #include <zlib.h> 20 #include <assert.h> 21 22 /* 23 ** Implementation of the "sqlar_compress(X)" SQL function. 24 ** 25 ** If the type of X is SQLITE_BLOB, and compressing that blob using 26 ** zlib utility function compress() yields a smaller blob, return the 27 ** compressed blob. Otherwise, return a copy of X. 28 ** 29 ** SQLar uses the "zlib format" for compressed content. The zlib format 30 ** contains a two-byte identification header and a four-byte checksum at 31 ** the end. This is different from ZIP which uses the raw deflate format. 32 ** 33 ** Future enhancements to SQLar might add support for new compression formats. 34 ** If so, those new formats will be identified by alternative headers in the 35 ** compressed data. 36 */ 37 static void sqlarCompressFunc( 38 sqlite3_context *context, 39 int argc, 40 sqlite3_value **argv 41 ){ 42 assert( argc==1 ); 43 if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ 44 const Bytef *pData = sqlite3_value_blob(argv[0]); 45 uLong nData = sqlite3_value_bytes(argv[0]); 46 uLongf nOut = compressBound(nData); 47 Bytef *pOut; 48 49 pOut = (Bytef*)sqlite3_malloc(nOut); 50 if( pOut==0 ){ 51 sqlite3_result_error_nomem(context); 52 return; 53 }else{ 54 if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ 55 sqlite3_result_error(context, "error in compress()", -1); 56 }else if( nOut<nData ){ 57 sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT); 58 }else{ 59 sqlite3_result_value(context, argv[0]); 60 } 61 sqlite3_free(pOut); 62 } 63 }else{ 64 sqlite3_result_value(context, argv[0]); 65 } 66 } 67 68 /* 69 ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function 70 ** 71 ** Parameter SZ is interpreted as an integer. If it is less than or 72 ** equal to zero, then this function returns a copy of X. Or, if 73 ** SZ is equal to the size of X when interpreted as a blob, also 74 ** return a copy of X. Otherwise, decompress blob X using zlib 75 ** utility function uncompress() and return the results (another 76 ** blob). 77 */ 78 static void sqlarUncompressFunc( 79 sqlite3_context *context, 80 int argc, 81 sqlite3_value **argv 82 ){ 83 uLong nData; 84 uLongf sz; 85 86 assert( argc==2 ); 87 sz = sqlite3_value_int(argv[1]); 88 89 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ 90 sqlite3_result_value(context, argv[0]); 91 }else{ 92 const Bytef *pData= sqlite3_value_blob(argv[0]); 93 Bytef *pOut = sqlite3_malloc(sz); 94 if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ 95 sqlite3_result_error(context, "error in uncompress()", -1); 96 }else{ 97 sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); 98 } 99 sqlite3_free(pOut); 100 } 101 } 102 103 104 #ifdef _WIN32 105 __declspec(dllexport) 106 #endif 107 int sqlite3_sqlar_init( 108 sqlite3 *db, 109 char **pzErrMsg, 110 const sqlite3_api_routines *pApi 111 ){ 112 int rc = SQLITE_OK; 113 SQLITE_EXTENSION_INIT2(pApi); 114 (void)pzErrMsg; /* Unused parameter */ 115 rc = sqlite3_create_function(db, "sqlar_compress", 1, 116 SQLITE_UTF8|SQLITE_INNOCUOUS, 0, 117 sqlarCompressFunc, 0, 0); 118 if( rc==SQLITE_OK ){ 119 rc = sqlite3_create_function(db, "sqlar_uncompress", 2, 120 SQLITE_UTF8|SQLITE_INNOCUOUS, 0, 121 sqlarUncompressFunc, 0, 0); 122 } 123 return rc; 124 } 125