blob: 4860a250f5f8db95ff17bc9af87f5ea2e7868b27 [file] [log] [blame]
drh75897232000-05-29 14:26:00 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drh75897232000-05-29 14:26:00 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drh75897232000-05-29 14:26:00 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drh75897232000-05-29 14:26:00 +000010**
11*************************************************************************
12** This file contains code to implement the "sqlite" command line
13** utility for accessing SQLite databases.
14**
drhc49f44e2006-10-26 18:15:42 +000015** $Id: shell.c,v 1.152 2006/10/26 18:15:42 drh Exp $
drh75897232000-05-29 14:26:00 +000016*/
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
danielk19772a02e332004-06-05 08:04:36 +000020#include <assert.h>
drh1d482dd2004-05-31 18:23:07 +000021#include "sqlite3.h"
drh75897232000-05-29 14:26:00 +000022#include <ctype.h>
persicom7e2dfdd2002-04-18 02:46:52 +000023
drhcdb36b72006-06-12 12:57:45 +000024#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
drh4c504392000-10-16 22:06:40 +000025# include <signal.h>
drhdd45df82002-04-18 12:39:03 +000026# include <pwd.h>
27# include <unistd.h>
28# include <sys/types.h>
drh4c504392000-10-16 22:06:40 +000029#endif
drh75897232000-05-29 14:26:00 +000030
drh820f3812003-01-08 13:02:52 +000031#ifdef __MACOS__
32# include <console.h>
33# include <signal.h>
34# include <unistd.h>
35# include <extras.h>
36# include <Files.h>
37# include <Folders.h>
38#endif
39
drhcdb36b72006-06-12 12:57:45 +000040#ifdef __OS2__
41# include <unistd.h>
42#endif
43
drh16e59552000-07-31 11:57:37 +000044#if defined(HAVE_READLINE) && HAVE_READLINE==1
drh8e7e7a22000-05-30 18:45:23 +000045# include <readline/readline.h>
46# include <readline/history.h>
47#else
drh9347b202003-07-18 01:30:59 +000048# define readline(p) local_getline(p,stdin)
persicom1d0b8722002-04-18 02:53:04 +000049# define add_history(X)
drh67505e72002-04-19 12:34:06 +000050# define read_history(X)
51# define write_history(X)
52# define stifle_history(X)
drh75897232000-05-29 14:26:00 +000053#endif
54
adamd2e8464a2006-09-06 21:39:40 +000055#if defined(_WIN32) || defined(WIN32)
56# include <io.h>
57#else
drh4328c8b2003-04-26 02:50:11 +000058/* Make sure isatty() has a prototype.
59*/
60extern int isatty();
adamd2e8464a2006-09-06 21:39:40 +000061#endif
drh4328c8b2003-04-26 02:50:11 +000062
drh75897232000-05-29 14:26:00 +000063/*
drhc49f44e2006-10-26 18:15:42 +000064** If the following flag is set, then command execution stops
65** at an error if we are not interactive.
66*/
67static int bail_on_error = 0;
68
69/*
drhc28490c2006-10-26 14:25:58 +000070** Threat stdin as an interactive input if the following variable
71** is true. Otherwise, assume stdin is connected to a file or pipe.
72*/
73static int stdin_is_interactive = 1;
74
75/*
drh4c504392000-10-16 22:06:40 +000076** The following is the open SQLite database. We make a pointer
77** to this database a static variable so that it can be accessed
78** by the SIGINT handler to interrupt database processing.
79*/
danielk197792f9a1b2004-06-19 09:08:16 +000080static sqlite3 *db = 0;
drh4c504392000-10-16 22:06:40 +000081
82/*
drh67505e72002-04-19 12:34:06 +000083** True if an interrupt (Control-C) has been received.
84*/
drh43617e92006-03-06 20:55:46 +000085static volatile int seenInterrupt = 0;
drh67505e72002-04-19 12:34:06 +000086
87/*
persicom7e2dfdd2002-04-18 02:46:52 +000088** This is the name of our program. It is set in main(), used
89** in a number of other places, mostly for error messages.
90*/
91static char *Argv0;
92
93/*
94** Prompt strings. Initialized in main. Settable with
95** .prompt main continue
96*/
97static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
98static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
99
drh44c2eb12003-04-30 11:38:26 +0000100
persicom7e2dfdd2002-04-18 02:46:52 +0000101/*
drh83965662003-04-17 02:54:13 +0000102** Determines if a string is a number of not.
103*/
danielk19772e588c72005-12-09 14:25:08 +0000104static int isNumber(const char *z, int *realnum){
drhc8d74412004-08-31 23:41:26 +0000105 if( *z=='-' || *z=='+' ) z++;
106 if( !isdigit(*z) ){
107 return 0;
108 }
109 z++;
110 if( realnum ) *realnum = 0;
111 while( isdigit(*z) ){ z++; }
112 if( *z=='.' ){
113 z++;
114 if( !isdigit(*z) ) return 0;
115 while( isdigit(*z) ){ z++; }
116 if( realnum ) *realnum = 1;
117 }
118 if( *z=='e' || *z=='E' ){
119 z++;
120 if( *z=='+' || *z=='-' ) z++;
121 if( !isdigit(*z) ) return 0;
122 while( isdigit(*z) ){ z++; }
123 if( realnum ) *realnum = 1;
124 }
125 return *z==0;
126}
drh83965662003-04-17 02:54:13 +0000127
128/*
danielk1977bc6ada42004-06-30 08:20:16 +0000129** A global char* and an SQL function to access its current value
130** from within an SQL statement. This program used to use the
131** sqlite_exec_printf() API to substitue a string into an SQL statement.
132** The correct way to do this with sqlite3 is to use the bind API, but
133** since the shell is built around the callback paradigm it would be a lot
134** of work. Instead just use this hack, which is quite harmless.
135*/
136static const char *zShellStatic = 0;
137static void shellstaticFunc(
138 sqlite3_context *context,
139 int argc,
140 sqlite3_value **argv
141){
142 assert( 0==argc );
143 assert( zShellStatic );
144 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
145}
146
147
148/*
drhfeac5f82004-08-01 00:10:45 +0000149** This routine reads a line of text from FILE in, stores
drh8e7e7a22000-05-30 18:45:23 +0000150** the text in memory obtained from malloc() and returns a pointer
151** to the text. NULL is returned at end of file, or if malloc()
152** fails.
153**
154** The interface is like "readline" but no command-line editing
155** is done.
156*/
drh9347b202003-07-18 01:30:59 +0000157static char *local_getline(char *zPrompt, FILE *in){
drh8e7e7a22000-05-30 18:45:23 +0000158 char *zLine;
159 int nLine;
drh8e7e7a22000-05-30 18:45:23 +0000160 int n;
161 int eol;
162
163 if( zPrompt && *zPrompt ){
164 printf("%s",zPrompt);
165 fflush(stdout);
166 }
167 nLine = 100;
168 zLine = malloc( nLine );
169 if( zLine==0 ) return 0;
170 n = 0;
171 eol = 0;
172 while( !eol ){
173 if( n+100>nLine ){
174 nLine = nLine*2 + 100;
175 zLine = realloc(zLine, nLine);
176 if( zLine==0 ) return 0;
177 }
drhdaffd0e2001-04-11 14:28:42 +0000178 if( fgets(&zLine[n], nLine - n, in)==0 ){
drh8e7e7a22000-05-30 18:45:23 +0000179 if( n==0 ){
180 free(zLine);
181 return 0;
182 }
183 zLine[n] = 0;
184 eol = 1;
185 break;
186 }
187 while( zLine[n] ){ n++; }
188 if( n>0 && zLine[n-1]=='\n' ){
189 n--;
190 zLine[n] = 0;
191 eol = 1;
192 }
193 }
194 zLine = realloc( zLine, n+1 );
195 return zLine;
196}
197
198/*
drhc28490c2006-10-26 14:25:58 +0000199** Retrieve a single line of input text.
drh8e7e7a22000-05-30 18:45:23 +0000200**
201** zPrior is a string of prior text retrieved. If not the empty
202** string, then issue a continuation prompt.
203*/
drhdaffd0e2001-04-11 14:28:42 +0000204static char *one_input_line(const char *zPrior, FILE *in){
drh8e7e7a22000-05-30 18:45:23 +0000205 char *zPrompt;
206 char *zResult;
drhdaffd0e2001-04-11 14:28:42 +0000207 if( in!=0 ){
drh9347b202003-07-18 01:30:59 +0000208 return local_getline(0, in);
drh8e7e7a22000-05-30 18:45:23 +0000209 }
210 if( zPrior && zPrior[0] ){
persicom7e2dfdd2002-04-18 02:46:52 +0000211 zPrompt = continuePrompt;
drh8e7e7a22000-05-30 18:45:23 +0000212 }else{
persicom7e2dfdd2002-04-18 02:46:52 +0000213 zPrompt = mainPrompt;
drh8e7e7a22000-05-30 18:45:23 +0000214 }
215 zResult = readline(zPrompt);
danielk19774af00c62005-01-23 23:43:21 +0000216#if defined(HAVE_READLINE) && HAVE_READLINE==1
drheb741d52006-06-03 17:37:25 +0000217 if( zResult && *zResult ) add_history(zResult);
danielk19774af00c62005-01-23 23:43:21 +0000218#endif
drh8e7e7a22000-05-30 18:45:23 +0000219 return zResult;
220}
221
persicom7e2dfdd2002-04-18 02:46:52 +0000222struct previous_mode_data {
223 int valid; /* Is there legit data in here? */
224 int mode;
225 int showHeader;
226 int colWidth[100];
227};
drh8e7e7a22000-05-30 18:45:23 +0000228/*
drh75897232000-05-29 14:26:00 +0000229** An pointer to an instance of this structure is passed from
230** the main program to the callback. This is used to communicate
231** state and mode information.
232*/
233struct callback_data {
danielk197792f9a1b2004-06-19 09:08:16 +0000234 sqlite3 *db; /* The database */
drhdaffd0e2001-04-11 14:28:42 +0000235 int echoOn; /* True to echo input commands */
drh28bd4bc2000-06-15 15:57:22 +0000236 int cnt; /* Number of records displayed so far */
237 FILE *out; /* Write results here */
238 int mode; /* An output mode setting */
239 int showHeader; /* True to show column names in List or Column mode */
drh33048c02001-10-01 14:29:22 +0000240 char *zDestTable; /* Name of destination table when MODE_Insert */
drh28bd4bc2000-06-15 15:57:22 +0000241 char separator[20]; /* Separator character for MODE_List */
drha0c66f52000-07-29 13:20:21 +0000242 int colWidth[100]; /* Requested width of each column when in column mode*/
243 int actualWidth[100]; /* Actual width of each column */
drh83965662003-04-17 02:54:13 +0000244 char nullvalue[20]; /* The text to print when a NULL comes back from
245 ** the database */
persicom7e2dfdd2002-04-18 02:46:52 +0000246 struct previous_mode_data explainPrev;
drh83965662003-04-17 02:54:13 +0000247 /* Holds the mode information just before
248 ** .explain ON */
drh44c2eb12003-04-30 11:38:26 +0000249 char outfile[FILENAME_MAX]; /* Filename for *out */
250 const char *zDbFilename; /* name of the database file */
drh75897232000-05-29 14:26:00 +0000251};
252
253/*
254** These are the allowed modes.
255*/
drh967e8b72000-06-21 13:59:10 +0000256#define MODE_Line 0 /* One column per line. Blank line between records */
drh75897232000-05-29 14:26:00 +0000257#define MODE_Column 1 /* One record per line in neat columns */
258#define MODE_List 2 /* One record per line with a separator */
drhe3710332000-09-29 13:30:53 +0000259#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
260#define MODE_Html 4 /* Generate an XHTML table */
261#define MODE_Insert 5 /* Generate SQL "insert" statements */
drhfeac5f82004-08-01 00:10:45 +0000262#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
drh8e64d1c2004-10-07 00:32:39 +0000263#define MODE_Csv 7 /* Quote strings, numbers are plain */
264#define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */
persicom7e2dfdd2002-04-18 02:46:52 +0000265
drh0850b532006-01-31 19:31:43 +0000266static const char *modeDescr[MODE_NUM_OF] = {
persicom7e2dfdd2002-04-18 02:46:52 +0000267 "line",
268 "column",
269 "list",
270 "semi",
271 "html",
drhfeac5f82004-08-01 00:10:45 +0000272 "insert",
273 "tcl",
drh8e64d1c2004-10-07 00:32:39 +0000274 "csv",
persicom7e2dfdd2002-04-18 02:46:52 +0000275};
drh75897232000-05-29 14:26:00 +0000276
277/*
278** Number of elements in an array
279*/
280#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
281
282/*
drh28bd4bc2000-06-15 15:57:22 +0000283** Output the given string as a quoted string using SQL quoting conventions.
284*/
285static void output_quoted_string(FILE *out, const char *z){
286 int i;
287 int nSingle = 0;
drh28bd4bc2000-06-15 15:57:22 +0000288 for(i=0; z[i]; i++){
289 if( z[i]=='\'' ) nSingle++;
drh28bd4bc2000-06-15 15:57:22 +0000290 }
291 if( nSingle==0 ){
292 fprintf(out,"'%s'",z);
drh28bd4bc2000-06-15 15:57:22 +0000293 }else{
294 fprintf(out,"'");
295 while( *z ){
296 for(i=0; z[i] && z[i]!='\''; i++){}
297 if( i==0 ){
298 fprintf(out,"''");
299 z++;
300 }else if( z[i]=='\'' ){
301 fprintf(out,"%.*s''",i,z);
302 z += i+1;
303 }else{
drhcd7d2732002-02-26 23:24:26 +0000304 fprintf(out,"%s",z);
drh28bd4bc2000-06-15 15:57:22 +0000305 break;
306 }
307 }
drhcd7d2732002-02-26 23:24:26 +0000308 fprintf(out,"'");
drh28bd4bc2000-06-15 15:57:22 +0000309 }
310}
311
312/*
drhfeac5f82004-08-01 00:10:45 +0000313** Output the given string as a quoted according to C or TCL quoting rules.
314*/
315static void output_c_string(FILE *out, const char *z){
316 unsigned int c;
317 fputc('"', out);
318 while( (c = *(z++))!=0 ){
319 if( c=='\\' ){
320 fputc(c, out);
321 fputc(c, out);
322 }else if( c=='\t' ){
323 fputc('\\', out);
324 fputc('t', out);
325 }else if( c=='\n' ){
326 fputc('\\', out);
327 fputc('n', out);
328 }else if( c=='\r' ){
329 fputc('\\', out);
330 fputc('r', out);
331 }else if( !isprint(c) ){
drh0a8640d2005-08-30 20:12:02 +0000332 fprintf(out, "\\%03o", c&0xff);
drhfeac5f82004-08-01 00:10:45 +0000333 }else{
334 fputc(c, out);
335 }
336 }
337 fputc('"', out);
338}
339
340/*
drhc08a4f12000-06-15 16:49:48 +0000341** Output the given string with characters that are special to
342** HTML escaped.
343*/
344static void output_html_string(FILE *out, const char *z){
345 int i;
346 while( *z ){
347 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
348 if( i>0 ){
349 fprintf(out,"%.*s",i,z);
350 }
351 if( z[i]=='<' ){
352 fprintf(out,"&lt;");
353 }else if( z[i]=='&' ){
354 fprintf(out,"&amp;");
355 }else{
356 break;
357 }
358 z += i + 1;
359 }
360}
361
362/*
drhc49f44e2006-10-26 18:15:42 +0000363** If a field contains any character identified by a 1 in the following
364** array, then the string must be quoted for CSV.
365*/
366static const char needCsvQuote[] = {
367 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
368 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
369 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
375 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
376 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
377 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
378 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
379 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
380 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
381 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
382 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
383};
384
385/*
drh8e64d1c2004-10-07 00:32:39 +0000386** Output a single term of CSV. Actually, p->separator is used for
387** the separator, which may or may not be a comma. p->nullvalue is
388** the null value. Strings are quoted using ANSI-C rules. Numbers
389** appear outside of quotes.
390*/
391static void output_csv(struct callback_data *p, const char *z, int bSep){
drhc49f44e2006-10-26 18:15:42 +0000392 FILE *out = p->out;
drh8e64d1c2004-10-07 00:32:39 +0000393 if( z==0 ){
drhc49f44e2006-10-26 18:15:42 +0000394 fprintf(out,"%s",p->nullvalue);
drh8e64d1c2004-10-07 00:32:39 +0000395 }else{
drhc49f44e2006-10-26 18:15:42 +0000396 int i;
397 for(i=0; z[i]; i++){
398 if( needCsvQuote[((unsigned char*)z)[i]] ){
399 i = 0;
400 break;
401 }
402 }
403 if( i==0 ){
404 putc('"', out);
405 for(i=0; z[i]; i++){
406 if( z[i]=='"' ) putc('"', out);
407 putc(z[i], out);
408 }
409 putc('"', out);
410 }else{
411 fprintf(out, "%s", z);
412 }
drh8e64d1c2004-10-07 00:32:39 +0000413 }
414 if( bSep ){
415 fprintf(p->out, p->separator);
416 }
417}
418
danielk19774af00c62005-01-23 23:43:21 +0000419#ifdef SIGINT
drh8e64d1c2004-10-07 00:32:39 +0000420/*
drh4c504392000-10-16 22:06:40 +0000421** This routine runs when the user presses Ctrl-C
422*/
423static void interrupt_handler(int NotUsed){
drh67505e72002-04-19 12:34:06 +0000424 seenInterrupt = 1;
danielk19776f8a5032004-05-10 10:34:51 +0000425 if( db ) sqlite3_interrupt(db);
drh4c504392000-10-16 22:06:40 +0000426}
danielk19774af00c62005-01-23 23:43:21 +0000427#endif
drh4c504392000-10-16 22:06:40 +0000428
429/*
drh75897232000-05-29 14:26:00 +0000430** This is the callback routine that the SQLite library
431** invokes for each row of a query result.
432*/
433static int callback(void *pArg, int nArg, char **azArg, char **azCol){
434 int i;
435 struct callback_data *p = (struct callback_data*)pArg;
436 switch( p->mode ){
437 case MODE_Line: {
drhe3710332000-09-29 13:30:53 +0000438 int w = 5;
drh6a535342001-10-19 16:44:56 +0000439 if( azArg==0 ) break;
drhe3710332000-09-29 13:30:53 +0000440 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000441 int len = strlen(azCol[i] ? azCol[i] : "");
drhe3710332000-09-29 13:30:53 +0000442 if( len>w ) w = len;
443 }
drh75897232000-05-29 14:26:00 +0000444 if( p->cnt++>0 ) fprintf(p->out,"\n");
445 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000446 fprintf(p->out,"%*s = %s\n", w, azCol[i],
drha69d9162003-04-17 22:57:53 +0000447 azArg[i] ? azArg[i] : p->nullvalue);
drh75897232000-05-29 14:26:00 +0000448 }
449 break;
450 }
451 case MODE_Column: {
drha0c66f52000-07-29 13:20:21 +0000452 if( p->cnt++==0 ){
drh75897232000-05-29 14:26:00 +0000453 for(i=0; i<nArg; i++){
drha0c66f52000-07-29 13:20:21 +0000454 int w, n;
455 if( i<ArraySize(p->colWidth) ){
drh75897232000-05-29 14:26:00 +0000456 w = p->colWidth[i];
457 }else{
drha0c66f52000-07-29 13:20:21 +0000458 w = 0;
drh75897232000-05-29 14:26:00 +0000459 }
drha0c66f52000-07-29 13:20:21 +0000460 if( w<=0 ){
drhff6e9112000-08-28 16:21:58 +0000461 w = strlen(azCol[i] ? azCol[i] : "");
drha0c66f52000-07-29 13:20:21 +0000462 if( w<10 ) w = 10;
persicom7e2dfdd2002-04-18 02:46:52 +0000463 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
drha0c66f52000-07-29 13:20:21 +0000464 if( w<n ) w = n;
465 }
466 if( i<ArraySize(p->actualWidth) ){
persicom1d0b8722002-04-18 02:53:04 +0000467 p->actualWidth[i] = w;
drha0c66f52000-07-29 13:20:21 +0000468 }
469 if( p->showHeader ){
470 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
471 }
472 }
473 if( p->showHeader ){
474 for(i=0; i<nArg; i++){
475 int w;
476 if( i<ArraySize(p->actualWidth) ){
477 w = p->actualWidth[i];
478 }else{
479 w = 10;
480 }
481 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
482 "----------------------------------------------------------",
483 i==nArg-1 ? "\n": " ");
484 }
drh75897232000-05-29 14:26:00 +0000485 }
486 }
drh6a535342001-10-19 16:44:56 +0000487 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000488 for(i=0; i<nArg; i++){
489 int w;
drha0c66f52000-07-29 13:20:21 +0000490 if( i<ArraySize(p->actualWidth) ){
491 w = p->actualWidth[i];
drh75897232000-05-29 14:26:00 +0000492 }else{
493 w = 10;
494 }
drhc61053b2000-06-04 12:58:36 +0000495 fprintf(p->out,"%-*.*s%s",w,w,
persicom7e2dfdd2002-04-18 02:46:52 +0000496 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
drh75897232000-05-29 14:26:00 +0000497 }
498 break;
499 }
drhe3710332000-09-29 13:30:53 +0000500 case MODE_Semi:
drh75897232000-05-29 14:26:00 +0000501 case MODE_List: {
502 if( p->cnt++==0 && p->showHeader ){
503 for(i=0; i<nArg; i++){
504 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
505 }
506 }
drh6a535342001-10-19 16:44:56 +0000507 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000508 for(i=0; i<nArg; i++){
drh4c653a02000-06-07 01:27:47 +0000509 char *z = azArg[i];
persicom7e2dfdd2002-04-18 02:46:52 +0000510 if( z==0 ) z = p->nullvalue;
drh71172c52002-01-24 00:00:21 +0000511 fprintf(p->out, "%s", z);
drhe3710332000-09-29 13:30:53 +0000512 if( i<nArg-1 ){
513 fprintf(p->out, "%s", p->separator);
514 }else if( p->mode==MODE_Semi ){
515 fprintf(p->out, ";\n");
516 }else{
517 fprintf(p->out, "\n");
518 }
drh75897232000-05-29 14:26:00 +0000519 }
520 break;
521 }
drh1e5d0e92000-05-31 23:33:17 +0000522 case MODE_Html: {
523 if( p->cnt++==0 && p->showHeader ){
524 fprintf(p->out,"<TR>");
525 for(i=0; i<nArg; i++){
526 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
527 }
528 fprintf(p->out,"</TR>\n");
529 }
drh6a535342001-10-19 16:44:56 +0000530 if( azArg==0 ) break;
drh28bd4bc2000-06-15 15:57:22 +0000531 fprintf(p->out,"<TR>");
drh1e5d0e92000-05-31 23:33:17 +0000532 for(i=0; i<nArg; i++){
drhc08a4f12000-06-15 16:49:48 +0000533 fprintf(p->out,"<TD>");
persicom7e2dfdd2002-04-18 02:46:52 +0000534 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
drhc08a4f12000-06-15 16:49:48 +0000535 fprintf(p->out,"</TD>\n");
drh1e5d0e92000-05-31 23:33:17 +0000536 }
drh7d686b22002-11-11 13:56:47 +0000537 fprintf(p->out,"</TR>\n");
drh1e5d0e92000-05-31 23:33:17 +0000538 break;
539 }
drhfeac5f82004-08-01 00:10:45 +0000540 case MODE_Tcl: {
541 if( p->cnt++==0 && p->showHeader ){
542 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000543 output_c_string(p->out,azCol[i] ? azCol[i] : "");
drhfeac5f82004-08-01 00:10:45 +0000544 fprintf(p->out, "%s", p->separator);
545 }
546 fprintf(p->out,"\n");
547 }
548 if( azArg==0 ) break;
549 for(i=0; i<nArg; i++){
550 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
551 fprintf(p->out, "%s", p->separator);
552 }
553 fprintf(p->out,"\n");
554 break;
555 }
drh8e64d1c2004-10-07 00:32:39 +0000556 case MODE_Csv: {
557 if( p->cnt++==0 && p->showHeader ){
558 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000559 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
drh8e64d1c2004-10-07 00:32:39 +0000560 }
561 fprintf(p->out,"\n");
562 }
563 if( azArg==0 ) break;
564 for(i=0; i<nArg; i++){
565 output_csv(p, azArg[i], i<nArg-1);
566 }
567 fprintf(p->out,"\n");
568 break;
569 }
drh28bd4bc2000-06-15 15:57:22 +0000570 case MODE_Insert: {
drh6a535342001-10-19 16:44:56 +0000571 if( azArg==0 ) break;
drh33048c02001-10-01 14:29:22 +0000572 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
drh28bd4bc2000-06-15 15:57:22 +0000573 for(i=0; i<nArg; i++){
574 char *zSep = i>0 ? ",": "";
575 if( azArg[i]==0 ){
576 fprintf(p->out,"%sNULL",zSep);
drhc8d74412004-08-31 23:41:26 +0000577 }else if( isNumber(azArg[i], 0) ){
drh28bd4bc2000-06-15 15:57:22 +0000578 fprintf(p->out,"%s%s",zSep, azArg[i]);
579 }else{
580 if( zSep[0] ) fprintf(p->out,"%s",zSep);
581 output_quoted_string(p->out, azArg[i]);
582 }
583 }
584 fprintf(p->out,");\n");
drh6a535342001-10-19 16:44:56 +0000585 break;
drh28bd4bc2000-06-15 15:57:22 +0000586 }
persicom1d0b8722002-04-18 02:53:04 +0000587 }
drh75897232000-05-29 14:26:00 +0000588 return 0;
589}
590
591/*
drh33048c02001-10-01 14:29:22 +0000592** Set the destination table field of the callback_data structure to
593** the name of the table given. Escape any quote characters in the
594** table name.
595*/
596static void set_table_name(struct callback_data *p, const char *zName){
597 int i, n;
598 int needQuote;
599 char *z;
600
601 if( p->zDestTable ){
602 free(p->zDestTable);
603 p->zDestTable = 0;
604 }
605 if( zName==0 ) return;
drh4c755c02004-08-08 20:22:17 +0000606 needQuote = !isalpha((unsigned char)*zName) && *zName!='_';
drh33048c02001-10-01 14:29:22 +0000607 for(i=n=0; zName[i]; i++, n++){
drh4c755c02004-08-08 20:22:17 +0000608 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){
drh33048c02001-10-01 14:29:22 +0000609 needQuote = 1;
610 if( zName[i]=='\'' ) n++;
611 }
612 }
613 if( needQuote ) n += 2;
614 z = p->zDestTable = malloc( n+1 );
615 if( z==0 ){
616 fprintf(stderr,"Out of memory!\n");
617 exit(1);
618 }
619 n = 0;
620 if( needQuote ) z[n++] = '\'';
621 for(i=0; zName[i]; i++){
622 z[n++] = zName[i];
623 if( zName[i]=='\'' ) z[n++] = '\'';
624 }
625 if( needQuote ) z[n++] = '\'';
626 z[n] = 0;
627}
628
danielk19772a02e332004-06-05 08:04:36 +0000629/* zIn is either a pointer to a NULL-terminated string in memory obtained
630** from malloc(), or a NULL pointer. The string pointed to by zAppend is
631** added to zIn, and the result returned in memory obtained from malloc().
632** zIn, if it was not NULL, is freed.
633**
634** If the third argument, quote, is not '\0', then it is used as a
635** quote character for zAppend.
636*/
drhc28490c2006-10-26 14:25:58 +0000637static char *appendText(char *zIn, char const *zAppend, char quote){
danielk19772a02e332004-06-05 08:04:36 +0000638 int len;
639 int i;
640 int nAppend = strlen(zAppend);
641 int nIn = (zIn?strlen(zIn):0);
642
643 len = nAppend+nIn+1;
644 if( quote ){
645 len += 2;
646 for(i=0; i<nAppend; i++){
647 if( zAppend[i]==quote ) len++;
648 }
649 }
650
651 zIn = (char *)realloc(zIn, len);
652 if( !zIn ){
653 return 0;
654 }
655
656 if( quote ){
657 char *zCsr = &zIn[nIn];
658 *zCsr++ = quote;
659 for(i=0; i<nAppend; i++){
660 *zCsr++ = zAppend[i];
661 if( zAppend[i]==quote ) *zCsr++ = quote;
662 }
663 *zCsr++ = quote;
664 *zCsr++ = '\0';
665 assert( (zCsr-zIn)==len );
666 }else{
667 memcpy(&zIn[nIn], zAppend, nAppend);
668 zIn[len-1] = '\0';
669 }
670
671 return zIn;
672}
673
drhdd3d4592004-08-30 01:54:05 +0000674
675/*
676** Execute a query statement that has a single result column. Print
677** that result column on a line by itself with a semicolon terminator.
678*/
679static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
680 sqlite3_stmt *pSelect;
681 int rc;
682 rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
683 if( rc!=SQLITE_OK || !pSelect ){
684 return rc;
685 }
686 rc = sqlite3_step(pSelect);
687 while( rc==SQLITE_ROW ){
688 fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
689 rc = sqlite3_step(pSelect);
690 }
691 return sqlite3_finalize(pSelect);
692}
693
694
drh33048c02001-10-01 14:29:22 +0000695/*
drh4c653a02000-06-07 01:27:47 +0000696** This is a different callback routine used for dumping the database.
697** Each row received by this callback consists of a table name,
698** the table type ("index" or "table") and SQL to create the table.
699** This routine should print text sufficient to recreate the table.
700*/
701static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
danielk19772a02e332004-06-05 08:04:36 +0000702 int rc;
703 const char *zTable;
704 const char *zType;
705 const char *zSql;
drhdaffd0e2001-04-11 14:28:42 +0000706 struct callback_data *p = (struct callback_data *)pArg;
danielk19772a02e332004-06-05 08:04:36 +0000707
drh4c653a02000-06-07 01:27:47 +0000708 if( nArg!=3 ) return 1;
danielk19772a02e332004-06-05 08:04:36 +0000709 zTable = azArg[0];
710 zType = azArg[1];
711 zSql = azArg[2];
712
drh00b950d2005-09-11 02:03:03 +0000713 if( strcmp(zTable, "sqlite_sequence")==0 ){
drhf8eb96a2005-02-03 00:42:34 +0000714 fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
drh00b950d2005-09-11 02:03:03 +0000715 }else if( strcmp(zTable, "sqlite_stat1")==0 ){
716 fprintf(p->out, "ANALYZE sqlite_master;\n");
717 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
718 return 0;
719 }else{
720 fprintf(p->out, "%s;\n", zSql);
drhf8eb96a2005-02-03 00:42:34 +0000721 }
danielk19772a02e332004-06-05 08:04:36 +0000722
723 if( strcmp(zType, "table")==0 ){
724 sqlite3_stmt *pTableInfo = 0;
danielk19772a02e332004-06-05 08:04:36 +0000725 char *zSelect = 0;
726 char *zTableInfo = 0;
727 char *zTmp = 0;
728
729 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
730 zTableInfo = appendText(zTableInfo, zTable, '"');
731 zTableInfo = appendText(zTableInfo, ");", 0);
732
733 rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
734 if( zTableInfo ) free(zTableInfo);
735 if( rc!=SQLITE_OK || !pTableInfo ){
736 return 1;
737 }
738
739 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
740 zTmp = appendText(zTmp, zTable, '"');
741 if( zTmp ){
742 zSelect = appendText(zSelect, zTmp, '\'');
743 }
744 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
745 rc = sqlite3_step(pTableInfo);
746 while( rc==SQLITE_ROW ){
danielk19772e588c72005-12-09 14:25:08 +0000747 const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
danielk19773f41e972004-06-08 00:39:01 +0000748 zSelect = appendText(zSelect, "quote(", 0);
danielk19772e588c72005-12-09 14:25:08 +0000749 zSelect = appendText(zSelect, zText, '"');
danielk19772a02e332004-06-05 08:04:36 +0000750 rc = sqlite3_step(pTableInfo);
751 if( rc==SQLITE_ROW ){
752 zSelect = appendText(zSelect, ") || ', ' || ", 0);
753 }else{
754 zSelect = appendText(zSelect, ") ", 0);
755 }
756 }
757 rc = sqlite3_finalize(pTableInfo);
758 if( rc!=SQLITE_OK ){
759 if( zSelect ) free(zSelect);
760 return 1;
761 }
762 zSelect = appendText(zSelect, "|| ')' FROM ", 0);
763 zSelect = appendText(zSelect, zTable, '"');
764
drhdd3d4592004-08-30 01:54:05 +0000765 rc = run_table_dump_query(p->out, p->db, zSelect);
766 if( rc==SQLITE_CORRUPT ){
767 zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
768 rc = run_table_dump_query(p->out, p->db, zSelect);
769 }
danielk19772a02e332004-06-05 08:04:36 +0000770 if( zSelect ) free(zSelect);
danielk19772a02e332004-06-05 08:04:36 +0000771 if( rc!=SQLITE_OK ){
772 return 1;
773 }
drh4c653a02000-06-07 01:27:47 +0000774 }
drh4c653a02000-06-07 01:27:47 +0000775 return 0;
776}
777
778/*
drhdd3d4592004-08-30 01:54:05 +0000779** Run zQuery. Update dump_callback() as the callback routine.
780** If we get a SQLITE_CORRUPT error, rerun the query after appending
781** "ORDER BY rowid DESC" to the end.
782*/
783static int run_schema_dump_query(
784 struct callback_data *p,
785 const char *zQuery,
786 char **pzErrMsg
787){
788 int rc;
789 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
790 if( rc==SQLITE_CORRUPT ){
791 char *zQ2;
792 int len = strlen(zQuery);
793 if( pzErrMsg ) sqlite3_free(*pzErrMsg);
794 zQ2 = malloc( len+100 );
795 if( zQ2==0 ) return rc;
796 sprintf(zQ2, "%s ORDER BY rowid DESC", zQuery);
797 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
798 free(zQ2);
799 }
800 return rc;
801}
802
803/*
drh75897232000-05-29 14:26:00 +0000804** Text of a help message
805*/
persicom1d0b8722002-04-18 02:53:04 +0000806static char zHelp[] =
jplyon6a65bb32003-05-04 07:25:57 +0000807 ".databases List names and files of attached databases\n"
drhb860bc92004-08-04 15:16:55 +0000808 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
drhdaffd0e2001-04-11 14:28:42 +0000809 ".echo ON|OFF Turn command echo on or off\n"
drh75897232000-05-29 14:26:00 +0000810 ".exit Exit this program\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000811 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000812 ".header(s) ON|OFF Turn display of headers on or off\n"
drh75897232000-05-29 14:26:00 +0000813 ".help Show this message\n"
drhb860bc92004-08-04 15:16:55 +0000814 ".import FILE TABLE Import data from FILE into TABLE\n"
drh75897232000-05-29 14:26:00 +0000815 ".indices TABLE Show names of all indices on TABLE\n"
drh70df4fe2006-06-13 15:12:21 +0000816#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +0000817 ".load FILE ?ENTRY? Load an extension library\n"
drh70df4fe2006-06-13 15:12:21 +0000818#endif
danielk19776b77a362005-01-13 11:10:25 +0000819 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
drh3b584fa2004-09-24 12:50:03 +0000820 " csv Comma-separated values\n"
drhb860bc92004-08-04 15:16:55 +0000821 " column Left-aligned columns. (See .width)\n"
822 " html HTML <table> code\n"
823 " insert SQL insert statements for TABLE\n"
824 " line One value per line\n"
825 " list Values delimited by .separator string\n"
826 " tabs Tab-separated values\n"
827 " tcl TCL list elements\n"
828 ".nullvalue STRING Print STRING in place of NULL values\n"
drh75897232000-05-29 14:26:00 +0000829 ".output FILENAME Send output to FILENAME\n"
830 ".output stdout Send output to the screen\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000831 ".prompt MAIN CONTINUE Replace the standard prompts\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000832 ".quit Exit this program\n"
drhdaffd0e2001-04-11 14:28:42 +0000833 ".read FILENAME Execute SQL in FILENAME\n"
drh75897232000-05-29 14:26:00 +0000834 ".schema ?TABLE? Show the CREATE statements\n"
drhb860bc92004-08-04 15:16:55 +0000835 ".separator STRING Change separator used by output mode and .import\n"
drhdd45df82002-04-18 12:39:03 +0000836 ".show Show the current values for various settings\n"
drhfeac5f82004-08-01 00:10:45 +0000837 ".tables ?PATTERN? List names of tables matching a LIKE pattern\n"
drh2dfbbca2000-07-28 14:32:48 +0000838 ".timeout MS Try opening locked tables for MS milliseconds\n"
drh75897232000-05-29 14:26:00 +0000839 ".width NUM NUM ... Set column widths for \"column\" mode\n"
840;
841
drhdaffd0e2001-04-11 14:28:42 +0000842/* Forward reference */
drhc28490c2006-10-26 14:25:58 +0000843static int process_input(struct callback_data *p, FILE *in);
drhdaffd0e2001-04-11 14:28:42 +0000844
drh75897232000-05-29 14:26:00 +0000845/*
drh44c2eb12003-04-30 11:38:26 +0000846** Make sure the database is open. If it is not, then open it. If
847** the database fails to open, print an error message and exit.
848*/
849static void open_db(struct callback_data *p){
850 if( p->db==0 ){
danielk19774f057f92004-06-08 00:02:33 +0000851 sqlite3_open(p->zDbFilename, &p->db);
danielk197780290862004-05-22 09:21:21 +0000852 db = p->db;
danielk1977bc6ada42004-06-30 08:20:16 +0000853 sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
854 shellstaticFunc, 0, 0);
danielk197780290862004-05-22 09:21:21 +0000855 if( SQLITE_OK!=sqlite3_errcode(db) ){
856 fprintf(stderr,"Unable to open database \"%s\": %s\n",
857 p->zDbFilename, sqlite3_errmsg(db));
drh22fbcb82004-02-01 01:22:50 +0000858 exit(1);
drh44c2eb12003-04-30 11:38:26 +0000859 }
drhc2e87a32006-06-27 15:16:14 +0000860#ifndef SQLITE_OMIT_LOAD_EXTENSION
861 sqlite3_enable_load_extension(p->db, 1);
862#endif
drh44c2eb12003-04-30 11:38:26 +0000863 }
864}
865
866/*
drhfeac5f82004-08-01 00:10:45 +0000867** Do C-language style dequoting.
868**
869** \t -> tab
870** \n -> newline
871** \r -> carriage return
872** \NNN -> ascii character NNN in octal
873** \\ -> backslash
874*/
875static void resolve_backslashes(char *z){
876 int i, j, c;
877 for(i=j=0; (c = z[i])!=0; i++, j++){
878 if( c=='\\' ){
879 c = z[++i];
880 if( c=='n' ){
881 c = '\n';
882 }else if( c=='t' ){
883 c = '\t';
884 }else if( c=='r' ){
885 c = '\r';
886 }else if( c>='0' && c<='7' ){
drhaa816082005-12-29 12:53:09 +0000887 c -= '0';
drhfeac5f82004-08-01 00:10:45 +0000888 if( z[i+1]>='0' && z[i+1]<='7' ){
889 i++;
890 c = (c<<3) + z[i] - '0';
891 if( z[i+1]>='0' && z[i+1]<='7' ){
892 i++;
893 c = (c<<3) + z[i] - '0';
894 }
895 }
896 }
897 }
898 z[j] = c;
899 }
900 z[j] = 0;
901}
902
903/*
drhc28490c2006-10-26 14:25:58 +0000904** Interpret zArg as a boolean value. Return either 0 or 1.
905*/
906static int booleanValue(char *zArg){
907 int val = atoi(zArg);
908 int j;
909 for(j=0; zArg[j]; j++){
910 zArg[j] = tolower(zArg[j]);
911 }
912 if( strcmp(zArg,"on")==0 ){
913 val = 1;
914 }else if( strcmp(zArg,"yes")==0 ){
915 val = 1;
916 }
917 return val;
918}
919
920/*
drh75897232000-05-29 14:26:00 +0000921** If an input line begins with "." then invoke this routine to
922** process that line.
drh67505e72002-04-19 12:34:06 +0000923**
924** Return 1 to exit and 0 to continue.
drh75897232000-05-29 14:26:00 +0000925*/
drh44c2eb12003-04-30 11:38:26 +0000926static int do_meta_command(char *zLine, struct callback_data *p){
drh75897232000-05-29 14:26:00 +0000927 int i = 1;
928 int nArg = 0;
929 int n, c;
drh67505e72002-04-19 12:34:06 +0000930 int rc = 0;
drh75897232000-05-29 14:26:00 +0000931 char *azArg[50];
932
933 /* Parse the input line into tokens.
934 */
935 while( zLine[i] && nArg<ArraySize(azArg) ){
drh4c755c02004-08-08 20:22:17 +0000936 while( isspace((unsigned char)zLine[i]) ){ i++; }
drh06333682004-03-09 13:37:45 +0000937 if( zLine[i]==0 ) break;
drh75897232000-05-29 14:26:00 +0000938 if( zLine[i]=='\'' || zLine[i]=='"' ){
939 int delim = zLine[i++];
940 azArg[nArg++] = &zLine[i];
941 while( zLine[i] && zLine[i]!=delim ){ i++; }
942 if( zLine[i]==delim ){
943 zLine[i++] = 0;
944 }
drhfeac5f82004-08-01 00:10:45 +0000945 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +0000946 }else{
947 azArg[nArg++] = &zLine[i];
drh4c755c02004-08-08 20:22:17 +0000948 while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; }
drh75897232000-05-29 14:26:00 +0000949 if( zLine[i] ) zLine[i++] = 0;
drhfeac5f82004-08-01 00:10:45 +0000950 resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +0000951 }
952 }
953
954 /* Process the input line.
955 */
drh67505e72002-04-19 12:34:06 +0000956 if( nArg==0 ) return rc;
drh75897232000-05-29 14:26:00 +0000957 n = strlen(azArg[0]);
958 c = azArg[0][0];
drhc49f44e2006-10-26 18:15:42 +0000959 if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
960 bail_on_error = booleanValue(azArg[1]);
961 }else
962
jplyon6a65bb32003-05-04 07:25:57 +0000963 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
jplyon672a1ed2003-05-11 20:07:05 +0000964 struct callback_data data;
965 char *zErrMsg = 0;
jplyon6a65bb32003-05-04 07:25:57 +0000966 open_db(p);
jplyon672a1ed2003-05-11 20:07:05 +0000967 memcpy(&data, p, sizeof(data));
drhd8885442004-03-17 23:42:12 +0000968 data.showHeader = 1;
jplyon672a1ed2003-05-11 20:07:05 +0000969 data.mode = MODE_Column;
drhd8885442004-03-17 23:42:12 +0000970 data.colWidth[0] = 3;
971 data.colWidth[1] = 15;
972 data.colWidth[2] = 58;
drh0b2110c2004-10-26 00:08:10 +0000973 data.cnt = 0;
danielk19776f8a5032004-05-10 10:34:51 +0000974 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
jplyon672a1ed2003-05-11 20:07:05 +0000975 if( zErrMsg ){
976 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +0000977 sqlite3_free(zErrMsg);
jplyon6a65bb32003-05-04 07:25:57 +0000978 }
979 }else
980
drh4c653a02000-06-07 01:27:47 +0000981 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
982 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +0000983 open_db(p);
drh33048c02001-10-01 14:29:22 +0000984 fprintf(p->out, "BEGIN TRANSACTION;\n");
drh4c653a02000-06-07 01:27:47 +0000985 if( nArg==1 ){
drhdd3d4592004-08-30 01:54:05 +0000986 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +0000987 "SELECT name, type, sql FROM sqlite_master "
drh0b9a5942006-09-13 20:22:02 +0000988 "WHERE sql NOT NULL AND type=='table' AND rootpage!=0", 0
drhdd3d4592004-08-30 01:54:05 +0000989 );
990 run_schema_dump_query(p,
991 "SELECT name, type, sql FROM sqlite_master "
drh0b9a5942006-09-13 20:22:02 +0000992 "WHERE sql NOT NULL AND "
993 " AND type!='table' AND type!='meta'", 0
994 );
995 run_table_dump_query(p->out, p->db,
996 "SELECT sql FROM sqlite_master "
997 "WHERE sql NOT NULL AND rootpage==0 AND type='table'"
drha18c5682000-10-08 22:20:57 +0000998 );
drh4c653a02000-06-07 01:27:47 +0000999 }else{
1000 int i;
drhdd3d4592004-08-30 01:54:05 +00001001 for(i=1; i<nArg; i++){
danielk1977bc6ada42004-06-30 08:20:16 +00001002 zShellStatic = azArg[i];
drhdd3d4592004-08-30 01:54:05 +00001003 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +00001004 "SELECT name, type, sql FROM sqlite_master "
drhdd3d4592004-08-30 01:54:05 +00001005 "WHERE tbl_name LIKE shellstatic() AND type=='table'"
drh0b9a5942006-09-13 20:22:02 +00001006 " AND rootpage!=0 AND sql NOT NULL", 0);
drhdd3d4592004-08-30 01:54:05 +00001007 run_schema_dump_query(p,
1008 "SELECT name, type, sql FROM sqlite_master "
1009 "WHERE tbl_name LIKE shellstatic() AND type!='table'"
1010 " AND type!='meta' AND sql NOT NULL", 0);
drh0b9a5942006-09-13 20:22:02 +00001011 run_table_dump_query(p->out, p->db,
1012 "SELECT sql FROM sqlite_master "
1013 "WHERE sql NOT NULL AND rootpage==0 AND type='table'"
1014 " AND tbl_name LIKE shellstatic()"
1015 );
danielk1977bc6ada42004-06-30 08:20:16 +00001016 zShellStatic = 0;
drh4c653a02000-06-07 01:27:47 +00001017 }
1018 }
1019 if( zErrMsg ){
1020 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001021 sqlite3_free(zErrMsg);
drh33048c02001-10-01 14:29:22 +00001022 }else{
1023 fprintf(p->out, "COMMIT;\n");
drh4c653a02000-06-07 01:27:47 +00001024 }
1025 }else
drh75897232000-05-29 14:26:00 +00001026
drhdaffd0e2001-04-11 14:28:42 +00001027 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001028 p->echoOn = booleanValue(azArg[1]);
drhdaffd0e2001-04-11 14:28:42 +00001029 }else
1030
drh75897232000-05-29 14:26:00 +00001031 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
drh67505e72002-04-19 12:34:06 +00001032 rc = 1;
drh75897232000-05-29 14:26:00 +00001033 }else
1034
drhdd45df82002-04-18 12:39:03 +00001035 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
drhc28490c2006-10-26 14:25:58 +00001036 int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
persicom7e2dfdd2002-04-18 02:46:52 +00001037 if(val == 1) {
1038 if(!p->explainPrev.valid) {
1039 p->explainPrev.valid = 1;
1040 p->explainPrev.mode = p->mode;
1041 p->explainPrev.showHeader = p->showHeader;
1042 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
1043 }
1044 /* We could put this code under the !p->explainValid
1045 ** condition so that it does not execute if we are already in
1046 ** explain mode. However, always executing it allows us an easy
1047 ** was to reset to explain mode in case the user previously
1048 ** did an .explain followed by a .width, .mode or .header
1049 ** command.
1050 */
1051 p->mode = MODE_Column;
1052 p->showHeader = 1;
1053 memset(p->colWidth,0,ArraySize(p->colWidth));
1054 p->colWidth[0] = 4;
drhe69cc5b2005-08-27 01:50:53 +00001055 p->colWidth[1] = 14;
persicom7e2dfdd2002-04-18 02:46:52 +00001056 p->colWidth[2] = 10;
1057 p->colWidth[3] = 10;
drhe69cc5b2005-08-27 01:50:53 +00001058 p->colWidth[4] = 33;
persicom7e2dfdd2002-04-18 02:46:52 +00001059 }else if (p->explainPrev.valid) {
1060 p->explainPrev.valid = 0;
1061 p->mode = p->explainPrev.mode;
1062 p->showHeader = p->explainPrev.showHeader;
1063 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
1064 }
drh75897232000-05-29 14:26:00 +00001065 }else
1066
drhc28490c2006-10-26 14:25:58 +00001067 if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
persicom7e2dfdd2002-04-18 02:46:52 +00001068 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001069 p->showHeader = booleanValue(azArg[1]);
drh75897232000-05-29 14:26:00 +00001070 }else
1071
1072 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
1073 fprintf(stderr,zHelp);
1074 }else
1075
drhfeac5f82004-08-01 00:10:45 +00001076 if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
1077 char *zTable = azArg[2]; /* Insert data into this table */
1078 char *zFile = azArg[1]; /* The file from which to extract data */
1079 sqlite3_stmt *pStmt; /* A statement */
1080 int rc; /* Result code */
1081 int nCol; /* Number of columns in the table */
1082 int nByte; /* Number of bytes in an SQL string */
1083 int i, j; /* Loop counters */
1084 int nSep; /* Number of bytes in p->separator[] */
1085 char *zSql; /* An SQL statement */
1086 char *zLine; /* A single line of input from the file */
1087 char **azCol; /* zLine[] broken up into columns */
1088 char *zCommit; /* How to commit changes */
drhb860bc92004-08-04 15:16:55 +00001089 FILE *in; /* The input file */
1090 int lineno = 0; /* Line number of input file */
drhfeac5f82004-08-01 00:10:45 +00001091
drha543c822006-06-08 16:10:14 +00001092 open_db(p);
drhfeac5f82004-08-01 00:10:45 +00001093 nSep = strlen(p->separator);
1094 if( nSep==0 ){
1095 fprintf(stderr, "non-null separator required for import\n");
1096 return 0;
1097 }
1098 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
1099 if( zSql==0 ) return 0;
1100 nByte = strlen(zSql);
drh5e6078b2006-01-31 19:07:22 +00001101 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001102 sqlite3_free(zSql);
1103 if( rc ){
1104 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1105 nCol = 0;
1106 }else{
1107 nCol = sqlite3_column_count(pStmt);
1108 }
1109 sqlite3_finalize(pStmt);
1110 if( nCol==0 ) return 0;
1111 zSql = malloc( nByte + 20 + nCol*2 );
1112 if( zSql==0 ) return 0;
1113 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
1114 j = strlen(zSql);
1115 for(i=1; i<nCol; i++){
1116 zSql[j++] = ',';
1117 zSql[j++] = '?';
1118 }
1119 zSql[j++] = ')';
1120 zSql[j] = 0;
drh5e6078b2006-01-31 19:07:22 +00001121 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001122 free(zSql);
1123 if( rc ){
1124 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
1125 sqlite3_finalize(pStmt);
1126 return 0;
1127 }
1128 in = fopen(zFile, "rb");
1129 if( in==0 ){
1130 fprintf(stderr, "cannot open file: %s\n", zFile);
1131 sqlite3_finalize(pStmt);
1132 return 0;
1133 }
1134 azCol = malloc( sizeof(azCol[0])*(nCol+1) );
drh43617e92006-03-06 20:55:46 +00001135 if( azCol==0 ){
1136 fclose(in);
1137 return 0;
1138 }
drhfeac5f82004-08-01 00:10:45 +00001139 sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
1140 zCommit = "COMMIT";
1141 while( (zLine = local_getline(0, in))!=0 ){
1142 char *z;
1143 i = 0;
drhb860bc92004-08-04 15:16:55 +00001144 lineno++;
drhfeac5f82004-08-01 00:10:45 +00001145 azCol[0] = zLine;
drh36d4e972004-10-06 14:39:06 +00001146 for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){
drhfeac5f82004-08-01 00:10:45 +00001147 if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
1148 *z = 0;
1149 i++;
drhb860bc92004-08-04 15:16:55 +00001150 if( i<nCol ){
1151 azCol[i] = &z[nSep];
1152 z += nSep-1;
1153 }
drhfeac5f82004-08-01 00:10:45 +00001154 }
1155 }
drh1cd7f832005-08-05 18:50:51 +00001156 *z = 0;
drhb860bc92004-08-04 15:16:55 +00001157 if( i+1!=nCol ){
1158 fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
1159 zFile, lineno, nCol, i+1);
1160 zCommit = "ROLLBACK";
1161 break;
1162 }
drhfeac5f82004-08-01 00:10:45 +00001163 for(i=0; i<nCol; i++){
1164 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
1165 }
1166 sqlite3_step(pStmt);
1167 rc = sqlite3_reset(pStmt);
1168 free(zLine);
1169 if( rc!=SQLITE_OK ){
1170 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1171 zCommit = "ROLLBACK";
1172 break;
1173 }
1174 }
1175 free(azCol);
1176 fclose(in);
1177 sqlite3_finalize(pStmt);
drhb860bc92004-08-04 15:16:55 +00001178 sqlite3_exec(p->db, zCommit, 0, 0, 0);
drhfeac5f82004-08-01 00:10:45 +00001179 }else
1180
drh75897232000-05-29 14:26:00 +00001181 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
1182 struct callback_data data;
1183 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001184 open_db(p);
drh75897232000-05-29 14:26:00 +00001185 memcpy(&data, p, sizeof(data));
1186 data.showHeader = 0;
1187 data.mode = MODE_List;
danielk1977bc6ada42004-06-30 08:20:16 +00001188 zShellStatic = azArg[1];
1189 sqlite3_exec(p->db,
drha18c5682000-10-08 22:20:57 +00001190 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001191 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001192 "UNION ALL "
1193 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001194 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001195 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001196 callback, &data, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001197 );
danielk1977bc6ada42004-06-30 08:20:16 +00001198 zShellStatic = 0;
drh75897232000-05-29 14:26:00 +00001199 if( zErrMsg ){
1200 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001201 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001202 }
1203 }else
1204
drh70df4fe2006-06-13 15:12:21 +00001205#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +00001206 if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
1207 const char *zFile, *zProc;
1208 char *zErrMsg = 0;
1209 int rc;
1210 zFile = azArg[1];
1211 zProc = nArg>=3 ? azArg[2] : 0;
1212 open_db(p);
1213 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
1214 if( rc!=SQLITE_OK ){
1215 fprintf(stderr, "%s\n", zErrMsg);
1216 sqlite3_free(zErrMsg);
1217 }
1218 }else
drh70df4fe2006-06-13 15:12:21 +00001219#endif
drh1e397f82006-06-08 15:28:43 +00001220
drh28bd4bc2000-06-15 15:57:22 +00001221 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
drh75897232000-05-29 14:26:00 +00001222 int n2 = strlen(azArg[1]);
persicom7e2dfdd2002-04-18 02:46:52 +00001223 if( strncmp(azArg[1],"line",n2)==0
1224 ||
1225 strncmp(azArg[1],"lines",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001226 p->mode = MODE_Line;
persicom7e2dfdd2002-04-18 02:46:52 +00001227 }else if( strncmp(azArg[1],"column",n2)==0
1228 ||
1229 strncmp(azArg[1],"columns",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001230 p->mode = MODE_Column;
1231 }else if( strncmp(azArg[1],"list",n2)==0 ){
1232 p->mode = MODE_List;
drh1e5d0e92000-05-31 23:33:17 +00001233 }else if( strncmp(azArg[1],"html",n2)==0 ){
1234 p->mode = MODE_Html;
drhfeac5f82004-08-01 00:10:45 +00001235 }else if( strncmp(azArg[1],"tcl",n2)==0 ){
1236 p->mode = MODE_Tcl;
1237 }else if( strncmp(azArg[1],"csv",n2)==0 ){
drh8e64d1c2004-10-07 00:32:39 +00001238 p->mode = MODE_Csv;
drhfeac5f82004-08-01 00:10:45 +00001239 strcpy(p->separator, ",");
1240 }else if( strncmp(azArg[1],"tabs",n2)==0 ){
1241 p->mode = MODE_List;
1242 strcpy(p->separator, "\t");
drh28bd4bc2000-06-15 15:57:22 +00001243 }else if( strncmp(azArg[1],"insert",n2)==0 ){
1244 p->mode = MODE_Insert;
1245 if( nArg>=3 ){
drh33048c02001-10-01 14:29:22 +00001246 set_table_name(p, azArg[2]);
drh28bd4bc2000-06-15 15:57:22 +00001247 }else{
drh33048c02001-10-01 14:29:22 +00001248 set_table_name(p, "table");
drh28bd4bc2000-06-15 15:57:22 +00001249 }
drhdaffd0e2001-04-11 14:28:42 +00001250 }else {
drhfeac5f82004-08-01 00:10:45 +00001251 fprintf(stderr,"mode should be on of: "
1252 "column csv html insert line list tabs tcl\n");
drh75897232000-05-29 14:26:00 +00001253 }
1254 }else
1255
persicom7e2dfdd2002-04-18 02:46:52 +00001256 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
1257 sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
1258 }else
1259
drh75897232000-05-29 14:26:00 +00001260 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
1261 if( p->out!=stdout ){
1262 fclose(p->out);
1263 }
1264 if( strcmp(azArg[1],"stdout")==0 ){
1265 p->out = stdout;
persicom7e2dfdd2002-04-18 02:46:52 +00001266 strcpy(p->outfile,"stdout");
drh75897232000-05-29 14:26:00 +00001267 }else{
drha1f9b5e2004-02-14 16:31:02 +00001268 p->out = fopen(azArg[1], "wb");
drh75897232000-05-29 14:26:00 +00001269 if( p->out==0 ){
1270 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
1271 p->out = stdout;
persicom7e2dfdd2002-04-18 02:46:52 +00001272 } else {
1273 strcpy(p->outfile,azArg[1]);
drh75897232000-05-29 14:26:00 +00001274 }
1275 }
1276 }else
1277
drhdd45df82002-04-18 12:39:03 +00001278 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
persicom7e2dfdd2002-04-18 02:46:52 +00001279 if( nArg >= 2) {
1280 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
1281 }
1282 if( nArg >= 3) {
1283 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
1284 }
1285 }else
1286
1287 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
drhf73287c2004-02-25 02:25:37 +00001288 rc = 1;
persicom7e2dfdd2002-04-18 02:46:52 +00001289 }else
1290
drhdaffd0e2001-04-11 14:28:42 +00001291 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
drha1f9b5e2004-02-14 16:31:02 +00001292 FILE *alt = fopen(azArg[1], "rb");
drhdaffd0e2001-04-11 14:28:42 +00001293 if( alt==0 ){
1294 fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
1295 }else{
1296 process_input(p, alt);
1297 fclose(alt);
1298 }
1299 }else
1300
drh75897232000-05-29 14:26:00 +00001301 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
1302 struct callback_data data;
1303 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001304 open_db(p);
drh75897232000-05-29 14:26:00 +00001305 memcpy(&data, p, sizeof(data));
1306 data.showHeader = 0;
drhe3710332000-09-29 13:30:53 +00001307 data.mode = MODE_Semi;
drh75897232000-05-29 14:26:00 +00001308 if( nArg>1 ){
drhc8d74412004-08-31 23:41:26 +00001309 int i;
1310 for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]);
1311 if( strcmp(azArg[1],"sqlite_master")==0 ){
drha18c5682000-10-08 22:20:57 +00001312 char *new_argv[2], *new_colv[2];
1313 new_argv[0] = "CREATE TABLE sqlite_master (\n"
1314 " type text,\n"
1315 " name text,\n"
1316 " tbl_name text,\n"
drhadbca9c2001-09-27 15:11:53 +00001317 " rootpage integer,\n"
drha18c5682000-10-08 22:20:57 +00001318 " sql text\n"
1319 ")";
1320 new_argv[1] = 0;
1321 new_colv[0] = "sql";
1322 new_colv[1] = 0;
1323 callback(&data, 1, new_argv, new_colv);
drhc8d74412004-08-31 23:41:26 +00001324 }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){
drhe0bc4042002-06-25 01:09:11 +00001325 char *new_argv[2], *new_colv[2];
1326 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
1327 " type text,\n"
1328 " name text,\n"
1329 " tbl_name text,\n"
1330 " rootpage integer,\n"
1331 " sql text\n"
1332 ")";
1333 new_argv[1] = 0;
1334 new_colv[0] = "sql";
1335 new_colv[1] = 0;
1336 callback(&data, 1, new_argv, new_colv);
drha18c5682000-10-08 22:20:57 +00001337 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001338 zShellStatic = azArg[1];
1339 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001340 "SELECT sql FROM "
1341 " (SELECT * FROM sqlite_master UNION ALL"
1342 " SELECT * FROM sqlite_temp_master) "
danielk1977bc6ada42004-06-30 08:20:16 +00001343 "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL "
drhe0bc4042002-06-25 01:09:11 +00001344 "ORDER BY substr(type,2,1), name",
danielk1977bc6ada42004-06-30 08:20:16 +00001345 callback, &data, &zErrMsg);
1346 zShellStatic = 0;
drha18c5682000-10-08 22:20:57 +00001347 }
drh75897232000-05-29 14:26:00 +00001348 }else{
danielk19776f8a5032004-05-10 10:34:51 +00001349 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001350 "SELECT sql FROM "
1351 " (SELECT * FROM sqlite_master UNION ALL"
1352 " SELECT * FROM sqlite_temp_master) "
drh0c356672005-09-10 22:40:53 +00001353 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001354 "ORDER BY substr(type,2,1), name",
drha18c5682000-10-08 22:20:57 +00001355 callback, &data, &zErrMsg
1356 );
drh75897232000-05-29 14:26:00 +00001357 }
drh75897232000-05-29 14:26:00 +00001358 if( zErrMsg ){
1359 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001360 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001361 }
1362 }else
1363
1364 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
1365 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
1366 }else
1367
persicom7e2dfdd2002-04-18 02:46:52 +00001368 if( c=='s' && strncmp(azArg[0], "show", n)==0){
1369 int i;
1370 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
drh67505e72002-04-19 12:34:06 +00001371 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
drhdd45df82002-04-18 12:39:03 +00001372 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
persicom7e2dfdd2002-04-18 02:46:52 +00001373 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
drhfeac5f82004-08-01 00:10:45 +00001374 fprintf(p->out,"%9.9s: ", "nullvalue");
1375 output_c_string(p->out, p->nullvalue);
1376 fprintf(p->out, "\n");
drh67505e72002-04-19 12:34:06 +00001377 fprintf(p->out,"%9.9s: %s\n","output",
1378 strlen(p->outfile) ? p->outfile : "stdout");
drhfeac5f82004-08-01 00:10:45 +00001379 fprintf(p->out,"%9.9s: ", "separator");
1380 output_c_string(p->out, p->separator);
1381 fprintf(p->out, "\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001382 fprintf(p->out,"%9.9s: ","width");
1383 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
drhfeac5f82004-08-01 00:10:45 +00001384 fprintf(p->out,"%d ",p->colWidth[i]);
persicom7e2dfdd2002-04-18 02:46:52 +00001385 }
drhfeac5f82004-08-01 00:10:45 +00001386 fprintf(p->out,"\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001387 }else
1388
drh2dfbbca2000-07-28 14:32:48 +00001389 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
drhe3710332000-09-29 13:30:53 +00001390 char **azResult;
1391 int nRow, rc;
1392 char *zErrMsg;
drh44c2eb12003-04-30 11:38:26 +00001393 open_db(p);
drha50da102000-08-08 20:19:09 +00001394 if( nArg==1 ){
danielk19776f8a5032004-05-10 10:34:51 +00001395 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001396 "SELECT name FROM sqlite_master "
drh0c356672005-09-10 22:40:53 +00001397 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001398 "UNION ALL "
1399 "SELECT name FROM sqlite_temp_master "
1400 "WHERE type IN ('table','view') "
1401 "ORDER BY 1",
drha18c5682000-10-08 22:20:57 +00001402 &azResult, &nRow, 0, &zErrMsg
1403 );
drha50da102000-08-08 20:19:09 +00001404 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001405 zShellStatic = azArg[1];
1406 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001407 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001408 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001409 "UNION ALL "
1410 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001411 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001412 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001413 &azResult, &nRow, 0, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001414 );
danielk1977bc6ada42004-06-30 08:20:16 +00001415 zShellStatic = 0;
drha50da102000-08-08 20:19:09 +00001416 }
drh75897232000-05-29 14:26:00 +00001417 if( zErrMsg ){
1418 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001419 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001420 }
drhe3710332000-09-29 13:30:53 +00001421 if( rc==SQLITE_OK ){
1422 int len, maxlen = 0;
1423 int i, j;
1424 int nPrintCol, nPrintRow;
1425 for(i=1; i<=nRow; i++){
1426 if( azResult[i]==0 ) continue;
1427 len = strlen(azResult[i]);
1428 if( len>maxlen ) maxlen = len;
1429 }
1430 nPrintCol = 80/(maxlen+2);
1431 if( nPrintCol<1 ) nPrintCol = 1;
1432 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
1433 for(i=0; i<nPrintRow; i++){
1434 for(j=i+1; j<=nRow; j+=nPrintRow){
1435 char *zSp = j<=nPrintRow ? "" : " ";
1436 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
1437 }
1438 printf("\n");
1439 }
1440 }
danielk19776f8a5032004-05-10 10:34:51 +00001441 sqlite3_free_table(azResult);
drh75897232000-05-29 14:26:00 +00001442 }else
1443
drh2dfbbca2000-07-28 14:32:48 +00001444 if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
drh44c2eb12003-04-30 11:38:26 +00001445 open_db(p);
danielk19776f8a5032004-05-10 10:34:51 +00001446 sqlite3_busy_timeout(p->db, atoi(azArg[1]));
drh2dfbbca2000-07-28 14:32:48 +00001447 }else
1448
drh75897232000-05-29 14:26:00 +00001449 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
1450 int j;
drh43617e92006-03-06 20:55:46 +00001451 assert( nArg<=ArraySize(azArg) );
drh75897232000-05-29 14:26:00 +00001452 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
1453 p->colWidth[j-1] = atoi(azArg[j]);
1454 }
1455 }else
1456
1457 {
drh67505e72002-04-19 12:34:06 +00001458 fprintf(stderr, "unknown command or invalid arguments: "
1459 " \"%s\". Enter \".help\" for help\n", azArg[0]);
drh75897232000-05-29 14:26:00 +00001460 }
drh67505e72002-04-19 12:34:06 +00001461
1462 return rc;
drh75897232000-05-29 14:26:00 +00001463}
1464
drh67505e72002-04-19 12:34:06 +00001465/*
drh324ccef2003-02-05 14:06:20 +00001466** Return TRUE if the last non-whitespace character in z[] is a semicolon.
1467** z[] is N characters long.
1468*/
1469static int _ends_with_semicolon(const char *z, int N){
drh4c755c02004-08-08 20:22:17 +00001470 while( N>0 && isspace((unsigned char)z[N-1]) ){ N--; }
drh324ccef2003-02-05 14:06:20 +00001471 return N>0 && z[N-1]==';';
1472}
1473
1474/*
drh70c7a4b2003-04-26 03:03:06 +00001475** Test to see if a line consists entirely of whitespace.
1476*/
1477static int _all_whitespace(const char *z){
1478 for(; *z; z++){
drh4c755c02004-08-08 20:22:17 +00001479 if( isspace(*(unsigned char*)z) ) continue;
drh70c7a4b2003-04-26 03:03:06 +00001480 if( *z=='/' && z[1]=='*' ){
1481 z += 2;
1482 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
1483 if( *z==0 ) return 0;
1484 z++;
1485 continue;
1486 }
1487 if( *z=='-' && z[1]=='-' ){
1488 z += 2;
1489 while( *z && *z!='\n' ){ z++; }
1490 if( *z==0 ) return 1;
1491 continue;
1492 }
1493 return 0;
1494 }
1495 return 1;
1496}
1497
1498/*
drha9b17162003-04-29 18:01:28 +00001499** Return TRUE if the line typed in is an SQL command terminator other
1500** than a semi-colon. The SQL Server style "go" command is understood
1501** as is the Oracle "/".
1502*/
1503static int _is_command_terminator(const char *zLine){
drh4c755c02004-08-08 20:22:17 +00001504 while( isspace(*(unsigned char*)zLine) ){ zLine++; };
drha9b17162003-04-29 18:01:28 +00001505 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */
drhc8d74412004-08-31 23:41:26 +00001506 if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o'
1507 && _all_whitespace(&zLine[2]) ){
drha9b17162003-04-29 18:01:28 +00001508 return 1; /* SQL Server */
1509 }
1510 return 0;
1511}
1512
1513/*
drh67505e72002-04-19 12:34:06 +00001514** Read input from *in and process it. If *in==0 then input
1515** is interactive - the user is typing it it. Otherwise, input
1516** is coming from a file or device. A prompt is issued and history
1517** is saved only if input is interactive. An interrupt signal will
1518** cause this routine to exit immediately, unless input is interactive.
drhc28490c2006-10-26 14:25:58 +00001519**
1520** Return the number of errors.
drh67505e72002-04-19 12:34:06 +00001521*/
drhc28490c2006-10-26 14:25:58 +00001522static int process_input(struct callback_data *p, FILE *in){
drhdaffd0e2001-04-11 14:28:42 +00001523 char *zLine;
1524 char *zSql = 0;
1525 int nSql = 0;
1526 char *zErrMsg;
drhc49f44e2006-10-26 18:15:42 +00001527 int rc;
1528 int errCnt = 0;
drhc28490c2006-10-26 14:25:58 +00001529 int lineno = 0;
1530 int startline = 0;
drhc49f44e2006-10-26 18:15:42 +00001531
1532 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
1533 fflush(p->out);
1534 zLine = one_input_line(zSql, in);
1535 if( zLine==0 ){
1536 break; /* We have reached EOF */
1537 }
drh67505e72002-04-19 12:34:06 +00001538 if( seenInterrupt ){
1539 if( in!=0 ) break;
1540 seenInterrupt = 0;
1541 }
drhc28490c2006-10-26 14:25:58 +00001542 lineno++;
drhdaffd0e2001-04-11 14:28:42 +00001543 if( p->echoOn ) printf("%s\n", zLine);
drhf817b6b2003-06-16 00:16:41 +00001544 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
drh2af0b2d2002-02-21 02:25:02 +00001545 if( zLine && zLine[0]=='.' && nSql==0 ){
drhc49f44e2006-10-26 18:15:42 +00001546 rc = do_meta_command(zLine, p);
drhdaffd0e2001-04-11 14:28:42 +00001547 free(zLine);
drhc49f44e2006-10-26 18:15:42 +00001548 if( rc ){
1549 errCnt++;
1550 }
drhdaffd0e2001-04-11 14:28:42 +00001551 continue;
1552 }
drha9b17162003-04-29 18:01:28 +00001553 if( _is_command_terminator(zLine) ){
1554 strcpy(zLine,";");
1555 }
drhdaffd0e2001-04-11 14:28:42 +00001556 if( zSql==0 ){
1557 int i;
drh4c755c02004-08-08 20:22:17 +00001558 for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){}
drhdaffd0e2001-04-11 14:28:42 +00001559 if( zLine[i]!=0 ){
1560 nSql = strlen(zLine);
1561 zSql = malloc( nSql+1 );
drhc1f44942006-05-10 14:39:13 +00001562 if( zSql==0 ){
1563 fprintf(stderr, "out of memory\n");
1564 exit(1);
1565 }
drhdaffd0e2001-04-11 14:28:42 +00001566 strcpy(zSql, zLine);
drhc28490c2006-10-26 14:25:58 +00001567 startline = lineno;
drhdaffd0e2001-04-11 14:28:42 +00001568 }
1569 }else{
1570 int len = strlen(zLine);
1571 zSql = realloc( zSql, nSql + len + 2 );
1572 if( zSql==0 ){
1573 fprintf(stderr,"%s: out of memory!\n", Argv0);
1574 exit(1);
1575 }
1576 strcpy(&zSql[nSql++], "\n");
1577 strcpy(&zSql[nSql], zLine);
1578 nSql += len;
1579 }
1580 free(zLine);
danielk19776f8a5032004-05-10 10:34:51 +00001581 if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){
drhdaffd0e2001-04-11 14:28:42 +00001582 p->cnt = 0;
drh44c2eb12003-04-30 11:38:26 +00001583 open_db(p);
danielk19776f8a5032004-05-10 10:34:51 +00001584 rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
drh7f953e22002-07-13 17:33:45 +00001585 if( rc || zErrMsg ){
drhc28490c2006-10-26 14:25:58 +00001586 char zPrefix[100];
1587 if( in!=0 || !stdin_is_interactive ){
1588 sprintf(zPrefix, "SQL error near line %d:", startline);
1589 }else{
1590 sprintf(zPrefix, "SQL error:");
1591 }
drh7f953e22002-07-13 17:33:45 +00001592 if( zErrMsg!=0 ){
drhc28490c2006-10-26 14:25:58 +00001593 printf("%s %s\n", zPrefix, zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001594 sqlite3_free(zErrMsg);
drh7f953e22002-07-13 17:33:45 +00001595 zErrMsg = 0;
1596 }else{
drhc28490c2006-10-26 14:25:58 +00001597 printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
drh7f953e22002-07-13 17:33:45 +00001598 }
drhc49f44e2006-10-26 18:15:42 +00001599 errCnt++;
drhdaffd0e2001-04-11 14:28:42 +00001600 }
1601 free(zSql);
1602 zSql = 0;
1603 nSql = 0;
1604 }
1605 }
1606 if( zSql ){
drh70c7a4b2003-04-26 03:03:06 +00001607 if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
drhdaffd0e2001-04-11 14:28:42 +00001608 free(zSql);
1609 }
drhc49f44e2006-10-26 18:15:42 +00001610 return errCnt;
drhdaffd0e2001-04-11 14:28:42 +00001611}
1612
drh67505e72002-04-19 12:34:06 +00001613/*
1614** Return a pathname which is the user's home directory. A
1615** 0 return indicates an error of some kind. Space to hold the
1616** resulting string is obtained from malloc(). The calling
1617** function should free the result.
1618*/
1619static char *find_home_dir(void){
1620 char *home_dir = NULL;
persicom7e2dfdd2002-04-18 02:46:52 +00001621
drhcdb36b72006-06-12 12:57:45 +00001622#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
drh67505e72002-04-19 12:34:06 +00001623 struct passwd *pwent;
1624 uid_t uid = getuid();
drhbd842ba2002-08-21 11:26:41 +00001625 if( (pwent=getpwuid(uid)) != NULL) {
1626 home_dir = pwent->pw_dir;
drh67505e72002-04-19 12:34:06 +00001627 }
1628#endif
1629
drh820f3812003-01-08 13:02:52 +00001630#ifdef __MACOS__
1631 char home_path[_MAX_PATH+1];
1632 home_dir = getcwd(home_path, _MAX_PATH);
1633#endif
1634
drh164a1b62006-08-19 11:15:20 +00001635#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
1636 if (!home_dir) {
1637 home_dir = getenv("USERPROFILE");
1638 }
1639#endif
1640
drh67505e72002-04-19 12:34:06 +00001641 if (!home_dir) {
1642 home_dir = getenv("HOME");
drh67505e72002-04-19 12:34:06 +00001643 }
1644
drhcdb36b72006-06-12 12:57:45 +00001645#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
drhe98d4fa2002-04-21 19:06:22 +00001646 if (!home_dir) {
drh164a1b62006-08-19 11:15:20 +00001647 char *zDrive, *zPath;
1648 int n;
1649 zDrive = getenv("HOMEDRIVE");
1650 zPath = getenv("HOMEPATH");
1651 if( zDrive && zPath ){
1652 n = strlen(zDrive) + strlen(zPath) + 1;
1653 home_dir = malloc( n );
1654 if( home_dir==0 ) return 0;
1655 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
1656 return home_dir;
1657 }
1658 home_dir = "c:\\";
drhe98d4fa2002-04-21 19:06:22 +00001659 }
1660#endif
1661
drh67505e72002-04-19 12:34:06 +00001662 if( home_dir ){
1663 char *z = malloc( strlen(home_dir)+1 );
1664 if( z ) strcpy(z, home_dir);
1665 home_dir = z;
1666 }
drhe98d4fa2002-04-21 19:06:22 +00001667
drh67505e72002-04-19 12:34:06 +00001668 return home_dir;
1669}
1670
1671/*
1672** Read input from the file given by sqliterc_override. Or if that
1673** parameter is NULL, take input from ~/.sqliterc
1674*/
drh22fbcb82004-02-01 01:22:50 +00001675static void process_sqliterc(
1676 struct callback_data *p, /* Configuration data */
1677 const char *sqliterc_override /* Name of config file. NULL to use default */
1678){
persicom7e2dfdd2002-04-18 02:46:52 +00001679 char *home_dir = NULL;
drh22fbcb82004-02-01 01:22:50 +00001680 const char *sqliterc = sqliterc_override;
drh43617e92006-03-06 20:55:46 +00001681 char *zBuf = 0;
persicom7e2dfdd2002-04-18 02:46:52 +00001682 FILE *in = NULL;
1683
1684 if (sqliterc == NULL) {
drh67505e72002-04-19 12:34:06 +00001685 home_dir = find_home_dir();
drhe98d4fa2002-04-21 19:06:22 +00001686 if( home_dir==0 ){
1687 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
1688 return;
1689 }
drh22fbcb82004-02-01 01:22:50 +00001690 zBuf = malloc(strlen(home_dir) + 15);
1691 if( zBuf==0 ){
persicom7e2dfdd2002-04-18 02:46:52 +00001692 fprintf(stderr,"%s: out of memory!\n", Argv0);
1693 exit(1);
1694 }
drh22fbcb82004-02-01 01:22:50 +00001695 sprintf(zBuf,"%s/.sqliterc",home_dir);
drh67505e72002-04-19 12:34:06 +00001696 free(home_dir);
drh22fbcb82004-02-01 01:22:50 +00001697 sqliterc = (const char*)zBuf;
persicom7e2dfdd2002-04-18 02:46:52 +00001698 }
drha1f9b5e2004-02-14 16:31:02 +00001699 in = fopen(sqliterc,"rb");
drh22fbcb82004-02-01 01:22:50 +00001700 if( in ){
drhc28490c2006-10-26 14:25:58 +00001701 if( stdin_is_interactive ){
drh22fbcb82004-02-01 01:22:50 +00001702 printf("Loading resources from %s\n",sqliterc);
1703 }
persicom7e2dfdd2002-04-18 02:46:52 +00001704 process_input(p,in);
drhdd45df82002-04-18 12:39:03 +00001705 fclose(in);
persicom7e2dfdd2002-04-18 02:46:52 +00001706 }
drh43617e92006-03-06 20:55:46 +00001707 free(zBuf);
persicom7e2dfdd2002-04-18 02:46:52 +00001708 return;
1709}
1710
drh67505e72002-04-19 12:34:06 +00001711/*
drhe1e38c42003-05-04 18:30:59 +00001712** Show available command line options
1713*/
1714static const char zOptions[] =
1715 " -init filename read/process named file\n"
1716 " -echo print commands before execution\n"
1717 " -[no]header turn headers on or off\n"
drhc49f44e2006-10-26 18:15:42 +00001718 " -bail stop after hitting an error\n"
1719 " -interactive force interactive I/O\n"
1720 " -batch force batch I/O\n"
drhe1e38c42003-05-04 18:30:59 +00001721 " -column set output mode to 'column'\n"
drhc49f44e2006-10-26 18:15:42 +00001722 " -csv set output mode to 'csv'\n"
drhe1e38c42003-05-04 18:30:59 +00001723 " -html set output mode to HTML\n"
1724 " -line set output mode to 'line'\n"
1725 " -list set output mode to 'list'\n"
1726 " -separator 'x' set output field separator (|)\n"
1727 " -nullvalue 'text' set text string for NULL values\n"
1728 " -version show SQLite version\n"
drhe1e38c42003-05-04 18:30:59 +00001729;
1730static void usage(int showDetail){
drh80e8be92006-08-29 12:04:19 +00001731 fprintf(stderr,
1732 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
1733 "FILENAME is the name of an SQLite database. A new database is created\n"
1734 "if the file does not previously exist.\n", Argv0);
drhe1e38c42003-05-04 18:30:59 +00001735 if( showDetail ){
drh80e8be92006-08-29 12:04:19 +00001736 fprintf(stderr, "OPTIONS include:\n%s", zOptions);
drhe1e38c42003-05-04 18:30:59 +00001737 }else{
1738 fprintf(stderr, "Use the -help option for additional information\n");
1739 }
1740 exit(1);
1741}
1742
1743/*
drh67505e72002-04-19 12:34:06 +00001744** Initialize the state information in data
1745*/
drh0850b532006-01-31 19:31:43 +00001746static void main_init(struct callback_data *data) {
persicom7e2dfdd2002-04-18 02:46:52 +00001747 memset(data, 0, sizeof(*data));
1748 data->mode = MODE_List;
1749 strcpy(data->separator,"|");
1750 data->showHeader = 0;
1751 strcpy(mainPrompt,"sqlite> ");
1752 strcpy(continuePrompt," ...> ");
1753}
1754
drh75897232000-05-29 14:26:00 +00001755int main(int argc, char **argv){
drh75897232000-05-29 14:26:00 +00001756 char *zErrMsg = 0;
1757 struct callback_data data;
drh22fbcb82004-02-01 01:22:50 +00001758 const char *zInitFile = 0;
1759 char *zFirstCmd = 0;
drh44c2eb12003-04-30 11:38:26 +00001760 int i;
drhc28490c2006-10-26 14:25:58 +00001761 int rc = 0;
drh75897232000-05-29 14:26:00 +00001762
drh820f3812003-01-08 13:02:52 +00001763#ifdef __MACOS__
1764 argc = ccommand(&argv);
drh820f3812003-01-08 13:02:52 +00001765#endif
1766
drhdaffd0e2001-04-11 14:28:42 +00001767 Argv0 = argv[0];
persicom7e2dfdd2002-04-18 02:46:52 +00001768 main_init(&data);
drhc28490c2006-10-26 14:25:58 +00001769 stdin_is_interactive = isatty(0);
persicom7e2dfdd2002-04-18 02:46:52 +00001770
drh44c2eb12003-04-30 11:38:26 +00001771 /* Make sure we have a valid signal handler early, before anything
1772 ** else is done.
1773 */
drh4c504392000-10-16 22:06:40 +00001774#ifdef SIGINT
1775 signal(SIGINT, interrupt_handler);
1776#endif
drh44c2eb12003-04-30 11:38:26 +00001777
drh22fbcb82004-02-01 01:22:50 +00001778 /* Do an initial pass through the command-line argument to locate
1779 ** the name of the database file, the name of the initialization file,
1780 ** and the first command to execute.
drh44c2eb12003-04-30 11:38:26 +00001781 */
drh22fbcb82004-02-01 01:22:50 +00001782 for(i=1; i<argc-1; i++){
drhc28490c2006-10-26 14:25:58 +00001783 char *z;
drh44c2eb12003-04-30 11:38:26 +00001784 if( argv[i][0]!='-' ) break;
drhc28490c2006-10-26 14:25:58 +00001785 z = argv[i];
1786 if( z[0]=='-' && z[1]=='-' ) z++;
drh44c2eb12003-04-30 11:38:26 +00001787 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
1788 i++;
drh22fbcb82004-02-01 01:22:50 +00001789 }else if( strcmp(argv[i],"-init")==0 ){
1790 i++;
1791 zInitFile = argv[i];
drh44c2eb12003-04-30 11:38:26 +00001792 }
1793 }
drh22fbcb82004-02-01 01:22:50 +00001794 if( i<argc ){
1795 data.zDbFilename = argv[i++];
1796 }else{
danielk197703aded42004-11-22 05:26:27 +00001797#ifndef SQLITE_OMIT_MEMORYDB
drh22fbcb82004-02-01 01:22:50 +00001798 data.zDbFilename = ":memory:";
danielk197703aded42004-11-22 05:26:27 +00001799#else
1800 data.zDbFilename = 0;
1801#endif
drh22fbcb82004-02-01 01:22:50 +00001802 }
1803 if( i<argc ){
1804 zFirstCmd = argv[i++];
1805 }
drh44c2eb12003-04-30 11:38:26 +00001806 data.out = stdout;
1807
drh01b41712005-08-29 23:06:23 +00001808#ifdef SQLITE_OMIT_MEMORYDB
1809 if( data.zDbFilename==0 ){
1810 fprintf(stderr,"%s: no database filename specified\n", argv[0]);
1811 exit(1);
1812 }
1813#endif
1814
drh44c2eb12003-04-30 11:38:26 +00001815 /* Go ahead and open the database file if it already exists. If the
1816 ** file does not exist, delay opening it. This prevents empty database
1817 ** files from being created if a user mistypes the database name argument
1818 ** to the sqlite command-line tool.
1819 */
drhc8d74412004-08-31 23:41:26 +00001820 if( access(data.zDbFilename, 0)==0 ){
drh44c2eb12003-04-30 11:38:26 +00001821 open_db(&data);
1822 }
1823
drh22fbcb82004-02-01 01:22:50 +00001824 /* Process the initialization file if there is one. If no -init option
1825 ** is given on the command line, look for a file named ~/.sqliterc and
1826 ** try to process it.
drh44c2eb12003-04-30 11:38:26 +00001827 */
drh22fbcb82004-02-01 01:22:50 +00001828 process_sqliterc(&data,zInitFile);
drh44c2eb12003-04-30 11:38:26 +00001829
drh22fbcb82004-02-01 01:22:50 +00001830 /* Make a second pass through the command-line argument and set
1831 ** options. This second pass is delayed until after the initialization
1832 ** file is processed so that the command-line arguments will override
1833 ** settings in the initialization file.
drh44c2eb12003-04-30 11:38:26 +00001834 */
drh22fbcb82004-02-01 01:22:50 +00001835 for(i=1; i<argc && argv[i][0]=='-'; i++){
1836 char *z = argv[i];
drhc28490c2006-10-26 14:25:58 +00001837 if( z[1]=='-' ){ z++; }
drh2e584cd2006-09-25 13:09:22 +00001838 if( strcmp(z,"-init")==0 ){
drh22fbcb82004-02-01 01:22:50 +00001839 i++;
1840 }else if( strcmp(z,"-html")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001841 data.mode = MODE_Html;
drh22fbcb82004-02-01 01:22:50 +00001842 }else if( strcmp(z,"-list")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001843 data.mode = MODE_List;
drh22fbcb82004-02-01 01:22:50 +00001844 }else if( strcmp(z,"-line")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001845 data.mode = MODE_Line;
drh22fbcb82004-02-01 01:22:50 +00001846 }else if( strcmp(z,"-column")==0 ){
drh8b32e172002-04-08 02:42:57 +00001847 data.mode = MODE_Column;
drhc49f44e2006-10-26 18:15:42 +00001848 }else if( strcmp(z,"-csv")==0 ){
1849 data.mode = MODE_Csv;
1850 strcpy(data.separator,",");
drh22fbcb82004-02-01 01:22:50 +00001851 }else if( strcmp(z,"-separator")==0 ){
1852 i++;
1853 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
1854 }else if( strcmp(z,"-nullvalue")==0 ){
1855 i++;
1856 sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
1857 }else if( strcmp(z,"-header")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001858 data.showHeader = 1;
drh22fbcb82004-02-01 01:22:50 +00001859 }else if( strcmp(z,"-noheader")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001860 data.showHeader = 0;
drh22fbcb82004-02-01 01:22:50 +00001861 }else if( strcmp(z,"-echo")==0 ){
drhdaffd0e2001-04-11 14:28:42 +00001862 data.echoOn = 1;
drhc49f44e2006-10-26 18:15:42 +00001863 }else if( strcmp(z,"-bail")==0 ){
1864 bail_on_error = 1;
drh22fbcb82004-02-01 01:22:50 +00001865 }else if( strcmp(z,"-version")==0 ){
drhc8d74412004-08-31 23:41:26 +00001866 printf("%s\n", sqlite3_libversion());
drh151e3e12006-06-06 12:32:21 +00001867 return 0;
drhc28490c2006-10-26 14:25:58 +00001868 }else if( strcmp(z,"-interactive")==0 ){
1869 stdin_is_interactive = 1;
1870 }else if( strcmp(z,"-batch")==0 ){
1871 stdin_is_interactive = 0;
drh80e8be92006-08-29 12:04:19 +00001872 }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
drhe1e38c42003-05-04 18:30:59 +00001873 usage(1);
drh1e5d0e92000-05-31 23:33:17 +00001874 }else{
drh22fbcb82004-02-01 01:22:50 +00001875 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
drhe1e38c42003-05-04 18:30:59 +00001876 fprintf(stderr,"Use -help for a list of options.\n");
drh1e5d0e92000-05-31 23:33:17 +00001877 return 1;
1878 }
1879 }
drh44c2eb12003-04-30 11:38:26 +00001880
drh22fbcb82004-02-01 01:22:50 +00001881 if( zFirstCmd ){
drh44c2eb12003-04-30 11:38:26 +00001882 /* Run just the command that follows the database name
1883 */
drh22fbcb82004-02-01 01:22:50 +00001884 if( zFirstCmd[0]=='.' ){
1885 do_meta_command(zFirstCmd, &data);
drh6ff13852001-11-25 13:18:23 +00001886 exit(0);
1887 }else{
1888 int rc;
drh44c2eb12003-04-30 11:38:26 +00001889 open_db(&data);
danielk19776f8a5032004-05-10 10:34:51 +00001890 rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
drh6ff13852001-11-25 13:18:23 +00001891 if( rc!=0 && zErrMsg!=0 ){
1892 fprintf(stderr,"SQL error: %s\n", zErrMsg);
1893 exit(1);
1894 }
drh75897232000-05-29 14:26:00 +00001895 }
1896 }else{
drh44c2eb12003-04-30 11:38:26 +00001897 /* Run commands received from standard input
1898 */
drhc28490c2006-10-26 14:25:58 +00001899 if( stdin_is_interactive ){
drh67505e72002-04-19 12:34:06 +00001900 char *zHome;
1901 char *zHistory = 0;
drh75897232000-05-29 14:26:00 +00001902 printf(
drhb217a572000-08-22 13:40:18 +00001903 "SQLite version %s\n"
1904 "Enter \".help\" for instructions\n",
drhc8d74412004-08-31 23:41:26 +00001905 sqlite3_libversion()
drh75897232000-05-29 14:26:00 +00001906 );
drh67505e72002-04-19 12:34:06 +00001907 zHome = find_home_dir();
1908 if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
1909 sprintf(zHistory,"%s/.sqlite_history", zHome);
1910 }
danielk19774af00c62005-01-23 23:43:21 +00001911#if defined(HAVE_READLINE) && HAVE_READLINE==1
drh67505e72002-04-19 12:34:06 +00001912 if( zHistory ) read_history(zHistory);
danielk19774af00c62005-01-23 23:43:21 +00001913#endif
drhc28490c2006-10-26 14:25:58 +00001914 rc = process_input(&data, 0);
drh67505e72002-04-19 12:34:06 +00001915 if( zHistory ){
1916 stifle_history(100);
1917 write_history(zHistory);
adamd0a3daa32006-07-28 20:16:14 +00001918 free(zHistory);
drh67505e72002-04-19 12:34:06 +00001919 }
adamd0a3daa32006-07-28 20:16:14 +00001920 free(zHome);
drhdaffd0e2001-04-11 14:28:42 +00001921 }else{
drhc28490c2006-10-26 14:25:58 +00001922 rc = process_input(&data, stdin);
drh75897232000-05-29 14:26:00 +00001923 }
1924 }
drh33048c02001-10-01 14:29:22 +00001925 set_table_name(&data, 0);
adamd0a3daa32006-07-28 20:16:14 +00001926 if( db ){
1927 if( sqlite3_close(db)!=SQLITE_OK ){
1928 fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
1929 }
1930 }
drhc28490c2006-10-26 14:25:58 +00001931 return rc;
drh75897232000-05-29 14:26:00 +00001932}