1 /* 2 ** 2019-03-30 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 ** An SQL function that uses the incremental BLOB I/O mechanism of SQLite 14 ** to read or write part of a blob. This is intended for debugging use 15 ** in the CLI. 16 ** 17 ** readblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,N) 18 ** 19 ** Returns N bytes of the blob starting at OFFSET. 20 ** 21 ** writeblob(SCHEMA,TABLE,COLUMN,ROWID,OFFSET,NEWDATA) 22 ** 23 ** NEWDATA must be a blob. The content of NEWDATA overwrites the 24 ** existing BLOB data at SCHEMA.TABLE.COLUMN for row ROWID beginning 25 ** at OFFSET bytes into the blob. 26 */ 27 #include "sqlite3ext.h" 28 SQLITE_EXTENSION_INIT1 29 #include <assert.h> 30 #include <string.h> 31 32 static void readblobFunc( 33 sqlite3_context *context, 34 int argc, 35 sqlite3_value **argv 36 ){ 37 sqlite3_blob *pBlob = 0; 38 const char *zSchema; 39 const char *zTable; 40 const char *zColumn; 41 sqlite3_int64 iRowid; 42 int iOfst; 43 unsigned char *aData; 44 int nData; 45 sqlite3 *db; 46 int rc; 47 48 zSchema = (const char*)sqlite3_value_text(argv[0]); 49 zTable = (const char*)sqlite3_value_text(argv[1]); 50 if( zTable==0 ){ 51 sqlite3_result_error(context, "bad table name", -1); 52 return; 53 } 54 zColumn = (const char*)sqlite3_value_text(argv[2]); 55 if( zTable==0 ){ 56 sqlite3_result_error(context, "bad column name", -1); 57 return; 58 } 59 iRowid = sqlite3_value_int64(argv[3]); 60 iOfst = sqlite3_value_int(argv[4]); 61 nData = sqlite3_value_int(argv[5]); 62 if( nData<=0 ) return; 63 aData = sqlite3_malloc64( nData+1 ); 64 if( aData==0 ){ 65 sqlite3_result_error_nomem(context); 66 return; 67 } 68 db = sqlite3_context_db_handle(context); 69 rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 0, &pBlob); 70 if( rc ){ 71 sqlite3_free(aData); 72 sqlite3_result_error(context, "cannot open BLOB pointer", -1); 73 return; 74 } 75 rc = sqlite3_blob_read(pBlob, aData, nData, iOfst); 76 sqlite3_blob_close(pBlob); 77 if( rc ){ 78 sqlite3_free(aData); 79 sqlite3_result_error(context, "BLOB read failed", -1); 80 }else{ 81 sqlite3_result_blob(context, aData, nData, sqlite3_free); 82 } 83 } 84 85 static void writeblobFunc( 86 sqlite3_context *context, 87 int argc, 88 sqlite3_value **argv 89 ){ 90 sqlite3_blob *pBlob = 0; 91 const char *zSchema; 92 const char *zTable; 93 const char *zColumn; 94 sqlite3_int64 iRowid; 95 int iOfst; 96 unsigned char *aData; 97 int nData; 98 sqlite3 *db; 99 int rc; 100 101 zSchema = (const char*)sqlite3_value_text(argv[0]); 102 zTable = (const char*)sqlite3_value_text(argv[1]); 103 if( zTable==0 ){ 104 sqlite3_result_error(context, "bad table name", -1); 105 return; 106 } 107 zColumn = (const char*)sqlite3_value_text(argv[2]); 108 if( zTable==0 ){ 109 sqlite3_result_error(context, "bad column name", -1); 110 return; 111 } 112 iRowid = sqlite3_value_int64(argv[3]); 113 iOfst = sqlite3_value_int(argv[4]); 114 if( sqlite3_value_type(argv[5])!=SQLITE_BLOB ){ 115 sqlite3_result_error(context, "6th argument must be a BLOB", -1); 116 return; 117 } 118 nData = sqlite3_value_bytes(argv[5]); 119 aData = (unsigned char *)sqlite3_value_blob(argv[5]); 120 db = sqlite3_context_db_handle(context); 121 rc = sqlite3_blob_open(db, zSchema, zTable, zColumn, iRowid, 1, &pBlob); 122 if( rc ){ 123 sqlite3_result_error(context, "cannot open BLOB pointer", -1); 124 return; 125 } 126 rc = sqlite3_blob_write(pBlob, aData, nData, iOfst); 127 sqlite3_blob_close(pBlob); 128 if( rc ){ 129 sqlite3_result_error(context, "BLOB write failed", -1); 130 } 131 } 132 133 134 #ifdef _WIN32 135 __declspec(dllexport) 136 #endif 137 int sqlite3_blobio_init( 138 sqlite3 *db, 139 char **pzErrMsg, 140 const sqlite3_api_routines *pApi 141 ){ 142 int rc = SQLITE_OK; 143 SQLITE_EXTENSION_INIT2(pApi); 144 (void)pzErrMsg; /* Unused parameter */ 145 rc = sqlite3_create_function(db, "readblob", 6, SQLITE_UTF8, 0, 146 readblobFunc, 0, 0); 147 if( rc==SQLITE_OK ){ 148 rc = sqlite3_create_function(db, "writeblob", 6, SQLITE_UTF8, 0, 149 writeblobFunc, 0, 0); 150 } 151 return rc; 152 } 153