Add the ".import" command to the command-line shell. (CVS 1873)

FossilOrigin-Name: b56afe640f7f3f2837120e3dd923c529c4a3123a
This commit is contained in:
drh 2004-08-01 00:10:45 +00:00
parent 9796ef5804
commit feac5f8dbc
7 changed files with 224 additions and 34 deletions

View File

@ -1,5 +1,5 @@
C Additional\stest\scase\sto\scover\sticket\s#831.\s(CVS\s1872)
D 2004-07-27T13:38:48
C Add\sthe\s".import"\scommand\sto\sthe\scommand-line\sshell.\s(CVS\s1873)
D 2004-08-01T00:10:45
F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -39,7 +39,7 @@ F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
F src/main.c 49ea4a45223a002d06b5a4a5db36327acafc1779
F src/main.c 41da595846e299b757cc413d18de804f97f68748
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345
F src/os_common.h fe9604754116bd2f2702d58f82d2d8b89998cb21
@ -53,13 +53,13 @@ F src/os_win.c 54181eb73cb4783c4241feca9eaa490768b39008
F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44
F src/pager.c e0865a9afa64f59c6dc1cc1ab50bc700f67ee28b
F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
F src/parse.y 0bcc53bba498081a544e50c8845bf4857ebfccb9
F src/parse.y 589b1a39b23092888adfa9ec1f3ded8a35e8e006
F src/pragma.c c8be18093f0492f9983406647808781ca0073d8b
F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c cbed45f4af76ad7fdfc0a0df6878b2b3827ae1d4
F src/shell.c 93c96c847228c02fb84bb381875d87ee71fbbeb4
F src/sqlite.h.in d5d542e3cfd25c79f46239d1722d8333f1b16796
F src/shell.c 7371f0a4b1c1aaed336176dfcc6e6742c138b263
F src/sqlite.h.in c340a12b4d0521efb474dd000fba3bdfb18d76da
F src/sqliteInt.h 691d584330cadab3801280caa49eb479fe2446a3
F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
F src/tclsqlite.c cece44ee1d4427185e4ac85ddec79f31ac26965a
@ -77,7 +77,7 @@ F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813
F src/vdbe.c f40f4ca4d9a7ba7c330e5673419f32dd3512547c
F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52
F src/vdbeInt.h 3d8e08c54dcb5ca2169db8bb3a37b81a12efaecd
F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355
F src/vdbeapi.c 3be4ccab4ba6c21d60feffc48e22cf8c1643c6d5
F src/vdbeaux.c daf40a292ec458ed962845a8d95d5c96bc242e04
F src/vdbemem.c bbf621377343bee046547712a144a94f387bb1eb
F src/where.c cf8a54641eea01f1af5d09529ad69166db92f658
@ -240,7 +240,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 76fe68cff6ce75dada510544b063dc1069eb2e0e
R c48658c71737283e3919f2cd9abce5ad
P a62129af99b4a576a48eb4931f417af257f510c7
R b813c752399c5314294f809547b48dc6
U drh
Z ed9af753dbee169dca4931e23b4b59b8
Z a47918bb8602f63d1d3008ff249473a1

View File

@ -1 +1 @@
a62129af99b4a576a48eb4931f417af257f510c7
b56afe640f7f3f2837120e3dd923c529c4a3123a

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.248 2004/07/24 14:35:58 drh Exp $
** $Id: main.c,v 1.249 2004/08/01 00:10:45 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -1242,7 +1242,7 @@ int sqlite3_open16(
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
int sqlite3_finalize(sqlite3_stmt *pStmt){
return sqlite3VdbeFinalize((Vdbe*)pStmt);
return pStmt ? sqlite3VdbeFinalize((Vdbe*)pStmt) : SQLITE_OK;
}
/*

View File

@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.131 2004/07/22 15:02:25 drh Exp $
** @(#) $Id: parse.y,v 1.132 2004/08/01 00:10:45 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@ -902,10 +902,8 @@ cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
}
%type key_opt {struct AttachKey}
key_opt(A) ::= . { A.type = 0; }
%ifdef SQLITE_HAS_CODEC
key_opt(A) ::= KEY ids(X). { A.type=1; A.key = X; }
key_opt(A) ::= KEY BLOB(X). { A.type=2; A.Key = X; }
%endif
key_opt(A) ::= KEY BLOB(X). { A.type=2; A.key = X; }
database_kw_opt ::= DATABASE.
database_kw_opt ::= .

View File

@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.107 2004/07/22 02:40:38 drh Exp $
** $Id: shell.c,v 1.108 2004/08/01 00:10:45 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
@ -104,7 +104,7 @@ static void shellstaticFunc(
/*
** This routine reads a line of text from standard input, stores
** This routine reads a line of text from FILE in, stores
** the text in memory obtained from malloc() and returns a pointer
** to the text. NULL is returned at end of file, or if malloc()
** fails.
@ -219,7 +219,8 @@ struct callback_data {
#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
#define MODE_Html 4 /* Generate an XHTML table */
#define MODE_Insert 5 /* Generate SQL "insert" statements */
#define MODE_NUM_OF 6 /* The number of modes (not a mode itself) */
#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
#define MODE_NUM_OF 7 /* The number of modes (not a mode itself) */
char *modeDescr[MODE_NUM_OF] = {
"line",
@ -227,7 +228,8 @@ char *modeDescr[MODE_NUM_OF] = {
"list",
"semi",
"html",
"insert"
"insert",
"tcl",
};
/*
@ -265,6 +267,34 @@ static void output_quoted_string(FILE *out, const char *z){
}
}
/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
static void output_c_string(FILE *out, const char *z){
unsigned int c;
fputc('"', out);
while( (c = *(z++))!=0 ){
if( c=='\\' ){
fputc(c, out);
fputc(c, out);
}else if( c=='\t' ){
fputc('\\', out);
fputc('t', out);
}else if( c=='\n' ){
fputc('\\', out);
fputc('n', out);
}else if( c=='\r' ){
fputc('\\', out);
fputc('r', out);
}else if( !isprint(c) ){
fprintf(out, "\\%03o", c);
}else{
fputc(c, out);
}
}
fputc('"', out);
}
/*
** Output the given string with characters that are special to
** HTML escaped.
@ -406,6 +436,22 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
fprintf(p->out,"</TR>\n");
break;
}
case MODE_Tcl: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_c_string(p->out,azCol[i]);
fprintf(p->out, "%s", p->separator);
}
fprintf(p->out,"\n");
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
fprintf(p->out, "%s", p->separator);
}
fprintf(p->out,"\n");
break;
}
case MODE_Insert: {
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
@ -603,9 +649,10 @@ static char zHelp[] =
".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
".header(s) ON|OFF Turn display of headers on or off\n"
".help Show this message\n"
".import FILE TABLE Import data from FILE\n"
".indices TABLE Show names of all indices on TABLE\n"
".mode MODE Set mode to one of \"line(s)\", \"column(s)\", \n"
" \"insert\", \"list\", or \"html\"\n"
".mode MODE Set mode to one of: cvs column html insert line\n"
" list tabs tcl\n"
".mode insert TABLE Generate SQL insert statements for TABLE\n"
".nullvalue STRING Print STRING instead of nothing for NULL data\n"
".output FILENAME Send output to FILENAME\n"
@ -617,9 +664,9 @@ static char zHelp[] =
".rekey OLD NEW NEW Change the encryption key\n"
#endif
".schema ?TABLE? Show the CREATE statements\n"
".separator STRING Change separator string for \"list\" mode\n"
".separator STRING Change separator string\n"
".show Show the current values for various settings\n"
".tables ?PATTERN? List names of tables matching a pattern\n"
".tables ?PATTERN? List names of tables matching a LIKE pattern\n"
".timeout MS Try opening locked tables for MS milliseconds\n"
".width NUM NUM ... Set column widths for \"column\" mode\n"
;
@ -648,6 +695,43 @@ static void open_db(struct callback_data *p){
}
}
/*
** Do C-language style dequoting.
**
** \t -> tab
** \n -> newline
** \r -> carriage return
** \NNN -> ascii character NNN in octal
** \\ -> backslash
*/
static void resolve_backslashes(char *z){
int i, j, c;
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' ){
c = z[++i];
if( c=='n' ){
c = '\n';
}else if( c=='t' ){
c = '\t';
}else if( c=='r' ){
c = '\r';
}else if( c>='0' && c<='7' ){
c =- '0';
if( z[i+1]>='0' && z[i+1]<='7' ){
i++;
c = (c<<3) + z[i] - '0';
if( z[i+1]>='0' && z[i+1]<='7' ){
i++;
c = (c<<3) + z[i] - '0';
}
}
}
}
z[j] = c;
}
z[j] = 0;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
@ -673,10 +757,12 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( zLine[i]==delim ){
zLine[i++] = 0;
}
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
}else{
azArg[nArg++] = &zLine[i];
while( zLine[i] && !isspace(zLine[i]) ){ i++; }
if( zLine[i] ) zLine[i++] = 0;
resolve_backslashes(azArg[nArg-1]);
}
}
@ -816,6 +902,98 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(stderr,zHelp);
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
char *zTable = azArg[2]; /* Insert data into this table */
char *zFile = azArg[1]; /* The file from which to extract data */
sqlite3_stmt *pStmt; /* A statement */
int rc; /* Result code */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int nSep; /* Number of bytes in p->separator[] */
char *zSql; /* An SQL statement */
char *zLine; /* A single line of input from the file */
char **azCol; /* zLine[] broken up into columns */
char *zCommit; /* How to commit changes */
FILE *in; /* The input file */
nSep = strlen(p->separator);
if( nSep==0 ){
fprintf(stderr, "non-null separator required for import\n");
return 0;
}
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if( zSql==0 ) return 0;
nByte = strlen(zSql);
rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
nCol = 0;
}else{
nCol = sqlite3_column_count(pStmt);
}
sqlite3_finalize(pStmt);
if( nCol==0 ) return 0;
zSql = malloc( nByte + 20 + nCol*2 );
if( zSql==0 ) return 0;
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
j = strlen(zSql);
for(i=1; i<nCol; i++){
zSql[j++] = ',';
zSql[j++] = '?';
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0);
free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
return 0;
}
in = fopen(zFile, "rb");
if( in==0 ){
fprintf(stderr, "cannot open file: %s\n", zFile);
sqlite3_finalize(pStmt);
return 0;
}
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
if( azCol==0 ) return 0;
sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
zCommit = "COMMIT";
while( (zLine = local_getline(0, in))!=0 ){
char *z;
i = 0;
azCol[0] = zLine;
for(i=0, z=zLine; *z; z++){
if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
*z = 0;
i++;
if( i>=nCol ) break;
azCol[i] = &z[nSep];
z += nSep-1;
}
}
while( i<nCol ) azCol[i++] = 0;
for(i=0; i<nCol; i++){
sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
}
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
free(zLine);
if( rc!=SQLITE_OK ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
zCommit = "ROLLBACK";
break;
}
}
free(azCol);
fclose(in);
sqlite3_finalize(pStmt);
sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
}else
if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
struct callback_data data;
char *zErrMsg = 0;
@ -854,6 +1032,14 @@ static int do_meta_command(char *zLine, 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],"tcl",n2)==0 ){
p->mode = MODE_Tcl;
}else if( strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_List;
strcpy(p->separator, ",");
}else if( strncmp(azArg[1],"tabs",n2)==0 ){
p->mode = MODE_List;
strcpy(p->separator, "\t");
}else if( strncmp(azArg[1],"insert",n2)==0 ){
p->mode = MODE_Insert;
if( nArg>=3 ){
@ -862,7 +1048,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
set_table_name(p, "table");
}
}else {
fprintf(stderr,"mode should be on of: column html insert line list\n");
fprintf(stderr,"mode should be on of: "
"column csv html insert line list tabs tcl\n");
}
}else
@ -999,15 +1186,19 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue);
fprintf(p->out,"%9.9s: ", "nullvalue");
output_c_string(p->out, p->nullvalue);
fprintf(p->out, "\n");
fprintf(p->out,"%9.9s: %s\n","output",
strlen(p->outfile) ? p->outfile : "stdout");
fprintf(p->out,"%9.9s: %s\n","separator", p->separator);
fprintf(p->out,"%9.9s: ", "separator");
output_c_string(p->out, p->separator);
fprintf(p->out, "\n");
fprintf(p->out,"%9.9s: ","width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
fprintf(p->out,"%d ",p->colWidth[i]);
}
fprintf(p->out,"\n\n");
fprintf(p->out,"\n");
}else
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){

View File

@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.111 2004/07/26 12:24:23 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.112 2004/08/01 00:10:45 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
@ -364,6 +364,7 @@ void sqlite3_free_table(char **result);
char *sqlite3_mprintf(const char*,...);
char *sqlite3_vmprintf(const char*, va_list);
void sqlite3_free(char *z);
char *sqlite3_snprintf(int,char*,const char*, ...);
#ifndef SQLITE_OMIT_AUTHORIZATION
/*

View File

@ -436,7 +436,7 @@ int sqlite3_bind_blob(
int rc;
rc = vdbeUnbind(p, i);
if( rc ){
if( rc || zData==0 ){
return rc;
}
pVar = &p->apVar[i-1];
@ -479,7 +479,7 @@ int sqlite3_bind_text(
int rc;
rc = vdbeUnbind(p, i);
if( rc ){
if( rc || zData==0 ){
return rc;
}
pVar = &p->apVar[i-1];
@ -502,7 +502,7 @@ int sqlite3_bind_text16(
int rc;
rc = vdbeUnbind(p, i);
if( rc ){
if( rc || zData==0 ){
return rc;
}
pVar = &p->apVar[i-1];