/ Check-in [e3fde56d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the blobio.c extension module implementing readblob() and writeblob(). Experimental.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e3fde56da46e9592143b8beeee5eba4d74b8ef67edb7bf73a85edd2e0f7a8d21
User & Date: drh 2019-03-30 17:30:50
Context
2019-03-30
18:39
The defragmentPage() routine detects corruption in the first-free-slot fields at offset 1 in the header and throws an error, rather than asserting. check-in: fb125bd3 user: drh tags: trunk
17:30
Add the blobio.c extension module implementing readblob() and writeblob(). Experimental. check-in: e3fde56d user: drh tags: trunk
17:07
Add an extra IO-error test to windowfault.test. check-in: 5b8c44cd user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added ext/misc/blobio.c.

            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 write 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  +}