xref: /sqlite-3.40.0/ext/misc/blobio.c (revision 0a0e89fa)
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 
readblobFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)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 
writeblobFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)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
sqlite3_blobio_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)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