From: shane Date: Thu, 22 Oct 2009 17:30:15 +0000 (+0000) Subject: Updated shell to output blobs in X'1234' form when in "insert" mode. Ticket [72adc99... X-Git-Tag: fts3-refactor~68 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=626a6e4aa25717ca24d16e0e13304561b39062a4;p=thirdparty%2Fsqlite.git Updated shell to output blobs in X'1234' form when in "insert" mode. Ticket [72adc99de9]. FossilOrigin-Name: a2ad9e6363308b7137fcb1916769151b96933cdb --- diff --git a/manifest b/manifest index 582759a509..2200135623 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 2dd5fb7acf..f1471d0868 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e51af74c3aeb82604841cc83a490351d1422e838 \ No newline at end of file +a2ad9e6363308b7137fcb1916769151b96933cdb \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 90f933bec5..b0d7162755 100644 --- a/src/shell.c +++ b/src/shell.c @@ -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; imode ){ @@ -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; ipStmt = pStmt; + } + do{ + /* extract the data and data types */ + for(i=0; ipStmt = 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);