From: drh Date: Sat, 30 Mar 2019 17:30:50 +0000 (+0000) Subject: Add the blobio.c extension module implementing readblob() and writeblob(). X-Git-Tag: version-3.28.0~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2c794b15a0704dabe5be9265ff77f67f35b9c24d;p=thirdparty%2Fsqlite.git Add the blobio.c extension module implementing readblob() and writeblob(). Experimental. FossilOrigin-Name: e3fde56da46e9592143b8beeee5eba4d74b8ef67edb7bf73a85edd2e0f7a8d21 --- diff --git a/ext/misc/blobio.c b/ext/misc/blobio.c new file mode 100644 index 0000000000..65ca467e3a --- /dev/null +++ b/ext/misc/blobio.c @@ -0,0 +1,152 @@ +/* +** 2019-03-30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** An SQL function that uses the incremental BLOB I/O mechanism of SQLite +** to read or write part of a blob. This is intended for debugging use +** in the CLI. +** +** readblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,N) +** +** Returns N bytes of the blob starting at OFFSET. +** +** writeblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,NEWDATA) +** +** NEWDATA must be a blob. The content of NEWDATA overwrites the +** existing BLOB data at SCHEMA.TABLE.COLUMN for row ROWID beginning +** at OFFSET bytes into the blob. +*/ +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#include +#include + +static void readblobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_blob *pBlob = 0; + const char *zSchema; + const char *zTable; + const char *zColumn; + sqlite3_int64 iRowid; + int iOfst; + unsigned char *aData; + int nData; + sqlite3 *db; + int rc; + + zSchema = (const char*)sqlite3_value_text(argv[0]); + zTable = (const char*)sqlite3_value_text(argv[1]); + if( zTable==0 ){ + sqlite3_result_error(context, "bad table name", -1); + return; + } + zColumn = (const char*)sqlite3_value_text(argv[2]); + if( zTable==0 ){ + sqlite3_result_error(context, "bad column name", -1); + return; + } + iRowid = sqlite3_value_int64(argv[3]); + iOfst = sqlite3_value_int(argv[4]); + nData = sqlite3_value_int(argv[5]); + if( nData<=0 ) return; + aData = sqlite3_malloc64( nData+1 ); + if( aData==0 ){ + sqlite3_result_error_nomem(context); + return; + } + db = sqlite3_context_db_handle(context); + rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 0, &pBlob); + if( rc ){ + sqlite3_free(aData); + sqlite3_result_error(context, "cannot open BLOB pointer", -1); + return; + } + rc = sqlite3_blob_read(pBlob, aData, nData, iOfst); + sqlite3_blob_close(pBlob); + if( rc ){ + sqlite3_free(aData); + sqlite3_result_error(context, "BLOB write failed", -1); + }else{ + sqlite3_result_blob(context, aData, nData, sqlite3_free); + } +} + +static void writeblobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_blob *pBlob = 0; + const char *zSchema; + const char *zTable; + const char *zColumn; + sqlite3_int64 iRowid; + int iOfst; + unsigned char *aData; + int nData; + sqlite3 *db; + int rc; + + zSchema = (const char*)sqlite3_value_text(argv[0]); + zTable = (const char*)sqlite3_value_text(argv[1]); + if( zTable==0 ){ + sqlite3_result_error(context, "bad table name", -1); + return; + } + zColumn = (const char*)sqlite3_value_text(argv[2]); + if( zTable==0 ){ + sqlite3_result_error(context, "bad column name", -1); + return; + } + iRowid = sqlite3_value_int64(argv[3]); + iOfst = sqlite3_value_int(argv[4]); + if( sqlite3_value_type(argv[5])!=SQLITE_BLOB ){ + sqlite3_result_error(context, "6th argument must be a BLOB", -1); + return; + } + nData = sqlite3_value_bytes(argv[5]); + aData = (unsigned char *)sqlite3_value_blob(argv[5]); + db = sqlite3_context_db_handle(context); + rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 1, &pBlob); + if( rc ){ + sqlite3_result_error(context, "cannot open BLOB pointer", -1); + return; + } + rc = sqlite3_blob_write(pBlob, aData, nData, iOfst); + sqlite3_blob_close(pBlob); + if( rc ){ + sqlite3_result_error(context, "BLOB write failed", -1); + } +} + + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_blobio_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "readblob", 6, SQLITE_UTF8, 0, + readblobFunc, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "writeblob", 6, SQLITE_UTF8, 0, + writeblobFunc, 0, 0); + } + return rc; +} diff --git a/manifest b/manifest index 33e41e24f5..5219d533a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sextra\sIO-error\stest\sto\swindowfault.test. -D 2019-03-30T17:07:23.564 +C Add\sthe\sblobio.c\sextension\smodule\simplementing\sreadblob()\sand\swriteblob().\nExperimental. +D 2019-03-30T17:30:50.464 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -277,6 +277,7 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23 F ext/misc/amatch.c 50a9ef2d38dabfa371f8c1904097d493271e63d58ccb0e9b79a4fa4a94e66660 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 +F ext/misc/blobio.c 085bbfa57ea58bb15d994ba4cd397bff6f0c38c4f618adbc62cf4d3780e5d88a F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243 @@ -1813,7 +1814,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c2edbf3b8c643edcd5823eb907fd7531cf5be8a8b6a014fa1b123eb0ea3231cf -R 86d53f0a0cd55849b6bfbfc0814c8bf0 -U dan -Z 7c8bdcb225b3e1ae6999bd7e018164b5 +P 5b8c44cd39c529e8adbc51f67088409e963515b988868856120a59e6c7160210 +R 34637151831985d0fc29dd4ea445150f +U drh +Z 97f8c049c6327eff8377c297f32c8976 diff --git a/manifest.uuid b/manifest.uuid index f057f0ba06..fe43a957fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5b8c44cd39c529e8adbc51f67088409e963515b988868856120a59e6c7160210 \ No newline at end of file +e3fde56da46e9592143b8beeee5eba4d74b8ef67edb7bf73a85edd2e0f7a8d21 \ No newline at end of file