From 28bd4bcc173909a9e96b7d586ed01065b6626ced Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 15 Jun 2000 15:57:22 +0000 Subject: [PATCH] :-) (CVS 98) FossilOrigin-Name: f26d0cdf45221a8fc97253c2a1939e79ae866fc9 --- manifest | 12 +++--- manifest.uuid | 2 +- src/shell.c | 110 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index 39462531aa..58254a2b1c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C :-)\s(CVS\s97) -D 2000-06-15T11:32:11 +C :-)\s(CVS\s98) +D 2000-06-15T15:57:23 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 F Makefile.in 4dc16840f68e3b599915e1ec8463d365474dd286 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 @@ -15,7 +15,7 @@ F src/insert.c ac4edfff474589c00b2490f206317dc5822122e5 F src/main.c e3297835b8e38ca726ac73f2c2bdb7cf08103197 F src/parse.y 6a3085fd8e2c477e73468e6d1a278cb72254c0c9 F src/select.c 3a12d76074fa57d7c39c4436bdeb8d7e1eb6fdf4 -F src/shell.c 3f4afc39a36e4824e8aa262623fd03568874799e +F src/shell.c 082feaeb8815c0521b6dfad451aefddb98b694f2 F src/sqlite.h 58da0a8590133777b741f9836beaef3d58f40268 F src/sqliteInt.h 19954bd2f75632849b265b9d7163a67391ec5148 F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7 @@ -64,7 +64,7 @@ F www/index.tcl 4116afce6a8c63d68882d2b00aa10b079e0129cd F www/lang.tcl 1645e9107d75709be4c6099b643db235bbe0a151 F www/opcode.tcl 3cdc4bb2515fcfcbe853e3f0c91cd9199e82dadd F www/sqlite.tcl 5420eab24b539928f80ea9b3088e2549d34f438d -P 36c2b059ac1092c7a260f527bba261daa4ff9f9f -R 9ebeaa4117ae6d1f63e342cce69944f3 +P 3b9689cc35acd3008ca32b6b9882f4e625381c6e +R d21be2d1bea392ba1ec68d7cba7fe995 U drh -Z 00f67aee729de2889d8b3b227291a2ee +Z 5039ec205aa1fc0411a39151197585a9 diff --git a/manifest.uuid b/manifest.uuid index 50b486572a..5c60b3ebff 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3b9689cc35acd3008ca32b6b9882f4e625381c6e \ No newline at end of file +f26d0cdf45221a8fc97253c2a1939e79ae866fc9 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index da0f1e69bf..f1fc9f58c0 100644 --- a/src/shell.c +++ b/src/shell.c @@ -24,7 +24,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.12 2000/06/07 02:04:23 drh Exp $ +** $Id: shell.c,v 1.13 2000/06/15 15:57:23 drh Exp $ */ #include #include @@ -122,14 +122,15 @@ static char *one_input_line(const char *zPrior, int isatty){ ** state and mode information. */ struct callback_data { - sqlite *db; /* The database */ - int cnt; /* Number of records displayed so far */ - FILE *out; /* Write results here */ - int mode; /* An output mode setting */ - int showHeader; /* True to show column names in List or Column mode */ - int escape; /* Escape this character when in MODE_List */ - char separator[20];/* Separator character for MODE_List */ - int colWidth[30]; /* Width of each column when in column mode */ + sqlite *db; /* The database */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ + int mode; /* An output mode setting */ + int showHeader; /* True to show column names in List or Column mode */ + int escape; /* Escape this character when in MODE_List */ + char zDestTable[250]; /* Name of destination table when MODE_Insert */ + char separator[20]; /* Separator character for MODE_List */ + int colWidth[30]; /* Width of each column when in column mode */ }; /* @@ -139,12 +140,71 @@ struct callback_data { #define MODE_Column 1 /* One record per line in neat columns */ #define MODE_List 2 /* One record per line with a separator */ #define MODE_Html 3 /* Generate an XHTML table */ +#define MODE_Insert 4 /* Generate SQL "insert" statements */ /* ** Number of elements in an array */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) +/* +** Return TRUE if the string supplied is a number of some kinds. +*/ +static int is_numeric(const char *z){ + int seen_digit = 0; + if( *z=='-' || *z=='+' ){ + z++; + } + while( isdigit(*z) ){ + seen_digit = 1; + z++; + } + if( seen_digit && *z=='.' ){ + z++; + while( isdigit(*z) ){ z++; } + } + if( seen_digit && (*z=='e' || *z=='E') + && (isdigit(z[1]) || ((z[1]=='-' || z[1]=='+') && isdigit(z[2]))) + ){ + z+=2; + while( isdigit(*z) ){ z++; } + } + return seen_digit && *z==0; +} + +/* +** Output the given string as a quoted string using SQL quoting conventions. +*/ +static void output_quoted_string(FILE *out, const char *z){ + int i; + int nSingle = 0; + int nDouble = 0; + for(i=0; z[i]; i++){ + if( z[i]=='\'' ) nSingle++; + else if( z[i]=='"' ) nDouble++; + } + if( nSingle==0 ){ + fprintf(out,"'%s'",z); + }else if( nDouble==0 ){ + fprintf(out,"\"%s\"",z); + }else{ + fprintf(out,"'"); + while( *z ){ + for(i=0; z[i] && z[i]!='\''; i++){} + if( i==0 ){ + fprintf(out,"''"); + z++; + }else if( z[i]=='\'' ){ + fprintf(out,"%.*s''",i,z); + z += i+1; + }else{ + fprintf(out,"%s'",z); + break; + } + } + } +} + /* ** This is the callback routine that the SQLite library ** invokes for each row of a query result. @@ -228,15 +288,28 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ } fprintf(p->out,"\n"); } + fprintf(p->out,""); for(i=0; iout,""); - for(i=0; iout,"%s",azArg[i] ? azArg[i] : ""); - } - fprintf(p->out,"\n"); + fprintf(p->out,"%s",azArg[i] ? azArg[i] : ""); } + fprintf(p->out,"\n"); break; } + case MODE_Insert: { + fprintf(p->out,"INSERT INTO '%s' VALUES(",p->zDestTable); + for(i=0; i0 ? ",": ""; + if( azArg[i]==0 ){ + fprintf(p->out,"%sNULL",zSep); + }else if( is_numeric(azArg[i]) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else{ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + } + } + fprintf(p->out,");\n"); + } } return 0; } @@ -394,7 +467,7 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ } }else - if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){ + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ int n2 = strlen(azArg[1]); if( strncmp(azArg[1],"line",n2)==0 ){ p->mode = MODE_Line; @@ -404,6 +477,13 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ p->mode = MODE_List; }else if( strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; + }else if( strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + if( nArg>=3 ){ + sprintf(p->zDestTable,"%.*s", (int)(sizeof(p->zDestTable)-1), azArg[2]); + }else{ + sprintf(p->zDestTable,"table"); + } } }else