]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Updated shell to output blobs in X'1234' form when in "insert" mode. Ticket [72adc99...
authorshane <shane@noemail.net>
Thu, 22 Oct 2009 17:30:15 +0000 (17:30 +0000)
committershane <shane@noemail.net>
Thu, 22 Oct 2009 17:30:15 +0000 (17:30 +0000)
FossilOrigin-Name: a2ad9e6363308b7137fcb1916769151b96933cdb

manifest
manifest.uuid
src/shell.c

index 582759a5094522094f3e20401816764f8a1df101..2200135623d60d42eaed9f37a6c167c2b5519e2d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Add\smarkings\son\stest\sevidence\sfor\sR-30323-21917.
-D 2009-10-22T00:20:18
+C Updated\sshell\sto\soutput\sblobs\sin\sX'1234'\sform\swhen\sin\s"insert"\smode.\s\sTicket\s[72adc99de9].
+D 2009-10-22T17:30:16
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -164,7 +161,7 @@ F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
 F src/resolve.c 3ac31c7181fab03732125fdedf7c2091a5c07f1b
 F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
 F src/select.c cbe366a0ce114856e66f5daf0f848d7c48a88298
-F src/shell.c 9a9fab0d54332c7e20876286dc48a145fd9dd462
+F src/shell.c 47dc8e71891a4b42ce1cff2625f2c88fa1d59a21
 F src/sqlite.h.in 5853e42a4066a6c9c3bf6592a9d57d0012bfdb90
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
 F src/sqliteInt.h 3b00a3ce79e60c5a47c342b738c8b75013f3ec84
@@ -764,14 +761,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 5354ace55f448d10128e2bfe4b904a1441e3bf10
-R b245b9c1f74645196c42f63cc83aa54d
-U drh
-Z 7e2aafe0748c57a887b2da682c0b0c54
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFK36VGoxKgR168RlERAkxbAJ0Rs1ALNw2b4OGeLkxym5lGuB+r5wCfUq2t
-TZYbIm/ITCW5tXtbYNlXCU0=
-=WVSC
------END PGP SIGNATURE-----
+P e51af74c3aeb82604841cc83a490351d1422e838
+R 5e972fea3b82d3b02406cd88c5212c96
+U shane
+Z 205a2d1cb1ef075c240f437a28ecdf29
index 2dd5fb7acf26c09933e2cccb768b598d93e44ca3..f1471d0868cbde9cf0489b4d35e87ce7bda66191 100644 (file)
@@ -1 +1 @@
-e51af74c3aeb82604841cc83a490351d1422e838
\ No newline at end of file
+a2ad9e6363308b7137fcb1916769151b96933cdb
\ No newline at end of file
index 90f933bec549bfb94c90011d392a0a5ced0648d0..b0d71627550abcb7c8700e5e5b4f91c5a2cf4798 100644 (file)
@@ -1259,7 +1259,7 @@ struct previous_mode_data {
 ** state and mode information.
 */
 struct callback_data {
-  sqlite3 *db;            /* The database */
+  sqlite3 *db;           /* The database */
   int echoOn;            /* True to echo input commands */
   int cnt;               /* Number of records displayed so far */
   FILE *out;             /* Write results here */
@@ -1277,6 +1277,7 @@ struct callback_data {
                          ** .explain ON */
   char outfile[FILENAME_MAX]; /* Filename for *out */
   const char *zDbFilename;    /* name of the database file */
+  sqlite3_stmt *pStmt;   /* Current statement if any. */
 };
 
 /*
@@ -1319,6 +1320,17 @@ static int strlen30(const char *z){
   return 0x3fffffff & (int)(z2 - z);
 }
 
+/*
+** Output the given string as a hex-encoded blob (eg. X'1234' )
+*/
+static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
+  int i;
+  char *zBlob = (char *)pBlob;
+  fprintf(out,"X'");
+  for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]); }
+  fprintf(out,"'");
+}
+
 /*
 ** Output the given string as a quoted string using SQL quoting conventions.
 */
@@ -1483,10 +1495,10 @@ static void interrupt_handler(int NotUsed){
 #endif
 
 /*
-** This is the callback routine that the SQLite library
+** This is the callback routine that the shell
 ** invokes for each row of a query result.
 */
-static int callback(void *pArg, int nArg, char **azArg, char **azCol){
+static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
   int i;
   struct callback_data *p = (struct callback_data*)pArg;
   switch( p->mode ){
@@ -1637,6 +1649,11 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
         char *zSep = i>0 ? ",": "";
         if( azArg[i]==0 ){
           fprintf(p->out,"%sNULL",zSep);
+        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
+          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
+          int nBlob = sqlite3_column_bytes(p->pStmt, i);
+          if( zSep[0] ) fprintf(p->out,"%s",zSep);
+          output_hex_blob(p->out, pBlob, nBlob);
         }else if( isNumber(azArg[i], 0) ){
           fprintf(p->out,"%s%s",zSep, azArg[i]);
         }else{
@@ -1651,6 +1668,15 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
   return 0;
 }
 
+/*
+** This is the callback routine that the SQLite library
+** invokes for each row of a query result.
+*/
+static int callback(void *pArg, int nArg, char **azArg, char **azCol){
+  /* since we don't have type info, call the shell_callback with a NULL value */
+  return shell_callback(pArg, nArg, azArg, azCol, NULL);
+}
+
 /*
 ** Set the destination table field of the callback_data structure to
 ** the name of the table given.  Escape any quote characters in the
@@ -1766,6 +1792,133 @@ static int run_table_dump_query(
   return sqlite3_finalize(pSelect);
 }
 
+/*
+** Allocate space and save off current error string.
+*/
+static char *save_err_msg(
+  sqlite3 *db            /* Database to query */
+){
+  int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
+  char *zErrMsg = sqlite3_malloc(nErrMsg);
+  if( zErrMsg ){
+    memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
+  }
+  return zErrMsg;
+}
+
+/*
+** Execute a statement or set of statements.  Print 
+** any result rows/columns depending on the current mode 
+** set via the supplied callback.
+**
+** This is very similar to SQLite's built-in sqlite3_exec() 
+** function except it takes a slightly different callback 
+** and callback data argument.
+*/
+static int shell_exec(
+  sqlite3 *db,                                /* An open database */
+  const char *zSql,                           /* SQL to be evaluated */
+  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
+                                              /* (not the same as sqlite3_exec) */
+  struct callback_data *pArg,                 /* Pointer to struct callback_data */
+  char **pzErrMsg                             /* Error msg written here */
+){
+  sqlite3_stmt *pStmt = NULL;
+  int rc, rc2;
+
+  if( pzErrMsg ){
+    *pzErrMsg = NULL;
+  }
+
+  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+  if( (SQLITE_OK != rc) || !pStmt ){
+    if( pzErrMsg ){
+      *pzErrMsg = save_err_msg(db);
+    }
+  }else{
+    /* perform the first step.  this will tell us if we
+    ** have a result set or not and how wide it is.
+    */
+    rc = sqlite3_step(pStmt);
+    /* if we have a result set... */
+    if( SQLITE_ROW == rc ){
+      /* if callback... */
+      if( xCallback ){
+        /* allocate space for col name ptr, value ptr, and type */
+        int nCol = sqlite3_column_count(pStmt);
+        void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
+        if( !pData ){
+          rc = SQLITE_NOMEM;
+        }else{
+          char **azCols = (char **)pData;      /* Names of result columns */
+          char **azVals = &azCols[nCol];       /* Results */
+          int *aiTypes = (int *)&azVals[nCol]; /* Result types */
+          int i;
+          assert(sizeof(int) <= sizeof(char *)); 
+          /* save off ptrs to column names */
+          for(i=0; i<nCol; i++){
+            azCols[i] = (char *)sqlite3_column_name(pStmt, i);
+          }
+          /* save off the prepared statment handle */
+          if( pArg ){
+            pArg->pStmt = pStmt;
+          }
+          do{
+            /* extract the data and data types */
+            for(i=0; i<nCol; i++){
+              azVals[i] = (char *)sqlite3_column_text(pStmt, i);
+              aiTypes[i] = sqlite3_column_type(pStmt, i);
+              if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
+                rc = SQLITE_NOMEM;
+                break; /* from for */
+              }
+            } /* end for */
+
+            /* if data and types extracted successfully... */
+            if( SQLITE_ROW == rc ){ 
+              /* call the supplied callback with the result row data */
+              if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
+                rc = SQLITE_ABORT;
+              }else{
+                rc = sqlite3_step(pStmt);
+              }
+            }
+          } while( SQLITE_ROW == rc );
+          sqlite3_free(pData);
+          if( pArg ){
+            pArg->pStmt = NULL;
+          }
+        }
+      }else{
+        do{
+          rc = sqlite3_step(pStmt);
+        } while( rc == SQLITE_ROW );
+      }
+    }
+
+    /* if the last sqlite3_step() didn't complete successfully... */
+    if( (SQLITE_OK != rc) && (SQLITE_DONE != rc) ){ 
+      if( pzErrMsg ){
+        *pzErrMsg = save_err_msg(db);
+      }
+    }else{
+      rc = SQLITE_OK;
+    }
+
+    rc2 = sqlite3_finalize(pStmt);
+    /* if the last sqlite3_finalize() didn't complete successfully 
+    ** AND we don't have a save error from sqlite3_step ... */
+    if( (SQLITE_OK != rc2) && (SQLITE_OK == rc) ){
+      rc = rc2;
+      if( pzErrMsg ){
+        *pzErrMsg = save_err_msg(db);
+      }
+    }
+  }
+
+  return rc;
+}
+
 
 /*
 ** This is a different callback routine used for dumping the database.
@@ -2910,7 +3063,7 @@ static int process_input(struct callback_data *p, FILE *in){
       p->cnt = 0;
       open_db(p);
       BEGIN_TIMER;
-      rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
+      rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
       END_TIMER;
       if( rc || zErrMsg ){
         char zPrefix[100];
@@ -3229,7 +3382,7 @@ int main(int argc, char **argv){
     }else{
       int rc;
       open_db(&data);
-      rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
+      rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg);
       if( rc!=0 && zErrMsg!=0 ){
         fprintf(stderr,"SQL error: %s\n", zErrMsg);
         exit(1);