Fossil SCM
Add built-in compress() and decompress() functions to the SQLite shell command.
Commit
91d648426ad81174ce31405c2b8acc96ca3090dd
Parent
b75bb1dc16bef8f…
1 file changed
+59
+59
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -20,10 +20,11 @@ | ||
| 20 | 20 | ** is a copy of the "shell.c" code from SQLite. This file contains logic |
| 21 | 21 | ** to initialize the code in shell.c. |
| 22 | 22 | */ |
| 23 | 23 | #include "config.h" |
| 24 | 24 | #include "sqlcmd.h" |
| 25 | +#include <zlib.h> | |
| 25 | 26 | |
| 26 | 27 | /* |
| 27 | 28 | ** Implementation of the "content(X)" SQL function. Return the complete |
| 28 | 29 | ** content of artifact identified by X as a blob. |
| 29 | 30 | */ |
| @@ -46,10 +47,64 @@ | ||
| 46 | 47 | sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx), |
| 47 | 48 | SQLITE_TRANSIENT); |
| 48 | 49 | blob_reset(&cx); |
| 49 | 50 | } |
| 50 | 51 | } |
| 52 | + | |
| 53 | +/* | |
| 54 | +** Implementation of the "compress(X)" SQL function. The input X is | |
| 55 | +** compressed using zLib and the output is returned. | |
| 56 | +*/ | |
| 57 | +static void sqlcmd_compress( | |
| 58 | + sqlite3_context *context, | |
| 59 | + int argc, | |
| 60 | + sqlite3_value **argv | |
| 61 | +){ | |
| 62 | + const unsigned char *pIn; | |
| 63 | + unsigned char *pOut; | |
| 64 | + unsigned int nIn; | |
| 65 | + unsigned long int nOut; | |
| 66 | + | |
| 67 | + pIn = sqlite3_value_blob(argv[0]); | |
| 68 | + nIn = sqlite3_value_bytes(argv[0]); | |
| 69 | + nOut = 13 + nIn + (nIn+999)/1000; | |
| 70 | + pOut = sqlite3_malloc( nOut+4 ); | |
| 71 | + pOut[0] = nIn>>24 & 0xff; | |
| 72 | + pOut[1] = nIn>>16 & 0xff; | |
| 73 | + pOut[2] = nIn>>8 & 0xff; | |
| 74 | + pOut[3] = nIn & 0xff; | |
| 75 | + compress(&pOut[4], &nOut, pIn, nIn); | |
| 76 | + sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free); | |
| 77 | +} | |
| 78 | + | |
| 79 | +/* | |
| 80 | +** Implementation of the "uncontent(X)" SQL function. The argument X | |
| 81 | +** is a blob which was obtained from compress(Y). The output will be | |
| 82 | +** the value Y. | |
| 83 | +*/ | |
| 84 | +static void sqlcmd_decompress( | |
| 85 | + sqlite3_context *context, | |
| 86 | + int argc, | |
| 87 | + sqlite3_value **argv | |
| 88 | +){ | |
| 89 | + const unsigned char *pIn; | |
| 90 | + unsigned char *pOut; | |
| 91 | + unsigned int nIn; | |
| 92 | + unsigned long int nOut; | |
| 93 | + int rc; | |
| 94 | + | |
| 95 | + pIn = sqlite3_value_blob(argv[0]); | |
| 96 | + nIn = sqlite3_value_bytes(argv[0]); | |
| 97 | + nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; | |
| 98 | + pOut = sqlite3_malloc( nOut+1 ); | |
| 99 | + rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); | |
| 100 | + if( rc==Z_OK ){ | |
| 101 | + sqlite3_result_blob(context, pOut, nOut, sqlite3_free); | |
| 102 | + }else{ | |
| 103 | + sqlite3_result_error(context, "input is not zlib compressed", -1); | |
| 104 | + } | |
| 105 | +} | |
| 51 | 106 | |
| 52 | 107 | /* |
| 53 | 108 | ** This is the "automatic extensionn" initializer that runs right after |
| 54 | 109 | ** the connection to the repository database is opened. Set up the |
| 55 | 110 | ** database connection to be more useful to the human operator. |
| @@ -59,10 +114,14 @@ | ||
| 59 | 114 | const char **pzErrMsg, |
| 60 | 115 | const void *notUsed |
| 61 | 116 | ){ |
| 62 | 117 | sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0, |
| 63 | 118 | sqlcmd_content, 0, 0); |
| 119 | + sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, | |
| 120 | + sqlcmd_compress, 0, 0); | |
| 121 | + sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, | |
| 122 | + sqlcmd_decompress, 0, 0); | |
| 64 | 123 | return SQLITE_OK; |
| 65 | 124 | } |
| 66 | 125 | |
| 67 | 126 | |
| 68 | 127 | /* |
| 69 | 128 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -20,10 +20,11 @@ | |
| 20 | ** is a copy of the "shell.c" code from SQLite. This file contains logic |
| 21 | ** to initialize the code in shell.c. |
| 22 | */ |
| 23 | #include "config.h" |
| 24 | #include "sqlcmd.h" |
| 25 | |
| 26 | /* |
| 27 | ** Implementation of the "content(X)" SQL function. Return the complete |
| 28 | ** content of artifact identified by X as a blob. |
| 29 | */ |
| @@ -46,10 +47,64 @@ | |
| 46 | sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx), |
| 47 | SQLITE_TRANSIENT); |
| 48 | blob_reset(&cx); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | /* |
| 53 | ** This is the "automatic extensionn" initializer that runs right after |
| 54 | ** the connection to the repository database is opened. Set up the |
| 55 | ** database connection to be more useful to the human operator. |
| @@ -59,10 +114,14 @@ | |
| 59 | const char **pzErrMsg, |
| 60 | const void *notUsed |
| 61 | ){ |
| 62 | sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0, |
| 63 | sqlcmd_content, 0, 0); |
| 64 | return SQLITE_OK; |
| 65 | } |
| 66 | |
| 67 | |
| 68 | /* |
| 69 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -20,10 +20,11 @@ | |
| 20 | ** is a copy of the "shell.c" code from SQLite. This file contains logic |
| 21 | ** to initialize the code in shell.c. |
| 22 | */ |
| 23 | #include "config.h" |
| 24 | #include "sqlcmd.h" |
| 25 | #include <zlib.h> |
| 26 | |
| 27 | /* |
| 28 | ** Implementation of the "content(X)" SQL function. Return the complete |
| 29 | ** content of artifact identified by X as a blob. |
| 30 | */ |
| @@ -46,10 +47,64 @@ | |
| 47 | sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx), |
| 48 | SQLITE_TRANSIENT); |
| 49 | blob_reset(&cx); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | /* |
| 54 | ** Implementation of the "compress(X)" SQL function. The input X is |
| 55 | ** compressed using zLib and the output is returned. |
| 56 | */ |
| 57 | static void sqlcmd_compress( |
| 58 | sqlite3_context *context, |
| 59 | int argc, |
| 60 | sqlite3_value **argv |
| 61 | ){ |
| 62 | const unsigned char *pIn; |
| 63 | unsigned char *pOut; |
| 64 | unsigned int nIn; |
| 65 | unsigned long int nOut; |
| 66 | |
| 67 | pIn = sqlite3_value_blob(argv[0]); |
| 68 | nIn = sqlite3_value_bytes(argv[0]); |
| 69 | nOut = 13 + nIn + (nIn+999)/1000; |
| 70 | pOut = sqlite3_malloc( nOut+4 ); |
| 71 | pOut[0] = nIn>>24 & 0xff; |
| 72 | pOut[1] = nIn>>16 & 0xff; |
| 73 | pOut[2] = nIn>>8 & 0xff; |
| 74 | pOut[3] = nIn & 0xff; |
| 75 | compress(&pOut[4], &nOut, pIn, nIn); |
| 76 | sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free); |
| 77 | } |
| 78 | |
| 79 | /* |
| 80 | ** Implementation of the "uncontent(X)" SQL function. The argument X |
| 81 | ** is a blob which was obtained from compress(Y). The output will be |
| 82 | ** the value Y. |
| 83 | */ |
| 84 | static void sqlcmd_decompress( |
| 85 | sqlite3_context *context, |
| 86 | int argc, |
| 87 | sqlite3_value **argv |
| 88 | ){ |
| 89 | const unsigned char *pIn; |
| 90 | unsigned char *pOut; |
| 91 | unsigned int nIn; |
| 92 | unsigned long int nOut; |
| 93 | int rc; |
| 94 | |
| 95 | pIn = sqlite3_value_blob(argv[0]); |
| 96 | nIn = sqlite3_value_bytes(argv[0]); |
| 97 | nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; |
| 98 | pOut = sqlite3_malloc( nOut+1 ); |
| 99 | rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); |
| 100 | if( rc==Z_OK ){ |
| 101 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 102 | }else{ |
| 103 | sqlite3_result_error(context, "input is not zlib compressed", -1); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /* |
| 108 | ** This is the "automatic extensionn" initializer that runs right after |
| 109 | ** the connection to the repository database is opened. Set up the |
| 110 | ** database connection to be more useful to the human operator. |
| @@ -59,10 +114,14 @@ | |
| 114 | const char **pzErrMsg, |
| 115 | const void *notUsed |
| 116 | ){ |
| 117 | sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0, |
| 118 | sqlcmd_content, 0, 0); |
| 119 | sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, |
| 120 | sqlcmd_compress, 0, 0); |
| 121 | sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, |
| 122 | sqlcmd_decompress, 0, 0); |
| 123 | return SQLITE_OK; |
| 124 | } |
| 125 | |
| 126 | |
| 127 | /* |
| 128 |