mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-03 16:53:36 +03:00
Updated shell to output blobs in X'1234' form when in "insert" mode. Ticket [72adc99de9].
FossilOrigin-Name: a2ad9e6363308b7137fcb1916769151b96933cdb
This commit is contained in:
24
manifest
24
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
e51af74c3aeb82604841cc83a490351d1422e838
|
||||
a2ad9e6363308b7137fcb1916769151b96933cdb
|
||||
161
src/shell.c
161
src/shell.c
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user