blob: 141b1256fd2954ff64ab7602a418538d43d534c1 [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**
drh902b9ee2008-12-05 17:17:07 +000015** $Id: shell.c,v 1.190 2008/12/05 17:17:08 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>
drhb0603412007-02-28 04:47:26 +000023#include <stdarg.h>
persicom7e2dfdd2002-04-18 02:46:52 +000024
drh454ad582007-11-26 22:54:27 +000025#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__)
drh4c504392000-10-16 22:06:40 +000026# include <signal.h>
chw97185482008-11-17 08:05:31 +000027# if !defined(__RTP__) && !defined(_WRS_KERNEL)
28# include <pwd.h>
29# endif
drhdd45df82002-04-18 12:39:03 +000030# include <unistd.h>
31# include <sys/types.h>
drh4c504392000-10-16 22:06:40 +000032#endif
drh75897232000-05-29 14:26:00 +000033
drhcdb36b72006-06-12 12:57:45 +000034#ifdef __OS2__
35# include <unistd.h>
36#endif
37
drh16e59552000-07-31 11:57:37 +000038#if defined(HAVE_READLINE) && HAVE_READLINE==1
drh8e7e7a22000-05-30 18:45:23 +000039# include <readline/readline.h>
40# include <readline/history.h>
41#else
drh9347b202003-07-18 01:30:59 +000042# define readline(p) local_getline(p,stdin)
persicom1d0b8722002-04-18 02:53:04 +000043# define add_history(X)
drh67505e72002-04-19 12:34:06 +000044# define read_history(X)
45# define write_history(X)
46# define stifle_history(X)
drh75897232000-05-29 14:26:00 +000047#endif
48
adamd2e8464a2006-09-06 21:39:40 +000049#if defined(_WIN32) || defined(WIN32)
50# include <io.h>
51#else
drh4328c8b2003-04-26 02:50:11 +000052/* Make sure isatty() has a prototype.
53*/
54extern int isatty();
adamd2e8464a2006-09-06 21:39:40 +000055#endif
drh4328c8b2003-04-26 02:50:11 +000056
chw65d3c132007-11-12 21:09:10 +000057#if defined(_WIN32_WCE)
58/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
59 * thus we always assume that we have a console. That can be
60 * overridden with the -batch command line option.
61 */
62#define isatty(x) 1
63#endif
64
chw97185482008-11-17 08:05:31 +000065#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
drh3b1a9882007-11-02 12:53:03 +000066#include <sys/time.h>
67#include <sys/resource.h>
68
drh902b9ee2008-12-05 17:17:07 +000069/*
70** Used to prevent warnings about unused parameters
71*/
72#define UNUSED_PARAMETER(x) (void)(x)
73
74
drh3b1a9882007-11-02 12:53:03 +000075/* Saved resource information for the beginning of an operation */
76static struct rusage sBegin;
77
78/* True if the timer is enabled */
79static int enableTimer = 0;
80
81/*
82** Begin timing an operation
83*/
84static void beginTimer(void){
85 if( enableTimer ){
86 getrusage(RUSAGE_SELF, &sBegin);
87 }
88}
89
drhf4608092008-07-11 17:23:24 +000090/* Return the difference of two time_structs in seconds */
91static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
92 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
93 (double)(pEnd->tv_sec - pStart->tv_sec);
drh3b1a9882007-11-02 12:53:03 +000094}
95
96/*
97** Print the timing results.
98*/
99static void endTimer(void){
100 if( enableTimer ){
101 struct rusage sEnd;
102 getrusage(RUSAGE_SELF, &sEnd);
103 printf("CPU Time: user %f sys %f\n",
drhf4608092008-07-11 17:23:24 +0000104 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
105 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
drh3b1a9882007-11-02 12:53:03 +0000106 }
107}
108#define BEGIN_TIMER beginTimer()
109#define END_TIMER endTimer()
110#define HAS_TIMER 1
111#else
112#define BEGIN_TIMER
113#define END_TIMER
114#define HAS_TIMER 0
115#endif
116
117
drh75897232000-05-29 14:26:00 +0000118/*
drhc49f44e2006-10-26 18:15:42 +0000119** If the following flag is set, then command execution stops
120** at an error if we are not interactive.
121*/
122static int bail_on_error = 0;
123
124/*
drhc28490c2006-10-26 14:25:58 +0000125** Threat stdin as an interactive input if the following variable
126** is true. Otherwise, assume stdin is connected to a file or pipe.
127*/
128static int stdin_is_interactive = 1;
129
130/*
drh4c504392000-10-16 22:06:40 +0000131** The following is the open SQLite database. We make a pointer
132** to this database a static variable so that it can be accessed
133** by the SIGINT handler to interrupt database processing.
134*/
danielk197792f9a1b2004-06-19 09:08:16 +0000135static sqlite3 *db = 0;
drh4c504392000-10-16 22:06:40 +0000136
137/*
drh67505e72002-04-19 12:34:06 +0000138** True if an interrupt (Control-C) has been received.
139*/
drh43617e92006-03-06 20:55:46 +0000140static volatile int seenInterrupt = 0;
drh67505e72002-04-19 12:34:06 +0000141
142/*
persicom7e2dfdd2002-04-18 02:46:52 +0000143** This is the name of our program. It is set in main(), used
144** in a number of other places, mostly for error messages.
145*/
146static char *Argv0;
147
148/*
149** Prompt strings. Initialized in main. Settable with
150** .prompt main continue
151*/
152static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
153static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
154
drhb0603412007-02-28 04:47:26 +0000155/*
156** Write I/O traces to the following stream.
157*/
rsebe0a9092007-07-30 18:24:38 +0000158#ifdef SQLITE_ENABLE_IOTRACE
drhb0603412007-02-28 04:47:26 +0000159static FILE *iotrace = 0;
rsebe0a9092007-07-30 18:24:38 +0000160#endif
drhb0603412007-02-28 04:47:26 +0000161
162/*
163** This routine works like printf in that its first argument is a
164** format string and subsequent arguments are values to be substituted
165** in place of % fields. The result of formatting this string
166** is written to iotrace.
167*/
rsebe0a9092007-07-30 18:24:38 +0000168#ifdef SQLITE_ENABLE_IOTRACE
drhb0603412007-02-28 04:47:26 +0000169static void iotracePrintf(const char *zFormat, ...){
170 va_list ap;
drhf075cd02007-02-28 06:14:25 +0000171 char *z;
drhb0603412007-02-28 04:47:26 +0000172 if( iotrace==0 ) return;
173 va_start(ap, zFormat);
drhf075cd02007-02-28 06:14:25 +0000174 z = sqlite3_vmprintf(zFormat, ap);
drhb0603412007-02-28 04:47:26 +0000175 va_end(ap);
drhf075cd02007-02-28 06:14:25 +0000176 fprintf(iotrace, "%s", z);
177 sqlite3_free(z);
drhb0603412007-02-28 04:47:26 +0000178}
rsebe0a9092007-07-30 18:24:38 +0000179#endif
drhb0603412007-02-28 04:47:26 +0000180
drh44c2eb12003-04-30 11:38:26 +0000181
persicom7e2dfdd2002-04-18 02:46:52 +0000182/*
drh83965662003-04-17 02:54:13 +0000183** Determines if a string is a number of not.
184*/
danielk19772e588c72005-12-09 14:25:08 +0000185static int isNumber(const char *z, int *realnum){
drhc8d74412004-08-31 23:41:26 +0000186 if( *z=='-' || *z=='+' ) z++;
187 if( !isdigit(*z) ){
188 return 0;
189 }
190 z++;
191 if( realnum ) *realnum = 0;
192 while( isdigit(*z) ){ z++; }
193 if( *z=='.' ){
194 z++;
195 if( !isdigit(*z) ) return 0;
196 while( isdigit(*z) ){ z++; }
197 if( realnum ) *realnum = 1;
198 }
199 if( *z=='e' || *z=='E' ){
200 z++;
201 if( *z=='+' || *z=='-' ) z++;
202 if( !isdigit(*z) ) return 0;
203 while( isdigit(*z) ){ z++; }
204 if( realnum ) *realnum = 1;
205 }
206 return *z==0;
207}
drh83965662003-04-17 02:54:13 +0000208
209/*
danielk1977bc6ada42004-06-30 08:20:16 +0000210** A global char* and an SQL function to access its current value
211** from within an SQL statement. This program used to use the
212** sqlite_exec_printf() API to substitue a string into an SQL statement.
213** The correct way to do this with sqlite3 is to use the bind API, but
214** since the shell is built around the callback paradigm it would be a lot
215** of work. Instead just use this hack, which is quite harmless.
216*/
217static const char *zShellStatic = 0;
218static void shellstaticFunc(
219 sqlite3_context *context,
220 int argc,
221 sqlite3_value **argv
222){
223 assert( 0==argc );
224 assert( zShellStatic );
drh902b9ee2008-12-05 17:17:07 +0000225 UNUSED_PARAMETER(argv);
danielk1977bc6ada42004-06-30 08:20:16 +0000226 sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
227}
228
229
230/*
drhfeac5f82004-08-01 00:10:45 +0000231** This routine reads a line of text from FILE in, stores
drh8e7e7a22000-05-30 18:45:23 +0000232** the text in memory obtained from malloc() and returns a pointer
233** to the text. NULL is returned at end of file, or if malloc()
234** fails.
235**
236** The interface is like "readline" but no command-line editing
237** is done.
238*/
drh9347b202003-07-18 01:30:59 +0000239static char *local_getline(char *zPrompt, FILE *in){
drh8e7e7a22000-05-30 18:45:23 +0000240 char *zLine;
241 int nLine;
drh8e7e7a22000-05-30 18:45:23 +0000242 int n;
243 int eol;
244
245 if( zPrompt && *zPrompt ){
246 printf("%s",zPrompt);
247 fflush(stdout);
248 }
249 nLine = 100;
250 zLine = malloc( nLine );
251 if( zLine==0 ) return 0;
252 n = 0;
253 eol = 0;
254 while( !eol ){
255 if( n+100>nLine ){
256 nLine = nLine*2 + 100;
257 zLine = realloc(zLine, nLine);
258 if( zLine==0 ) return 0;
259 }
drhdaffd0e2001-04-11 14:28:42 +0000260 if( fgets(&zLine[n], nLine - n, in)==0 ){
drh8e7e7a22000-05-30 18:45:23 +0000261 if( n==0 ){
262 free(zLine);
263 return 0;
264 }
265 zLine[n] = 0;
266 eol = 1;
267 break;
268 }
269 while( zLine[n] ){ n++; }
270 if( n>0 && zLine[n-1]=='\n' ){
271 n--;
272 zLine[n] = 0;
273 eol = 1;
274 }
275 }
276 zLine = realloc( zLine, n+1 );
277 return zLine;
278}
279
280/*
drhc28490c2006-10-26 14:25:58 +0000281** Retrieve a single line of input text.
drh8e7e7a22000-05-30 18:45:23 +0000282**
283** zPrior is a string of prior text retrieved. If not the empty
284** string, then issue a continuation prompt.
285*/
drhdaffd0e2001-04-11 14:28:42 +0000286static char *one_input_line(const char *zPrior, FILE *in){
drh8e7e7a22000-05-30 18:45:23 +0000287 char *zPrompt;
288 char *zResult;
drhdaffd0e2001-04-11 14:28:42 +0000289 if( in!=0 ){
drh9347b202003-07-18 01:30:59 +0000290 return local_getline(0, in);
drh8e7e7a22000-05-30 18:45:23 +0000291 }
292 if( zPrior && zPrior[0] ){
persicom7e2dfdd2002-04-18 02:46:52 +0000293 zPrompt = continuePrompt;
drh8e7e7a22000-05-30 18:45:23 +0000294 }else{
persicom7e2dfdd2002-04-18 02:46:52 +0000295 zPrompt = mainPrompt;
drh8e7e7a22000-05-30 18:45:23 +0000296 }
297 zResult = readline(zPrompt);
danielk19774af00c62005-01-23 23:43:21 +0000298#if defined(HAVE_READLINE) && HAVE_READLINE==1
drheb741d52006-06-03 17:37:25 +0000299 if( zResult && *zResult ) add_history(zResult);
danielk19774af00c62005-01-23 23:43:21 +0000300#endif
drh8e7e7a22000-05-30 18:45:23 +0000301 return zResult;
302}
303
persicom7e2dfdd2002-04-18 02:46:52 +0000304struct previous_mode_data {
305 int valid; /* Is there legit data in here? */
306 int mode;
307 int showHeader;
308 int colWidth[100];
309};
drh45e29d82006-11-20 16:21:10 +0000310
drh8e7e7a22000-05-30 18:45:23 +0000311/*
drh75897232000-05-29 14:26:00 +0000312** An pointer to an instance of this structure is passed from
313** the main program to the callback. This is used to communicate
314** state and mode information.
315*/
316struct callback_data {
danielk197792f9a1b2004-06-19 09:08:16 +0000317 sqlite3 *db; /* The database */
drhdaffd0e2001-04-11 14:28:42 +0000318 int echoOn; /* True to echo input commands */
drh28bd4bc2000-06-15 15:57:22 +0000319 int cnt; /* Number of records displayed so far */
320 FILE *out; /* Write results here */
321 int mode; /* An output mode setting */
drh45e29d82006-11-20 16:21:10 +0000322 int writableSchema; /* True if PRAGMA writable_schema=ON */
drh28bd4bc2000-06-15 15:57:22 +0000323 int showHeader; /* True to show column names in List or Column mode */
drh33048c02001-10-01 14:29:22 +0000324 char *zDestTable; /* Name of destination table when MODE_Insert */
drh28bd4bc2000-06-15 15:57:22 +0000325 char separator[20]; /* Separator character for MODE_List */
drha0c66f52000-07-29 13:20:21 +0000326 int colWidth[100]; /* Requested width of each column when in column mode*/
327 int actualWidth[100]; /* Actual width of each column */
drh83965662003-04-17 02:54:13 +0000328 char nullvalue[20]; /* The text to print when a NULL comes back from
329 ** the database */
persicom7e2dfdd2002-04-18 02:46:52 +0000330 struct previous_mode_data explainPrev;
drh83965662003-04-17 02:54:13 +0000331 /* Holds the mode information just before
332 ** .explain ON */
drh44c2eb12003-04-30 11:38:26 +0000333 char outfile[FILENAME_MAX]; /* Filename for *out */
334 const char *zDbFilename; /* name of the database file */
drh75897232000-05-29 14:26:00 +0000335};
336
337/*
338** These are the allowed modes.
339*/
drh967e8b72000-06-21 13:59:10 +0000340#define MODE_Line 0 /* One column per line. Blank line between records */
drh75897232000-05-29 14:26:00 +0000341#define MODE_Column 1 /* One record per line in neat columns */
342#define MODE_List 2 /* One record per line with a separator */
drhe3710332000-09-29 13:30:53 +0000343#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
344#define MODE_Html 4 /* Generate an XHTML table */
345#define MODE_Insert 5 /* Generate SQL "insert" statements */
drhfeac5f82004-08-01 00:10:45 +0000346#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
drh8e64d1c2004-10-07 00:32:39 +0000347#define MODE_Csv 7 /* Quote strings, numbers are plain */
drh66ce4d02008-02-15 17:38:06 +0000348#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
persicom7e2dfdd2002-04-18 02:46:52 +0000349
drh66ce4d02008-02-15 17:38:06 +0000350static const char *modeDescr[] = {
persicom7e2dfdd2002-04-18 02:46:52 +0000351 "line",
352 "column",
353 "list",
354 "semi",
355 "html",
drhfeac5f82004-08-01 00:10:45 +0000356 "insert",
357 "tcl",
drh8e64d1c2004-10-07 00:32:39 +0000358 "csv",
drh66ce4d02008-02-15 17:38:06 +0000359 "explain",
persicom7e2dfdd2002-04-18 02:46:52 +0000360};
drh75897232000-05-29 14:26:00 +0000361
362/*
363** Number of elements in an array
364*/
drh902b9ee2008-12-05 17:17:07 +0000365#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
drh75897232000-05-29 14:26:00 +0000366
367/*
drh28bd4bc2000-06-15 15:57:22 +0000368** Output the given string as a quoted string using SQL quoting conventions.
369*/
370static void output_quoted_string(FILE *out, const char *z){
371 int i;
372 int nSingle = 0;
drh28bd4bc2000-06-15 15:57:22 +0000373 for(i=0; z[i]; i++){
374 if( z[i]=='\'' ) nSingle++;
drh28bd4bc2000-06-15 15:57:22 +0000375 }
376 if( nSingle==0 ){
377 fprintf(out,"'%s'",z);
drh28bd4bc2000-06-15 15:57:22 +0000378 }else{
379 fprintf(out,"'");
380 while( *z ){
381 for(i=0; z[i] && z[i]!='\''; i++){}
382 if( i==0 ){
383 fprintf(out,"''");
384 z++;
385 }else if( z[i]=='\'' ){
386 fprintf(out,"%.*s''",i,z);
387 z += i+1;
388 }else{
drhcd7d2732002-02-26 23:24:26 +0000389 fprintf(out,"%s",z);
drh28bd4bc2000-06-15 15:57:22 +0000390 break;
391 }
392 }
drhcd7d2732002-02-26 23:24:26 +0000393 fprintf(out,"'");
drh28bd4bc2000-06-15 15:57:22 +0000394 }
395}
396
397/*
drhfeac5f82004-08-01 00:10:45 +0000398** Output the given string as a quoted according to C or TCL quoting rules.
399*/
400static void output_c_string(FILE *out, const char *z){
401 unsigned int c;
402 fputc('"', out);
403 while( (c = *(z++))!=0 ){
404 if( c=='\\' ){
405 fputc(c, out);
406 fputc(c, out);
407 }else if( c=='\t' ){
408 fputc('\\', out);
409 fputc('t', out);
410 }else if( c=='\n' ){
411 fputc('\\', out);
412 fputc('n', out);
413 }else if( c=='\r' ){
414 fputc('\\', out);
415 fputc('r', out);
416 }else if( !isprint(c) ){
drh0a8640d2005-08-30 20:12:02 +0000417 fprintf(out, "\\%03o", c&0xff);
drhfeac5f82004-08-01 00:10:45 +0000418 }else{
419 fputc(c, out);
420 }
421 }
422 fputc('"', out);
423}
424
425/*
drhc08a4f12000-06-15 16:49:48 +0000426** Output the given string with characters that are special to
427** HTML escaped.
428*/
429static void output_html_string(FILE *out, const char *z){
430 int i;
431 while( *z ){
432 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
433 if( i>0 ){
434 fprintf(out,"%.*s",i,z);
435 }
436 if( z[i]=='<' ){
437 fprintf(out,"&lt;");
438 }else if( z[i]=='&' ){
439 fprintf(out,"&amp;");
440 }else{
441 break;
442 }
443 z += i + 1;
444 }
445}
446
447/*
drhc49f44e2006-10-26 18:15:42 +0000448** If a field contains any character identified by a 1 in the following
449** array, then the string must be quoted for CSV.
450*/
451static const char needCsvQuote[] = {
452 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
453 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
454 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
460 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
461 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
462 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
463 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
464 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
465 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
466 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
467 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
468};
469
470/*
drh8e64d1c2004-10-07 00:32:39 +0000471** Output a single term of CSV. Actually, p->separator is used for
472** the separator, which may or may not be a comma. p->nullvalue is
473** the null value. Strings are quoted using ANSI-C rules. Numbers
474** appear outside of quotes.
475*/
476static void output_csv(struct callback_data *p, const char *z, int bSep){
drhc49f44e2006-10-26 18:15:42 +0000477 FILE *out = p->out;
drh8e64d1c2004-10-07 00:32:39 +0000478 if( z==0 ){
drhc49f44e2006-10-26 18:15:42 +0000479 fprintf(out,"%s",p->nullvalue);
drh8e64d1c2004-10-07 00:32:39 +0000480 }else{
drhc49f44e2006-10-26 18:15:42 +0000481 int i;
drhc85375d2007-12-18 15:41:44 +0000482 int nSep = strlen(p->separator);
drhc49f44e2006-10-26 18:15:42 +0000483 for(i=0; z[i]; i++){
drhc85375d2007-12-18 15:41:44 +0000484 if( needCsvQuote[((unsigned char*)z)[i]]
485 || (z[i]==p->separator[0] &&
486 (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){
drhc49f44e2006-10-26 18:15:42 +0000487 i = 0;
488 break;
489 }
490 }
491 if( i==0 ){
492 putc('"', out);
493 for(i=0; z[i]; i++){
494 if( z[i]=='"' ) putc('"', out);
495 putc(z[i], out);
496 }
497 putc('"', out);
498 }else{
499 fprintf(out, "%s", z);
500 }
drh8e64d1c2004-10-07 00:32:39 +0000501 }
502 if( bSep ){
drhd0e77882008-01-14 15:20:08 +0000503 fprintf(p->out, "%s", p->separator);
drh8e64d1c2004-10-07 00:32:39 +0000504 }
505}
506
danielk19774af00c62005-01-23 23:43:21 +0000507#ifdef SIGINT
drh8e64d1c2004-10-07 00:32:39 +0000508/*
drh4c504392000-10-16 22:06:40 +0000509** This routine runs when the user presses Ctrl-C
510*/
511static void interrupt_handler(int NotUsed){
drh902b9ee2008-12-05 17:17:07 +0000512 UNUSED_PARAMETER(NotUsed);
drh67505e72002-04-19 12:34:06 +0000513 seenInterrupt = 1;
danielk19776f8a5032004-05-10 10:34:51 +0000514 if( db ) sqlite3_interrupt(db);
drh4c504392000-10-16 22:06:40 +0000515}
danielk19774af00c62005-01-23 23:43:21 +0000516#endif
drh4c504392000-10-16 22:06:40 +0000517
518/*
drh75897232000-05-29 14:26:00 +0000519** This is the callback routine that the SQLite library
520** invokes for each row of a query result.
521*/
522static int callback(void *pArg, int nArg, char **azArg, char **azCol){
523 int i;
524 struct callback_data *p = (struct callback_data*)pArg;
525 switch( p->mode ){
526 case MODE_Line: {
drhe3710332000-09-29 13:30:53 +0000527 int w = 5;
drh6a535342001-10-19 16:44:56 +0000528 if( azArg==0 ) break;
drhe3710332000-09-29 13:30:53 +0000529 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000530 int len = strlen(azCol[i] ? azCol[i] : "");
drhe3710332000-09-29 13:30:53 +0000531 if( len>w ) w = len;
532 }
drh75897232000-05-29 14:26:00 +0000533 if( p->cnt++>0 ) fprintf(p->out,"\n");
534 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000535 fprintf(p->out,"%*s = %s\n", w, azCol[i],
drha69d9162003-04-17 22:57:53 +0000536 azArg[i] ? azArg[i] : p->nullvalue);
drh75897232000-05-29 14:26:00 +0000537 }
538 break;
539 }
danielk19770d78bae2008-01-03 07:09:48 +0000540 case MODE_Explain:
drh75897232000-05-29 14:26:00 +0000541 case MODE_Column: {
drha0c66f52000-07-29 13:20:21 +0000542 if( p->cnt++==0 ){
drh75897232000-05-29 14:26:00 +0000543 for(i=0; i<nArg; i++){
drha0c66f52000-07-29 13:20:21 +0000544 int w, n;
545 if( i<ArraySize(p->colWidth) ){
danielk19770d78bae2008-01-03 07:09:48 +0000546 w = p->colWidth[i];
drh75897232000-05-29 14:26:00 +0000547 }else{
danielk19770d78bae2008-01-03 07:09:48 +0000548 w = 0;
drh75897232000-05-29 14:26:00 +0000549 }
drha0c66f52000-07-29 13:20:21 +0000550 if( w<=0 ){
drhff6e9112000-08-28 16:21:58 +0000551 w = strlen(azCol[i] ? azCol[i] : "");
drha0c66f52000-07-29 13:20:21 +0000552 if( w<10 ) w = 10;
persicom7e2dfdd2002-04-18 02:46:52 +0000553 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
drha0c66f52000-07-29 13:20:21 +0000554 if( w<n ) w = n;
555 }
556 if( i<ArraySize(p->actualWidth) ){
persicom1d0b8722002-04-18 02:53:04 +0000557 p->actualWidth[i] = w;
drha0c66f52000-07-29 13:20:21 +0000558 }
559 if( p->showHeader ){
560 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
561 }
562 }
563 if( p->showHeader ){
564 for(i=0; i<nArg; i++){
565 int w;
566 if( i<ArraySize(p->actualWidth) ){
567 w = p->actualWidth[i];
568 }else{
569 w = 10;
570 }
571 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
572 "----------------------------------------------------------",
573 i==nArg-1 ? "\n": " ");
574 }
drh75897232000-05-29 14:26:00 +0000575 }
576 }
drh6a535342001-10-19 16:44:56 +0000577 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000578 for(i=0; i<nArg; i++){
579 int w;
drha0c66f52000-07-29 13:20:21 +0000580 if( i<ArraySize(p->actualWidth) ){
581 w = p->actualWidth[i];
drh75897232000-05-29 14:26:00 +0000582 }else{
583 w = 10;
584 }
drh902b9ee2008-12-05 17:17:07 +0000585 if( p->mode==MODE_Explain && azArg[i] && strlen(azArg[i])>(unsigned)w ){
danielk19770d78bae2008-01-03 07:09:48 +0000586 w = strlen(azArg[i]);
587 }
drhc61053b2000-06-04 12:58:36 +0000588 fprintf(p->out,"%-*.*s%s",w,w,
persicom7e2dfdd2002-04-18 02:46:52 +0000589 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
drh75897232000-05-29 14:26:00 +0000590 }
591 break;
592 }
drhe3710332000-09-29 13:30:53 +0000593 case MODE_Semi:
drh75897232000-05-29 14:26:00 +0000594 case MODE_List: {
595 if( p->cnt++==0 && p->showHeader ){
596 for(i=0; i<nArg; i++){
597 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
598 }
599 }
drh6a535342001-10-19 16:44:56 +0000600 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000601 for(i=0; i<nArg; i++){
drh4c653a02000-06-07 01:27:47 +0000602 char *z = azArg[i];
persicom7e2dfdd2002-04-18 02:46:52 +0000603 if( z==0 ) z = p->nullvalue;
drh71172c52002-01-24 00:00:21 +0000604 fprintf(p->out, "%s", z);
drhe3710332000-09-29 13:30:53 +0000605 if( i<nArg-1 ){
606 fprintf(p->out, "%s", p->separator);
607 }else if( p->mode==MODE_Semi ){
608 fprintf(p->out, ";\n");
609 }else{
610 fprintf(p->out, "\n");
611 }
drh75897232000-05-29 14:26:00 +0000612 }
613 break;
614 }
drh1e5d0e92000-05-31 23:33:17 +0000615 case MODE_Html: {
616 if( p->cnt++==0 && p->showHeader ){
mihailim57c591a2008-06-23 21:26:05 +0000617 fprintf(p->out,"<TR>");
drh1e5d0e92000-05-31 23:33:17 +0000618 for(i=0; i<nArg; i++){
mihailim57c591a2008-06-23 21:26:05 +0000619 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
drh1e5d0e92000-05-31 23:33:17 +0000620 }
mihailim57c591a2008-06-23 21:26:05 +0000621 fprintf(p->out,"</TR>\n");
drh1e5d0e92000-05-31 23:33:17 +0000622 }
drh6a535342001-10-19 16:44:56 +0000623 if( azArg==0 ) break;
mihailim57c591a2008-06-23 21:26:05 +0000624 fprintf(p->out,"<TR>");
drh1e5d0e92000-05-31 23:33:17 +0000625 for(i=0; i<nArg; i++){
mihailim57c591a2008-06-23 21:26:05 +0000626 fprintf(p->out,"<TD>");
persicom7e2dfdd2002-04-18 02:46:52 +0000627 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
mihailim57c591a2008-06-23 21:26:05 +0000628 fprintf(p->out,"</TD>\n");
drh1e5d0e92000-05-31 23:33:17 +0000629 }
mihailim57c591a2008-06-23 21:26:05 +0000630 fprintf(p->out,"</TR>\n");
drh1e5d0e92000-05-31 23:33:17 +0000631 break;
632 }
drhfeac5f82004-08-01 00:10:45 +0000633 case MODE_Tcl: {
634 if( p->cnt++==0 && p->showHeader ){
635 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000636 output_c_string(p->out,azCol[i] ? azCol[i] : "");
drhfeac5f82004-08-01 00:10:45 +0000637 fprintf(p->out, "%s", p->separator);
638 }
639 fprintf(p->out,"\n");
640 }
641 if( azArg==0 ) break;
642 for(i=0; i<nArg; i++){
643 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
644 fprintf(p->out, "%s", p->separator);
645 }
646 fprintf(p->out,"\n");
647 break;
648 }
drh8e64d1c2004-10-07 00:32:39 +0000649 case MODE_Csv: {
650 if( p->cnt++==0 && p->showHeader ){
651 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000652 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
drh8e64d1c2004-10-07 00:32:39 +0000653 }
654 fprintf(p->out,"\n");
655 }
656 if( azArg==0 ) break;
657 for(i=0; i<nArg; i++){
658 output_csv(p, azArg[i], i<nArg-1);
659 }
660 fprintf(p->out,"\n");
661 break;
662 }
drh28bd4bc2000-06-15 15:57:22 +0000663 case MODE_Insert: {
drh6a535342001-10-19 16:44:56 +0000664 if( azArg==0 ) break;
drh33048c02001-10-01 14:29:22 +0000665 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
drh28bd4bc2000-06-15 15:57:22 +0000666 for(i=0; i<nArg; i++){
667 char *zSep = i>0 ? ",": "";
668 if( azArg[i]==0 ){
669 fprintf(p->out,"%sNULL",zSep);
drhc8d74412004-08-31 23:41:26 +0000670 }else if( isNumber(azArg[i], 0) ){
drh28bd4bc2000-06-15 15:57:22 +0000671 fprintf(p->out,"%s%s",zSep, azArg[i]);
672 }else{
673 if( zSep[0] ) fprintf(p->out,"%s",zSep);
674 output_quoted_string(p->out, azArg[i]);
675 }
676 }
677 fprintf(p->out,");\n");
drh6a535342001-10-19 16:44:56 +0000678 break;
drh28bd4bc2000-06-15 15:57:22 +0000679 }
persicom1d0b8722002-04-18 02:53:04 +0000680 }
drh75897232000-05-29 14:26:00 +0000681 return 0;
682}
683
684/*
drh33048c02001-10-01 14:29:22 +0000685** Set the destination table field of the callback_data structure to
686** the name of the table given. Escape any quote characters in the
687** table name.
688*/
689static void set_table_name(struct callback_data *p, const char *zName){
690 int i, n;
691 int needQuote;
692 char *z;
693
694 if( p->zDestTable ){
695 free(p->zDestTable);
696 p->zDestTable = 0;
697 }
698 if( zName==0 ) return;
drh4c755c02004-08-08 20:22:17 +0000699 needQuote = !isalpha((unsigned char)*zName) && *zName!='_';
drh33048c02001-10-01 14:29:22 +0000700 for(i=n=0; zName[i]; i++, n++){
drh4c755c02004-08-08 20:22:17 +0000701 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){
drh33048c02001-10-01 14:29:22 +0000702 needQuote = 1;
703 if( zName[i]=='\'' ) n++;
704 }
705 }
706 if( needQuote ) n += 2;
707 z = p->zDestTable = malloc( n+1 );
708 if( z==0 ){
709 fprintf(stderr,"Out of memory!\n");
710 exit(1);
711 }
712 n = 0;
713 if( needQuote ) z[n++] = '\'';
714 for(i=0; zName[i]; i++){
715 z[n++] = zName[i];
716 if( zName[i]=='\'' ) z[n++] = '\'';
717 }
718 if( needQuote ) z[n++] = '\'';
719 z[n] = 0;
720}
721
danielk19772a02e332004-06-05 08:04:36 +0000722/* zIn is either a pointer to a NULL-terminated string in memory obtained
723** from malloc(), or a NULL pointer. The string pointed to by zAppend is
724** added to zIn, and the result returned in memory obtained from malloc().
725** zIn, if it was not NULL, is freed.
726**
727** If the third argument, quote, is not '\0', then it is used as a
728** quote character for zAppend.
729*/
drhc28490c2006-10-26 14:25:58 +0000730static char *appendText(char *zIn, char const *zAppend, char quote){
danielk19772a02e332004-06-05 08:04:36 +0000731 int len;
732 int i;
733 int nAppend = strlen(zAppend);
734 int nIn = (zIn?strlen(zIn):0);
735
736 len = nAppend+nIn+1;
737 if( quote ){
738 len += 2;
739 for(i=0; i<nAppend; i++){
740 if( zAppend[i]==quote ) len++;
741 }
742 }
743
744 zIn = (char *)realloc(zIn, len);
745 if( !zIn ){
746 return 0;
747 }
748
749 if( quote ){
750 char *zCsr = &zIn[nIn];
751 *zCsr++ = quote;
752 for(i=0; i<nAppend; i++){
753 *zCsr++ = zAppend[i];
754 if( zAppend[i]==quote ) *zCsr++ = quote;
755 }
756 *zCsr++ = quote;
757 *zCsr++ = '\0';
758 assert( (zCsr-zIn)==len );
759 }else{
760 memcpy(&zIn[nIn], zAppend, nAppend);
761 zIn[len-1] = '\0';
762 }
763
764 return zIn;
765}
766
drhdd3d4592004-08-30 01:54:05 +0000767
768/*
769** Execute a query statement that has a single result column. Print
770** that result column on a line by itself with a semicolon terminator.
drh45e29d82006-11-20 16:21:10 +0000771**
772** This is used, for example, to show the schema of the database by
773** querying the SQLITE_MASTER table.
drhdd3d4592004-08-30 01:54:05 +0000774*/
775static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
776 sqlite3_stmt *pSelect;
777 int rc;
778 rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
779 if( rc!=SQLITE_OK || !pSelect ){
780 return rc;
781 }
782 rc = sqlite3_step(pSelect);
783 while( rc==SQLITE_ROW ){
784 fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
785 rc = sqlite3_step(pSelect);
786 }
787 return sqlite3_finalize(pSelect);
788}
789
790
drh33048c02001-10-01 14:29:22 +0000791/*
drh4c653a02000-06-07 01:27:47 +0000792** This is a different callback routine used for dumping the database.
793** Each row received by this callback consists of a table name,
794** the table type ("index" or "table") and SQL to create the table.
795** This routine should print text sufficient to recreate the table.
796*/
797static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
danielk19772a02e332004-06-05 08:04:36 +0000798 int rc;
799 const char *zTable;
800 const char *zType;
801 const char *zSql;
drhdaffd0e2001-04-11 14:28:42 +0000802 struct callback_data *p = (struct callback_data *)pArg;
danielk19772a02e332004-06-05 08:04:36 +0000803
drh902b9ee2008-12-05 17:17:07 +0000804 UNUSED_PARAMETER(azCol);
drh4c653a02000-06-07 01:27:47 +0000805 if( nArg!=3 ) return 1;
danielk19772a02e332004-06-05 08:04:36 +0000806 zTable = azArg[0];
807 zType = azArg[1];
808 zSql = azArg[2];
809
drh00b950d2005-09-11 02:03:03 +0000810 if( strcmp(zTable, "sqlite_sequence")==0 ){
drhf8eb96a2005-02-03 00:42:34 +0000811 fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
drh00b950d2005-09-11 02:03:03 +0000812 }else if( strcmp(zTable, "sqlite_stat1")==0 ){
813 fprintf(p->out, "ANALYZE sqlite_master;\n");
814 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
815 return 0;
drh45e29d82006-11-20 16:21:10 +0000816 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
817 char *zIns;
818 if( !p->writableSchema ){
819 fprintf(p->out, "PRAGMA writable_schema=ON;\n");
820 p->writableSchema = 1;
821 }
822 zIns = sqlite3_mprintf(
823 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
824 "VALUES('table','%q','%q',0,'%q');",
825 zTable, zTable, zSql);
826 fprintf(p->out, "%s\n", zIns);
827 sqlite3_free(zIns);
828 return 0;
drh00b950d2005-09-11 02:03:03 +0000829 }else{
830 fprintf(p->out, "%s;\n", zSql);
drhf8eb96a2005-02-03 00:42:34 +0000831 }
danielk19772a02e332004-06-05 08:04:36 +0000832
833 if( strcmp(zType, "table")==0 ){
834 sqlite3_stmt *pTableInfo = 0;
danielk19772a02e332004-06-05 08:04:36 +0000835 char *zSelect = 0;
836 char *zTableInfo = 0;
837 char *zTmp = 0;
838
839 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
840 zTableInfo = appendText(zTableInfo, zTable, '"');
841 zTableInfo = appendText(zTableInfo, ");", 0);
842
843 rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
844 if( zTableInfo ) free(zTableInfo);
845 if( rc!=SQLITE_OK || !pTableInfo ){
846 return 1;
847 }
848
849 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
850 zTmp = appendText(zTmp, zTable, '"');
851 if( zTmp ){
852 zSelect = appendText(zSelect, zTmp, '\'');
853 }
854 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
855 rc = sqlite3_step(pTableInfo);
856 while( rc==SQLITE_ROW ){
danielk19772e588c72005-12-09 14:25:08 +0000857 const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
danielk19773f41e972004-06-08 00:39:01 +0000858 zSelect = appendText(zSelect, "quote(", 0);
danielk19772e588c72005-12-09 14:25:08 +0000859 zSelect = appendText(zSelect, zText, '"');
danielk19772a02e332004-06-05 08:04:36 +0000860 rc = sqlite3_step(pTableInfo);
861 if( rc==SQLITE_ROW ){
drh45e29d82006-11-20 16:21:10 +0000862 zSelect = appendText(zSelect, ") || ',' || ", 0);
danielk19772a02e332004-06-05 08:04:36 +0000863 }else{
864 zSelect = appendText(zSelect, ") ", 0);
865 }
866 }
867 rc = sqlite3_finalize(pTableInfo);
868 if( rc!=SQLITE_OK ){
869 if( zSelect ) free(zSelect);
870 return 1;
871 }
872 zSelect = appendText(zSelect, "|| ')' FROM ", 0);
873 zSelect = appendText(zSelect, zTable, '"');
874
drhdd3d4592004-08-30 01:54:05 +0000875 rc = run_table_dump_query(p->out, p->db, zSelect);
876 if( rc==SQLITE_CORRUPT ){
877 zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
878 rc = run_table_dump_query(p->out, p->db, zSelect);
879 }
danielk19772a02e332004-06-05 08:04:36 +0000880 if( zSelect ) free(zSelect);
drh4c653a02000-06-07 01:27:47 +0000881 }
drh4c653a02000-06-07 01:27:47 +0000882 return 0;
883}
884
885/*
drh45e29d82006-11-20 16:21:10 +0000886** Run zQuery. Use dump_callback() as the callback routine so that
887** the contents of the query are output as SQL statements.
888**
drhdd3d4592004-08-30 01:54:05 +0000889** If we get a SQLITE_CORRUPT error, rerun the query after appending
890** "ORDER BY rowid DESC" to the end.
891*/
892static int run_schema_dump_query(
893 struct callback_data *p,
894 const char *zQuery,
895 char **pzErrMsg
896){
897 int rc;
898 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
899 if( rc==SQLITE_CORRUPT ){
900 char *zQ2;
901 int len = strlen(zQuery);
902 if( pzErrMsg ) sqlite3_free(*pzErrMsg);
903 zQ2 = malloc( len+100 );
904 if( zQ2==0 ) return rc;
drh5bb3eb92007-05-04 13:15:55 +0000905 sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery);
drhdd3d4592004-08-30 01:54:05 +0000906 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
907 free(zQ2);
908 }
909 return rc;
910}
911
912/*
drh75897232000-05-29 14:26:00 +0000913** Text of a help message
914*/
persicom1d0b8722002-04-18 02:53:04 +0000915static char zHelp[] =
drh20f99c42007-01-08 14:31:35 +0000916 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
jplyon6a65bb32003-05-04 07:25:57 +0000917 ".databases List names and files of attached databases\n"
drhb860bc92004-08-04 15:16:55 +0000918 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
drhdaffd0e2001-04-11 14:28:42 +0000919 ".echo ON|OFF Turn command echo on or off\n"
drh75897232000-05-29 14:26:00 +0000920 ".exit Exit this program\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000921 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000922 ".header(s) ON|OFF Turn display of headers on or off\n"
drh75897232000-05-29 14:26:00 +0000923 ".help Show this message\n"
drhb860bc92004-08-04 15:16:55 +0000924 ".import FILE TABLE Import data from FILE into TABLE\n"
drh75897232000-05-29 14:26:00 +0000925 ".indices TABLE Show names of all indices on TABLE\n"
drhae5e4452007-05-03 17:18:36 +0000926#ifdef SQLITE_ENABLE_IOTRACE
927 ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
928#endif
drh70df4fe2006-06-13 15:12:21 +0000929#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +0000930 ".load FILE ?ENTRY? Load an extension library\n"
drh70df4fe2006-06-13 15:12:21 +0000931#endif
danielk19776b77a362005-01-13 11:10:25 +0000932 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
drh3b584fa2004-09-24 12:50:03 +0000933 " csv Comma-separated values\n"
drhb860bc92004-08-04 15:16:55 +0000934 " column Left-aligned columns. (See .width)\n"
935 " html HTML <table> code\n"
936 " insert SQL insert statements for TABLE\n"
937 " line One value per line\n"
938 " list Values delimited by .separator string\n"
939 " tabs Tab-separated values\n"
940 " tcl TCL list elements\n"
941 ".nullvalue STRING Print STRING in place of NULL values\n"
drh75897232000-05-29 14:26:00 +0000942 ".output FILENAME Send output to FILENAME\n"
943 ".output stdout Send output to the screen\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000944 ".prompt MAIN CONTINUE Replace the standard prompts\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000945 ".quit Exit this program\n"
drhdaffd0e2001-04-11 14:28:42 +0000946 ".read FILENAME Execute SQL in FILENAME\n"
drh75897232000-05-29 14:26:00 +0000947 ".schema ?TABLE? Show the CREATE statements\n"
drhb860bc92004-08-04 15:16:55 +0000948 ".separator STRING Change separator used by output mode and .import\n"
drhdd45df82002-04-18 12:39:03 +0000949 ".show Show the current values for various settings\n"
drhfeac5f82004-08-01 00:10:45 +0000950 ".tables ?PATTERN? List names of tables matching a LIKE pattern\n"
drh2dfbbca2000-07-28 14:32:48 +0000951 ".timeout MS Try opening locked tables for MS milliseconds\n"
drh3b1a9882007-11-02 12:53:03 +0000952#if HAS_TIMER
953 ".timer ON|OFF Turn the CPU timer measurement on or off\n"
954#endif
drh75897232000-05-29 14:26:00 +0000955 ".width NUM NUM ... Set column widths for \"column\" mode\n"
956;
957
drhdaffd0e2001-04-11 14:28:42 +0000958/* Forward reference */
drhc28490c2006-10-26 14:25:58 +0000959static int process_input(struct callback_data *p, FILE *in);
drhdaffd0e2001-04-11 14:28:42 +0000960
drh75897232000-05-29 14:26:00 +0000961/*
drh44c2eb12003-04-30 11:38:26 +0000962** Make sure the database is open. If it is not, then open it. If
963** the database fails to open, print an error message and exit.
964*/
965static void open_db(struct callback_data *p){
966 if( p->db==0 ){
danielk19774f057f92004-06-08 00:02:33 +0000967 sqlite3_open(p->zDbFilename, &p->db);
danielk197780290862004-05-22 09:21:21 +0000968 db = p->db;
drh4cea5ba2008-05-05 16:27:24 +0000969 if( db && sqlite3_errcode(db)==SQLITE_OK ){
970 sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
971 shellstaticFunc, 0, 0);
972 }
973 if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
danielk197780290862004-05-22 09:21:21 +0000974 fprintf(stderr,"Unable to open database \"%s\": %s\n",
975 p->zDbFilename, sqlite3_errmsg(db));
drh22fbcb82004-02-01 01:22:50 +0000976 exit(1);
drh44c2eb12003-04-30 11:38:26 +0000977 }
drhc2e87a32006-06-27 15:16:14 +0000978#ifndef SQLITE_OMIT_LOAD_EXTENSION
979 sqlite3_enable_load_extension(p->db, 1);
980#endif
drh44c2eb12003-04-30 11:38:26 +0000981 }
982}
983
984/*
drhfeac5f82004-08-01 00:10:45 +0000985** Do C-language style dequoting.
986**
987** \t -> tab
988** \n -> newline
989** \r -> carriage return
990** \NNN -> ascii character NNN in octal
991** \\ -> backslash
992*/
993static void resolve_backslashes(char *z){
994 int i, j, c;
995 for(i=j=0; (c = z[i])!=0; i++, j++){
996 if( c=='\\' ){
997 c = z[++i];
998 if( c=='n' ){
999 c = '\n';
1000 }else if( c=='t' ){
1001 c = '\t';
1002 }else if( c=='r' ){
1003 c = '\r';
1004 }else if( c>='0' && c<='7' ){
drhaa816082005-12-29 12:53:09 +00001005 c -= '0';
drhfeac5f82004-08-01 00:10:45 +00001006 if( z[i+1]>='0' && z[i+1]<='7' ){
1007 i++;
1008 c = (c<<3) + z[i] - '0';
1009 if( z[i+1]>='0' && z[i+1]<='7' ){
1010 i++;
1011 c = (c<<3) + z[i] - '0';
1012 }
1013 }
1014 }
1015 }
1016 z[j] = c;
1017 }
1018 z[j] = 0;
1019}
1020
1021/*
drhc28490c2006-10-26 14:25:58 +00001022** Interpret zArg as a boolean value. Return either 0 or 1.
1023*/
1024static int booleanValue(char *zArg){
1025 int val = atoi(zArg);
1026 int j;
1027 for(j=0; zArg[j]; j++){
1028 zArg[j] = tolower(zArg[j]);
1029 }
1030 if( strcmp(zArg,"on")==0 ){
1031 val = 1;
1032 }else if( strcmp(zArg,"yes")==0 ){
1033 val = 1;
1034 }
1035 return val;
1036}
1037
1038/*
drh75897232000-05-29 14:26:00 +00001039** If an input line begins with "." then invoke this routine to
1040** process that line.
drh67505e72002-04-19 12:34:06 +00001041**
drh47ad6842006-11-08 12:25:42 +00001042** Return 1 on error, 2 to exit, and 0 otherwise.
drh75897232000-05-29 14:26:00 +00001043*/
drh44c2eb12003-04-30 11:38:26 +00001044static int do_meta_command(char *zLine, struct callback_data *p){
drh75897232000-05-29 14:26:00 +00001045 int i = 1;
1046 int nArg = 0;
1047 int n, c;
drh67505e72002-04-19 12:34:06 +00001048 int rc = 0;
drh75897232000-05-29 14:26:00 +00001049 char *azArg[50];
1050
1051 /* Parse the input line into tokens.
1052 */
1053 while( zLine[i] && nArg<ArraySize(azArg) ){
drh4c755c02004-08-08 20:22:17 +00001054 while( isspace((unsigned char)zLine[i]) ){ i++; }
drh06333682004-03-09 13:37:45 +00001055 if( zLine[i]==0 ) break;
drh75897232000-05-29 14:26:00 +00001056 if( zLine[i]=='\'' || zLine[i]=='"' ){
1057 int delim = zLine[i++];
1058 azArg[nArg++] = &zLine[i];
1059 while( zLine[i] && zLine[i]!=delim ){ i++; }
1060 if( zLine[i]==delim ){
1061 zLine[i++] = 0;
1062 }
drhfeac5f82004-08-01 00:10:45 +00001063 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +00001064 }else{
1065 azArg[nArg++] = &zLine[i];
drh4c755c02004-08-08 20:22:17 +00001066 while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; }
drh75897232000-05-29 14:26:00 +00001067 if( zLine[i] ) zLine[i++] = 0;
drhfeac5f82004-08-01 00:10:45 +00001068 resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +00001069 }
1070 }
1071
1072 /* Process the input line.
1073 */
drh67505e72002-04-19 12:34:06 +00001074 if( nArg==0 ) return rc;
drh75897232000-05-29 14:26:00 +00001075 n = strlen(azArg[0]);
1076 c = azArg[0][0];
drhc49f44e2006-10-26 18:15:42 +00001077 if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
1078 bail_on_error = booleanValue(azArg[1]);
1079 }else
1080
jplyon6a65bb32003-05-04 07:25:57 +00001081 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
jplyon672a1ed2003-05-11 20:07:05 +00001082 struct callback_data data;
1083 char *zErrMsg = 0;
jplyon6a65bb32003-05-04 07:25:57 +00001084 open_db(p);
jplyon672a1ed2003-05-11 20:07:05 +00001085 memcpy(&data, p, sizeof(data));
drhd8885442004-03-17 23:42:12 +00001086 data.showHeader = 1;
jplyon672a1ed2003-05-11 20:07:05 +00001087 data.mode = MODE_Column;
drhd8885442004-03-17 23:42:12 +00001088 data.colWidth[0] = 3;
1089 data.colWidth[1] = 15;
1090 data.colWidth[2] = 58;
drh0b2110c2004-10-26 00:08:10 +00001091 data.cnt = 0;
danielk19776f8a5032004-05-10 10:34:51 +00001092 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
jplyon672a1ed2003-05-11 20:07:05 +00001093 if( zErrMsg ){
1094 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001095 sqlite3_free(zErrMsg);
jplyon6a65bb32003-05-04 07:25:57 +00001096 }
1097 }else
1098
drh4c653a02000-06-07 01:27:47 +00001099 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
1100 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001101 open_db(p);
drh33048c02001-10-01 14:29:22 +00001102 fprintf(p->out, "BEGIN TRANSACTION;\n");
drh45e29d82006-11-20 16:21:10 +00001103 p->writableSchema = 0;
drh93f41e52008-08-11 19:12:34 +00001104 sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0);
drh4c653a02000-06-07 01:27:47 +00001105 if( nArg==1 ){
drhdd3d4592004-08-30 01:54:05 +00001106 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +00001107 "SELECT name, type, sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001108 "WHERE sql NOT NULL AND type=='table'", 0
drh0b9a5942006-09-13 20:22:02 +00001109 );
1110 run_table_dump_query(p->out, p->db,
1111 "SELECT sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001112 "WHERE sql NOT NULL AND type IN ('index','trigger','view')"
drha18c5682000-10-08 22:20:57 +00001113 );
drh4c653a02000-06-07 01:27:47 +00001114 }else{
1115 int i;
drhdd3d4592004-08-30 01:54:05 +00001116 for(i=1; i<nArg; i++){
danielk1977bc6ada42004-06-30 08:20:16 +00001117 zShellStatic = azArg[i];
drhdd3d4592004-08-30 01:54:05 +00001118 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +00001119 "SELECT name, type, sql FROM sqlite_master "
drhdd3d4592004-08-30 01:54:05 +00001120 "WHERE tbl_name LIKE shellstatic() AND type=='table'"
drh45e29d82006-11-20 16:21:10 +00001121 " AND sql NOT NULL", 0);
drh0b9a5942006-09-13 20:22:02 +00001122 run_table_dump_query(p->out, p->db,
1123 "SELECT sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001124 "WHERE sql NOT NULL"
1125 " AND type IN ('index','trigger','view')"
drh0b9a5942006-09-13 20:22:02 +00001126 " AND tbl_name LIKE shellstatic()"
1127 );
danielk1977bc6ada42004-06-30 08:20:16 +00001128 zShellStatic = 0;
drh4c653a02000-06-07 01:27:47 +00001129 }
1130 }
drh45e29d82006-11-20 16:21:10 +00001131 if( p->writableSchema ){
1132 fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
1133 p->writableSchema = 0;
1134 }
drh93f41e52008-08-11 19:12:34 +00001135 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0);
drh4c653a02000-06-07 01:27:47 +00001136 if( zErrMsg ){
1137 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001138 sqlite3_free(zErrMsg);
drh33048c02001-10-01 14:29:22 +00001139 }else{
1140 fprintf(p->out, "COMMIT;\n");
drh4c653a02000-06-07 01:27:47 +00001141 }
1142 }else
drh75897232000-05-29 14:26:00 +00001143
drhdaffd0e2001-04-11 14:28:42 +00001144 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001145 p->echoOn = booleanValue(azArg[1]);
drhdaffd0e2001-04-11 14:28:42 +00001146 }else
1147
drh75897232000-05-29 14:26:00 +00001148 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
drh47ad6842006-11-08 12:25:42 +00001149 rc = 2;
drh75897232000-05-29 14:26:00 +00001150 }else
1151
drhdd45df82002-04-18 12:39:03 +00001152 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
drhc28490c2006-10-26 14:25:58 +00001153 int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
persicom7e2dfdd2002-04-18 02:46:52 +00001154 if(val == 1) {
1155 if(!p->explainPrev.valid) {
1156 p->explainPrev.valid = 1;
1157 p->explainPrev.mode = p->mode;
1158 p->explainPrev.showHeader = p->showHeader;
1159 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
1160 }
1161 /* We could put this code under the !p->explainValid
1162 ** condition so that it does not execute if we are already in
1163 ** explain mode. However, always executing it allows us an easy
1164 ** was to reset to explain mode in case the user previously
1165 ** did an .explain followed by a .width, .mode or .header
1166 ** command.
1167 */
danielk19770d78bae2008-01-03 07:09:48 +00001168 p->mode = MODE_Explain;
persicom7e2dfdd2002-04-18 02:46:52 +00001169 p->showHeader = 1;
1170 memset(p->colWidth,0,ArraySize(p->colWidth));
danielk19770d78bae2008-01-03 07:09:48 +00001171 p->colWidth[0] = 4; /* addr */
drh60a713c2008-01-21 16:22:45 +00001172 p->colWidth[1] = 13; /* opcode */
1173 p->colWidth[2] = 4; /* P1 */
1174 p->colWidth[3] = 4; /* P2 */
1175 p->colWidth[4] = 4; /* P3 */
1176 p->colWidth[5] = 13; /* P4 */
danielk19770d78bae2008-01-03 07:09:48 +00001177 p->colWidth[6] = 2; /* P5 */
drh60a713c2008-01-21 16:22:45 +00001178 p->colWidth[7] = 13; /* Comment */
persicom7e2dfdd2002-04-18 02:46:52 +00001179 }else if (p->explainPrev.valid) {
1180 p->explainPrev.valid = 0;
1181 p->mode = p->explainPrev.mode;
1182 p->showHeader = p->explainPrev.showHeader;
1183 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
1184 }
drh75897232000-05-29 14:26:00 +00001185 }else
1186
drhc28490c2006-10-26 14:25:58 +00001187 if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
persicom7e2dfdd2002-04-18 02:46:52 +00001188 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001189 p->showHeader = booleanValue(azArg[1]);
drh75897232000-05-29 14:26:00 +00001190 }else
1191
1192 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
1193 fprintf(stderr,zHelp);
1194 }else
1195
drhfeac5f82004-08-01 00:10:45 +00001196 if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
1197 char *zTable = azArg[2]; /* Insert data into this table */
1198 char *zFile = azArg[1]; /* The file from which to extract data */
1199 sqlite3_stmt *pStmt; /* A statement */
1200 int rc; /* Result code */
1201 int nCol; /* Number of columns in the table */
1202 int nByte; /* Number of bytes in an SQL string */
1203 int i, j; /* Loop counters */
1204 int nSep; /* Number of bytes in p->separator[] */
1205 char *zSql; /* An SQL statement */
1206 char *zLine; /* A single line of input from the file */
1207 char **azCol; /* zLine[] broken up into columns */
1208 char *zCommit; /* How to commit changes */
drhb860bc92004-08-04 15:16:55 +00001209 FILE *in; /* The input file */
1210 int lineno = 0; /* Line number of input file */
drhfeac5f82004-08-01 00:10:45 +00001211
drha543c822006-06-08 16:10:14 +00001212 open_db(p);
drhfeac5f82004-08-01 00:10:45 +00001213 nSep = strlen(p->separator);
1214 if( nSep==0 ){
1215 fprintf(stderr, "non-null separator required for import\n");
1216 return 0;
1217 }
1218 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
1219 if( zSql==0 ) return 0;
1220 nByte = strlen(zSql);
drh5e6078b2006-01-31 19:07:22 +00001221 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001222 sqlite3_free(zSql);
1223 if( rc ){
1224 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1225 nCol = 0;
drh47ad6842006-11-08 12:25:42 +00001226 rc = 1;
drhfeac5f82004-08-01 00:10:45 +00001227 }else{
1228 nCol = sqlite3_column_count(pStmt);
1229 }
1230 sqlite3_finalize(pStmt);
1231 if( nCol==0 ) return 0;
1232 zSql = malloc( nByte + 20 + nCol*2 );
1233 if( zSql==0 ) return 0;
1234 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
1235 j = strlen(zSql);
1236 for(i=1; i<nCol; i++){
1237 zSql[j++] = ',';
1238 zSql[j++] = '?';
1239 }
1240 zSql[j++] = ')';
1241 zSql[j] = 0;
drh5e6078b2006-01-31 19:07:22 +00001242 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001243 free(zSql);
1244 if( rc ){
1245 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
1246 sqlite3_finalize(pStmt);
drh47ad6842006-11-08 12:25:42 +00001247 return 1;
drhfeac5f82004-08-01 00:10:45 +00001248 }
1249 in = fopen(zFile, "rb");
1250 if( in==0 ){
1251 fprintf(stderr, "cannot open file: %s\n", zFile);
1252 sqlite3_finalize(pStmt);
1253 return 0;
1254 }
1255 azCol = malloc( sizeof(azCol[0])*(nCol+1) );
drh43617e92006-03-06 20:55:46 +00001256 if( azCol==0 ){
1257 fclose(in);
1258 return 0;
1259 }
drhfeac5f82004-08-01 00:10:45 +00001260 sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
1261 zCommit = "COMMIT";
1262 while( (zLine = local_getline(0, in))!=0 ){
1263 char *z;
1264 i = 0;
drhb860bc92004-08-04 15:16:55 +00001265 lineno++;
drhfeac5f82004-08-01 00:10:45 +00001266 azCol[0] = zLine;
drh36d4e972004-10-06 14:39:06 +00001267 for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){
drhfeac5f82004-08-01 00:10:45 +00001268 if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
1269 *z = 0;
1270 i++;
drhb860bc92004-08-04 15:16:55 +00001271 if( i<nCol ){
1272 azCol[i] = &z[nSep];
1273 z += nSep-1;
1274 }
drhfeac5f82004-08-01 00:10:45 +00001275 }
1276 }
drh1cd7f832005-08-05 18:50:51 +00001277 *z = 0;
drhb860bc92004-08-04 15:16:55 +00001278 if( i+1!=nCol ){
1279 fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
1280 zFile, lineno, nCol, i+1);
1281 zCommit = "ROLLBACK";
drh1822eee2008-12-04 12:26:00 +00001282 free(zLine);
drhb860bc92004-08-04 15:16:55 +00001283 break;
1284 }
drhfeac5f82004-08-01 00:10:45 +00001285 for(i=0; i<nCol; i++){
1286 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
1287 }
1288 sqlite3_step(pStmt);
1289 rc = sqlite3_reset(pStmt);
1290 free(zLine);
1291 if( rc!=SQLITE_OK ){
1292 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1293 zCommit = "ROLLBACK";
drh47ad6842006-11-08 12:25:42 +00001294 rc = 1;
drhfeac5f82004-08-01 00:10:45 +00001295 break;
1296 }
1297 }
1298 free(azCol);
1299 fclose(in);
1300 sqlite3_finalize(pStmt);
drhb860bc92004-08-04 15:16:55 +00001301 sqlite3_exec(p->db, zCommit, 0, 0, 0);
drhfeac5f82004-08-01 00:10:45 +00001302 }else
1303
drh75897232000-05-29 14:26:00 +00001304 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
1305 struct callback_data data;
1306 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001307 open_db(p);
drh75897232000-05-29 14:26:00 +00001308 memcpy(&data, p, sizeof(data));
1309 data.showHeader = 0;
1310 data.mode = MODE_List;
danielk1977bc6ada42004-06-30 08:20:16 +00001311 zShellStatic = azArg[1];
1312 sqlite3_exec(p->db,
drha18c5682000-10-08 22:20:57 +00001313 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001314 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001315 "UNION ALL "
1316 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001317 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001318 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001319 callback, &data, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001320 );
danielk1977bc6ada42004-06-30 08:20:16 +00001321 zShellStatic = 0;
drh75897232000-05-29 14:26:00 +00001322 if( zErrMsg ){
1323 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001324 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001325 }
1326 }else
1327
drhae5e4452007-05-03 17:18:36 +00001328#ifdef SQLITE_ENABLE_IOTRACE
drhb0603412007-02-28 04:47:26 +00001329 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
mlcreech3a00f902008-03-04 17:45:01 +00001330 extern void (*sqlite3IoTrace)(const char*, ...);
drhb0603412007-02-28 04:47:26 +00001331 if( iotrace && iotrace!=stdout ) fclose(iotrace);
1332 iotrace = 0;
1333 if( nArg<2 ){
mlcreech3a00f902008-03-04 17:45:01 +00001334 sqlite3IoTrace = 0;
drhb0603412007-02-28 04:47:26 +00001335 }else if( strcmp(azArg[1], "-")==0 ){
mlcreech3a00f902008-03-04 17:45:01 +00001336 sqlite3IoTrace = iotracePrintf;
drhb0603412007-02-28 04:47:26 +00001337 iotrace = stdout;
1338 }else{
1339 iotrace = fopen(azArg[1], "w");
1340 if( iotrace==0 ){
1341 fprintf(stderr, "cannot open \"%s\"\n", azArg[1]);
mlcreech3a00f902008-03-04 17:45:01 +00001342 sqlite3IoTrace = 0;
drhb0603412007-02-28 04:47:26 +00001343 }else{
mlcreech3a00f902008-03-04 17:45:01 +00001344 sqlite3IoTrace = iotracePrintf;
drhb0603412007-02-28 04:47:26 +00001345 }
1346 }
1347 }else
drhae5e4452007-05-03 17:18:36 +00001348#endif
drhb0603412007-02-28 04:47:26 +00001349
drh70df4fe2006-06-13 15:12:21 +00001350#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +00001351 if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
1352 const char *zFile, *zProc;
1353 char *zErrMsg = 0;
1354 int rc;
1355 zFile = azArg[1];
1356 zProc = nArg>=3 ? azArg[2] : 0;
1357 open_db(p);
1358 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
1359 if( rc!=SQLITE_OK ){
1360 fprintf(stderr, "%s\n", zErrMsg);
1361 sqlite3_free(zErrMsg);
drh47ad6842006-11-08 12:25:42 +00001362 rc = 1;
drh1e397f82006-06-08 15:28:43 +00001363 }
1364 }else
drh70df4fe2006-06-13 15:12:21 +00001365#endif
drh1e397f82006-06-08 15:28:43 +00001366
drh28bd4bc2000-06-15 15:57:22 +00001367 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
drh75897232000-05-29 14:26:00 +00001368 int n2 = strlen(azArg[1]);
persicom7e2dfdd2002-04-18 02:46:52 +00001369 if( strncmp(azArg[1],"line",n2)==0
1370 ||
1371 strncmp(azArg[1],"lines",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001372 p->mode = MODE_Line;
persicom7e2dfdd2002-04-18 02:46:52 +00001373 }else if( strncmp(azArg[1],"column",n2)==0
1374 ||
1375 strncmp(azArg[1],"columns",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001376 p->mode = MODE_Column;
1377 }else if( strncmp(azArg[1],"list",n2)==0 ){
1378 p->mode = MODE_List;
drh1e5d0e92000-05-31 23:33:17 +00001379 }else if( strncmp(azArg[1],"html",n2)==0 ){
1380 p->mode = MODE_Html;
drhfeac5f82004-08-01 00:10:45 +00001381 }else if( strncmp(azArg[1],"tcl",n2)==0 ){
1382 p->mode = MODE_Tcl;
1383 }else if( strncmp(azArg[1],"csv",n2)==0 ){
drh8e64d1c2004-10-07 00:32:39 +00001384 p->mode = MODE_Csv;
drh5bb3eb92007-05-04 13:15:55 +00001385 sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
drhfeac5f82004-08-01 00:10:45 +00001386 }else if( strncmp(azArg[1],"tabs",n2)==0 ){
1387 p->mode = MODE_List;
drh5bb3eb92007-05-04 13:15:55 +00001388 sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
drh28bd4bc2000-06-15 15:57:22 +00001389 }else if( strncmp(azArg[1],"insert",n2)==0 ){
1390 p->mode = MODE_Insert;
1391 if( nArg>=3 ){
drh33048c02001-10-01 14:29:22 +00001392 set_table_name(p, azArg[2]);
drh28bd4bc2000-06-15 15:57:22 +00001393 }else{
drh33048c02001-10-01 14:29:22 +00001394 set_table_name(p, "table");
drh28bd4bc2000-06-15 15:57:22 +00001395 }
drhdaffd0e2001-04-11 14:28:42 +00001396 }else {
drhcf68ae92006-12-19 18:47:41 +00001397 fprintf(stderr,"mode should be one of: "
drhfeac5f82004-08-01 00:10:45 +00001398 "column csv html insert line list tabs tcl\n");
drh75897232000-05-29 14:26:00 +00001399 }
1400 }else
1401
persicom7e2dfdd2002-04-18 02:46:52 +00001402 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
drh5bb3eb92007-05-04 13:15:55 +00001403 sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
1404 "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
persicom7e2dfdd2002-04-18 02:46:52 +00001405 }else
1406
drh75897232000-05-29 14:26:00 +00001407 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
1408 if( p->out!=stdout ){
1409 fclose(p->out);
1410 }
1411 if( strcmp(azArg[1],"stdout")==0 ){
1412 p->out = stdout;
drh5bb3eb92007-05-04 13:15:55 +00001413 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout");
drh75897232000-05-29 14:26:00 +00001414 }else{
drha1f9b5e2004-02-14 16:31:02 +00001415 p->out = fopen(azArg[1], "wb");
drh75897232000-05-29 14:26:00 +00001416 if( p->out==0 ){
1417 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
1418 p->out = stdout;
persicom7e2dfdd2002-04-18 02:46:52 +00001419 } else {
drh5bb3eb92007-05-04 13:15:55 +00001420 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
drh75897232000-05-29 14:26:00 +00001421 }
1422 }
1423 }else
1424
drhdd45df82002-04-18 12:39:03 +00001425 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
persicom7e2dfdd2002-04-18 02:46:52 +00001426 if( nArg >= 2) {
1427 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
1428 }
1429 if( nArg >= 3) {
1430 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
1431 }
1432 }else
1433
1434 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
drh47ad6842006-11-08 12:25:42 +00001435 rc = 2;
persicom7e2dfdd2002-04-18 02:46:52 +00001436 }else
1437
drhdaffd0e2001-04-11 14:28:42 +00001438 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
drha1f9b5e2004-02-14 16:31:02 +00001439 FILE *alt = fopen(azArg[1], "rb");
drhdaffd0e2001-04-11 14:28:42 +00001440 if( alt==0 ){
1441 fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
1442 }else{
1443 process_input(p, alt);
1444 fclose(alt);
1445 }
1446 }else
1447
drh75897232000-05-29 14:26:00 +00001448 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
1449 struct callback_data data;
1450 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001451 open_db(p);
drh75897232000-05-29 14:26:00 +00001452 memcpy(&data, p, sizeof(data));
1453 data.showHeader = 0;
drhe3710332000-09-29 13:30:53 +00001454 data.mode = MODE_Semi;
drh75897232000-05-29 14:26:00 +00001455 if( nArg>1 ){
drhc8d74412004-08-31 23:41:26 +00001456 int i;
1457 for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]);
1458 if( strcmp(azArg[1],"sqlite_master")==0 ){
drha18c5682000-10-08 22:20:57 +00001459 char *new_argv[2], *new_colv[2];
1460 new_argv[0] = "CREATE TABLE sqlite_master (\n"
1461 " type text,\n"
1462 " name text,\n"
1463 " tbl_name text,\n"
drhadbca9c2001-09-27 15:11:53 +00001464 " rootpage integer,\n"
drha18c5682000-10-08 22:20:57 +00001465 " sql text\n"
1466 ")";
1467 new_argv[1] = 0;
1468 new_colv[0] = "sql";
1469 new_colv[1] = 0;
1470 callback(&data, 1, new_argv, new_colv);
drhc8d74412004-08-31 23:41:26 +00001471 }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){
drhe0bc4042002-06-25 01:09:11 +00001472 char *new_argv[2], *new_colv[2];
1473 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
1474 " type text,\n"
1475 " name text,\n"
1476 " tbl_name text,\n"
1477 " rootpage integer,\n"
1478 " sql text\n"
1479 ")";
1480 new_argv[1] = 0;
1481 new_colv[0] = "sql";
1482 new_colv[1] = 0;
1483 callback(&data, 1, new_argv, new_colv);
drha18c5682000-10-08 22:20:57 +00001484 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001485 zShellStatic = azArg[1];
1486 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001487 "SELECT sql FROM "
1488 " (SELECT * FROM sqlite_master UNION ALL"
1489 " SELECT * FROM sqlite_temp_master) "
danielk1977bc6ada42004-06-30 08:20:16 +00001490 "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL "
drhe0bc4042002-06-25 01:09:11 +00001491 "ORDER BY substr(type,2,1), name",
danielk1977bc6ada42004-06-30 08:20:16 +00001492 callback, &data, &zErrMsg);
1493 zShellStatic = 0;
drha18c5682000-10-08 22:20:57 +00001494 }
drh75897232000-05-29 14:26:00 +00001495 }else{
danielk19776f8a5032004-05-10 10:34:51 +00001496 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001497 "SELECT sql FROM "
1498 " (SELECT * FROM sqlite_master UNION ALL"
1499 " SELECT * FROM sqlite_temp_master) "
drh0c356672005-09-10 22:40:53 +00001500 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001501 "ORDER BY substr(type,2,1), name",
drha18c5682000-10-08 22:20:57 +00001502 callback, &data, &zErrMsg
1503 );
drh75897232000-05-29 14:26:00 +00001504 }
drh75897232000-05-29 14:26:00 +00001505 if( zErrMsg ){
1506 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001507 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001508 }
1509 }else
1510
1511 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
drh5bb3eb92007-05-04 13:15:55 +00001512 sqlite3_snprintf(sizeof(p->separator), p->separator,
1513 "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
drh75897232000-05-29 14:26:00 +00001514 }else
1515
persicom7e2dfdd2002-04-18 02:46:52 +00001516 if( c=='s' && strncmp(azArg[0], "show", n)==0){
1517 int i;
1518 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
drh67505e72002-04-19 12:34:06 +00001519 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
drhdd45df82002-04-18 12:39:03 +00001520 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
persicom7e2dfdd2002-04-18 02:46:52 +00001521 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
drhfeac5f82004-08-01 00:10:45 +00001522 fprintf(p->out,"%9.9s: ", "nullvalue");
1523 output_c_string(p->out, p->nullvalue);
1524 fprintf(p->out, "\n");
drh67505e72002-04-19 12:34:06 +00001525 fprintf(p->out,"%9.9s: %s\n","output",
1526 strlen(p->outfile) ? p->outfile : "stdout");
drhfeac5f82004-08-01 00:10:45 +00001527 fprintf(p->out,"%9.9s: ", "separator");
1528 output_c_string(p->out, p->separator);
1529 fprintf(p->out, "\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001530 fprintf(p->out,"%9.9s: ","width");
1531 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
drhfeac5f82004-08-01 00:10:45 +00001532 fprintf(p->out,"%d ",p->colWidth[i]);
persicom7e2dfdd2002-04-18 02:46:52 +00001533 }
drhfeac5f82004-08-01 00:10:45 +00001534 fprintf(p->out,"\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001535 }else
1536
drh2dfbbca2000-07-28 14:32:48 +00001537 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
drhe3710332000-09-29 13:30:53 +00001538 char **azResult;
1539 int nRow, rc;
1540 char *zErrMsg;
drh44c2eb12003-04-30 11:38:26 +00001541 open_db(p);
drha50da102000-08-08 20:19:09 +00001542 if( nArg==1 ){
danielk19776f8a5032004-05-10 10:34:51 +00001543 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001544 "SELECT name FROM sqlite_master "
drh0c356672005-09-10 22:40:53 +00001545 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001546 "UNION ALL "
1547 "SELECT name FROM sqlite_temp_master "
1548 "WHERE type IN ('table','view') "
1549 "ORDER BY 1",
drha18c5682000-10-08 22:20:57 +00001550 &azResult, &nRow, 0, &zErrMsg
1551 );
drha50da102000-08-08 20:19:09 +00001552 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001553 zShellStatic = azArg[1];
1554 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001555 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001556 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001557 "UNION ALL "
1558 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001559 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001560 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001561 &azResult, &nRow, 0, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001562 );
danielk1977bc6ada42004-06-30 08:20:16 +00001563 zShellStatic = 0;
drha50da102000-08-08 20:19:09 +00001564 }
drh75897232000-05-29 14:26:00 +00001565 if( zErrMsg ){
1566 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001567 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001568 }
drhe3710332000-09-29 13:30:53 +00001569 if( rc==SQLITE_OK ){
1570 int len, maxlen = 0;
1571 int i, j;
1572 int nPrintCol, nPrintRow;
1573 for(i=1; i<=nRow; i++){
1574 if( azResult[i]==0 ) continue;
1575 len = strlen(azResult[i]);
1576 if( len>maxlen ) maxlen = len;
1577 }
1578 nPrintCol = 80/(maxlen+2);
1579 if( nPrintCol<1 ) nPrintCol = 1;
1580 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
1581 for(i=0; i<nPrintRow; i++){
1582 for(j=i+1; j<=nRow; j+=nPrintRow){
1583 char *zSp = j<=nPrintRow ? "" : " ";
1584 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
1585 }
1586 printf("\n");
1587 }
drh47ad6842006-11-08 12:25:42 +00001588 }else{
1589 rc = 1;
drhe3710332000-09-29 13:30:53 +00001590 }
danielk19776f8a5032004-05-10 10:34:51 +00001591 sqlite3_free_table(azResult);
drh75897232000-05-29 14:26:00 +00001592 }else
1593
drh3b1a9882007-11-02 12:53:03 +00001594 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
drh44c2eb12003-04-30 11:38:26 +00001595 open_db(p);
danielk19776f8a5032004-05-10 10:34:51 +00001596 sqlite3_busy_timeout(p->db, atoi(azArg[1]));
drh2dfbbca2000-07-28 14:32:48 +00001597 }else
drh3b1a9882007-11-02 12:53:03 +00001598
1599#if HAS_TIMER
1600 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){
1601 enableTimer = booleanValue(azArg[1]);
1602 }else
1603#endif
drh2dfbbca2000-07-28 14:32:48 +00001604
drh75897232000-05-29 14:26:00 +00001605 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
1606 int j;
drh43617e92006-03-06 20:55:46 +00001607 assert( nArg<=ArraySize(azArg) );
drh75897232000-05-29 14:26:00 +00001608 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
1609 p->colWidth[j-1] = atoi(azArg[j]);
1610 }
1611 }else
1612
drh3b1a9882007-11-02 12:53:03 +00001613
drh75897232000-05-29 14:26:00 +00001614 {
drh67505e72002-04-19 12:34:06 +00001615 fprintf(stderr, "unknown command or invalid arguments: "
1616 " \"%s\". Enter \".help\" for help\n", azArg[0]);
drh75897232000-05-29 14:26:00 +00001617 }
drh67505e72002-04-19 12:34:06 +00001618
1619 return rc;
drh75897232000-05-29 14:26:00 +00001620}
1621
drh67505e72002-04-19 12:34:06 +00001622/*
drh91a66392007-09-07 01:12:32 +00001623** Return TRUE if a semicolon occurs anywhere in the first N characters
1624** of string z[].
drh324ccef2003-02-05 14:06:20 +00001625*/
drh91a66392007-09-07 01:12:32 +00001626static int _contains_semicolon(const char *z, int N){
1627 int i;
1628 for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
1629 return 0;
drh324ccef2003-02-05 14:06:20 +00001630}
1631
1632/*
drh70c7a4b2003-04-26 03:03:06 +00001633** Test to see if a line consists entirely of whitespace.
1634*/
1635static int _all_whitespace(const char *z){
1636 for(; *z; z++){
drh4c755c02004-08-08 20:22:17 +00001637 if( isspace(*(unsigned char*)z) ) continue;
drh70c7a4b2003-04-26 03:03:06 +00001638 if( *z=='/' && z[1]=='*' ){
1639 z += 2;
1640 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
1641 if( *z==0 ) return 0;
1642 z++;
1643 continue;
1644 }
1645 if( *z=='-' && z[1]=='-' ){
1646 z += 2;
1647 while( *z && *z!='\n' ){ z++; }
1648 if( *z==0 ) return 1;
1649 continue;
1650 }
1651 return 0;
1652 }
1653 return 1;
1654}
1655
1656/*
drha9b17162003-04-29 18:01:28 +00001657** Return TRUE if the line typed in is an SQL command terminator other
1658** than a semi-colon. The SQL Server style "go" command is understood
1659** as is the Oracle "/".
1660*/
1661static int _is_command_terminator(const char *zLine){
drh4c755c02004-08-08 20:22:17 +00001662 while( isspace(*(unsigned char*)zLine) ){ zLine++; };
drha9b17162003-04-29 18:01:28 +00001663 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */
drhc8d74412004-08-31 23:41:26 +00001664 if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o'
1665 && _all_whitespace(&zLine[2]) ){
drha9b17162003-04-29 18:01:28 +00001666 return 1; /* SQL Server */
1667 }
1668 return 0;
1669}
1670
1671/*
drh67505e72002-04-19 12:34:06 +00001672** Read input from *in and process it. If *in==0 then input
1673** is interactive - the user is typing it it. Otherwise, input
1674** is coming from a file or device. A prompt is issued and history
1675** is saved only if input is interactive. An interrupt signal will
1676** cause this routine to exit immediately, unless input is interactive.
drhc28490c2006-10-26 14:25:58 +00001677**
1678** Return the number of errors.
drh67505e72002-04-19 12:34:06 +00001679*/
drhc28490c2006-10-26 14:25:58 +00001680static int process_input(struct callback_data *p, FILE *in){
danielk19772ac27622007-07-03 05:31:16 +00001681 char *zLine = 0;
drhdaffd0e2001-04-11 14:28:42 +00001682 char *zSql = 0;
1683 int nSql = 0;
drh91a66392007-09-07 01:12:32 +00001684 int nSqlPrior = 0;
drhdaffd0e2001-04-11 14:28:42 +00001685 char *zErrMsg;
drhc49f44e2006-10-26 18:15:42 +00001686 int rc;
1687 int errCnt = 0;
drhc28490c2006-10-26 14:25:58 +00001688 int lineno = 0;
1689 int startline = 0;
drhc49f44e2006-10-26 18:15:42 +00001690
1691 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
1692 fflush(p->out);
danielk19772ac27622007-07-03 05:31:16 +00001693 free(zLine);
drhc49f44e2006-10-26 18:15:42 +00001694 zLine = one_input_line(zSql, in);
1695 if( zLine==0 ){
1696 break; /* We have reached EOF */
1697 }
drh67505e72002-04-19 12:34:06 +00001698 if( seenInterrupt ){
1699 if( in!=0 ) break;
1700 seenInterrupt = 0;
1701 }
drhc28490c2006-10-26 14:25:58 +00001702 lineno++;
drhdaffd0e2001-04-11 14:28:42 +00001703 if( p->echoOn ) printf("%s\n", zLine);
drhf817b6b2003-06-16 00:16:41 +00001704 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
drh2af0b2d2002-02-21 02:25:02 +00001705 if( zLine && zLine[0]=='.' && nSql==0 ){
drhc49f44e2006-10-26 18:15:42 +00001706 rc = do_meta_command(zLine, p);
drh47ad6842006-11-08 12:25:42 +00001707 if( rc==2 ){
1708 break;
1709 }else if( rc ){
drhc49f44e2006-10-26 18:15:42 +00001710 errCnt++;
1711 }
drhdaffd0e2001-04-11 14:28:42 +00001712 continue;
1713 }
drhc717b382008-11-11 00:30:11 +00001714 if( _is_command_terminator(zLine) && sqlite3_complete(zSql) ){
drh5bb3eb92007-05-04 13:15:55 +00001715 memcpy(zLine,";",2);
drha9b17162003-04-29 18:01:28 +00001716 }
drh91a66392007-09-07 01:12:32 +00001717 nSqlPrior = nSql;
drhdaffd0e2001-04-11 14:28:42 +00001718 if( zSql==0 ){
1719 int i;
drh4c755c02004-08-08 20:22:17 +00001720 for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){}
drhdaffd0e2001-04-11 14:28:42 +00001721 if( zLine[i]!=0 ){
1722 nSql = strlen(zLine);
1723 zSql = malloc( nSql+1 );
drhc1f44942006-05-10 14:39:13 +00001724 if( zSql==0 ){
1725 fprintf(stderr, "out of memory\n");
1726 exit(1);
1727 }
drh5bb3eb92007-05-04 13:15:55 +00001728 memcpy(zSql, zLine, nSql+1);
drhc28490c2006-10-26 14:25:58 +00001729 startline = lineno;
drhdaffd0e2001-04-11 14:28:42 +00001730 }
1731 }else{
1732 int len = strlen(zLine);
1733 zSql = realloc( zSql, nSql + len + 2 );
1734 if( zSql==0 ){
1735 fprintf(stderr,"%s: out of memory!\n", Argv0);
1736 exit(1);
1737 }
drh5bb3eb92007-05-04 13:15:55 +00001738 zSql[nSql++] = '\n';
1739 memcpy(&zSql[nSql], zLine, len+1);
drhdaffd0e2001-04-11 14:28:42 +00001740 nSql += len;
1741 }
drh91a66392007-09-07 01:12:32 +00001742 if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
1743 && sqlite3_complete(zSql) ){
drhdaffd0e2001-04-11 14:28:42 +00001744 p->cnt = 0;
drh44c2eb12003-04-30 11:38:26 +00001745 open_db(p);
drh3b1a9882007-11-02 12:53:03 +00001746 BEGIN_TIMER;
danielk19776f8a5032004-05-10 10:34:51 +00001747 rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
drh3b1a9882007-11-02 12:53:03 +00001748 END_TIMER;
drh7f953e22002-07-13 17:33:45 +00001749 if( rc || zErrMsg ){
drhc28490c2006-10-26 14:25:58 +00001750 char zPrefix[100];
1751 if( in!=0 || !stdin_is_interactive ){
drh5bb3eb92007-05-04 13:15:55 +00001752 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
1753 "SQL error near line %d:", startline);
drhc28490c2006-10-26 14:25:58 +00001754 }else{
drh5bb3eb92007-05-04 13:15:55 +00001755 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "SQL error:");
drhc28490c2006-10-26 14:25:58 +00001756 }
drh7f953e22002-07-13 17:33:45 +00001757 if( zErrMsg!=0 ){
drhc28490c2006-10-26 14:25:58 +00001758 printf("%s %s\n", zPrefix, zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001759 sqlite3_free(zErrMsg);
drh7f953e22002-07-13 17:33:45 +00001760 zErrMsg = 0;
1761 }else{
drhc28490c2006-10-26 14:25:58 +00001762 printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
drh7f953e22002-07-13 17:33:45 +00001763 }
drhc49f44e2006-10-26 18:15:42 +00001764 errCnt++;
drhdaffd0e2001-04-11 14:28:42 +00001765 }
1766 free(zSql);
1767 zSql = 0;
1768 nSql = 0;
1769 }
1770 }
1771 if( zSql ){
drhdfef4992008-11-11 18:55:03 +00001772 if( !_all_whitespace(zSql) ) fprintf(stderr, "Incomplete SQL: %s\n", zSql);
drhdaffd0e2001-04-11 14:28:42 +00001773 free(zSql);
1774 }
danielk19772ac27622007-07-03 05:31:16 +00001775 free(zLine);
drhc49f44e2006-10-26 18:15:42 +00001776 return errCnt;
drhdaffd0e2001-04-11 14:28:42 +00001777}
1778
drh67505e72002-04-19 12:34:06 +00001779/*
1780** Return a pathname which is the user's home directory. A
1781** 0 return indicates an error of some kind. Space to hold the
1782** resulting string is obtained from malloc(). The calling
1783** function should free the result.
1784*/
1785static char *find_home_dir(void){
1786 char *home_dir = NULL;
persicom7e2dfdd2002-04-18 02:46:52 +00001787
chw97185482008-11-17 08:05:31 +00001788#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
drh67505e72002-04-19 12:34:06 +00001789 struct passwd *pwent;
1790 uid_t uid = getuid();
drhbd842ba2002-08-21 11:26:41 +00001791 if( (pwent=getpwuid(uid)) != NULL) {
1792 home_dir = pwent->pw_dir;
drh67505e72002-04-19 12:34:06 +00001793 }
1794#endif
1795
chw65d3c132007-11-12 21:09:10 +00001796#if defined(_WIN32_WCE)
1797 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
1798 */
1799 home_dir = strdup("/");
1800#else
1801
drh164a1b62006-08-19 11:15:20 +00001802#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
1803 if (!home_dir) {
1804 home_dir = getenv("USERPROFILE");
1805 }
1806#endif
1807
drh67505e72002-04-19 12:34:06 +00001808 if (!home_dir) {
1809 home_dir = getenv("HOME");
drh67505e72002-04-19 12:34:06 +00001810 }
1811
drhcdb36b72006-06-12 12:57:45 +00001812#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
drhe98d4fa2002-04-21 19:06:22 +00001813 if (!home_dir) {
drh164a1b62006-08-19 11:15:20 +00001814 char *zDrive, *zPath;
1815 int n;
1816 zDrive = getenv("HOMEDRIVE");
1817 zPath = getenv("HOMEPATH");
1818 if( zDrive && zPath ){
1819 n = strlen(zDrive) + strlen(zPath) + 1;
1820 home_dir = malloc( n );
1821 if( home_dir==0 ) return 0;
1822 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
1823 return home_dir;
1824 }
1825 home_dir = "c:\\";
drhe98d4fa2002-04-21 19:06:22 +00001826 }
1827#endif
1828
chw65d3c132007-11-12 21:09:10 +00001829#endif /* !_WIN32_WCE */
1830
drh67505e72002-04-19 12:34:06 +00001831 if( home_dir ){
drh5bb3eb92007-05-04 13:15:55 +00001832 int n = strlen(home_dir) + 1;
1833 char *z = malloc( n );
1834 if( z ) memcpy(z, home_dir, n);
drh67505e72002-04-19 12:34:06 +00001835 home_dir = z;
1836 }
drhe98d4fa2002-04-21 19:06:22 +00001837
drh67505e72002-04-19 12:34:06 +00001838 return home_dir;
1839}
1840
1841/*
1842** Read input from the file given by sqliterc_override. Or if that
1843** parameter is NULL, take input from ~/.sqliterc
1844*/
drh22fbcb82004-02-01 01:22:50 +00001845static void process_sqliterc(
1846 struct callback_data *p, /* Configuration data */
1847 const char *sqliterc_override /* Name of config file. NULL to use default */
1848){
persicom7e2dfdd2002-04-18 02:46:52 +00001849 char *home_dir = NULL;
drh22fbcb82004-02-01 01:22:50 +00001850 const char *sqliterc = sqliterc_override;
drh43617e92006-03-06 20:55:46 +00001851 char *zBuf = 0;
persicom7e2dfdd2002-04-18 02:46:52 +00001852 FILE *in = NULL;
drha959ac42007-06-20 13:10:00 +00001853 int nBuf;
persicom7e2dfdd2002-04-18 02:46:52 +00001854
1855 if (sqliterc == NULL) {
drh67505e72002-04-19 12:34:06 +00001856 home_dir = find_home_dir();
drhe98d4fa2002-04-21 19:06:22 +00001857 if( home_dir==0 ){
chw97185482008-11-17 08:05:31 +00001858#if !defined(__RTP__) && !defined(_WRS_KERNEL)
drhe98d4fa2002-04-21 19:06:22 +00001859 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
chw97185482008-11-17 08:05:31 +00001860#endif
drhe98d4fa2002-04-21 19:06:22 +00001861 return;
1862 }
drha959ac42007-06-20 13:10:00 +00001863 nBuf = strlen(home_dir) + 16;
1864 zBuf = malloc( nBuf );
drh22fbcb82004-02-01 01:22:50 +00001865 if( zBuf==0 ){
persicom7e2dfdd2002-04-18 02:46:52 +00001866 fprintf(stderr,"%s: out of memory!\n", Argv0);
1867 exit(1);
1868 }
drha959ac42007-06-20 13:10:00 +00001869 sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir);
drh67505e72002-04-19 12:34:06 +00001870 free(home_dir);
drh22fbcb82004-02-01 01:22:50 +00001871 sqliterc = (const char*)zBuf;
persicom7e2dfdd2002-04-18 02:46:52 +00001872 }
drha1f9b5e2004-02-14 16:31:02 +00001873 in = fopen(sqliterc,"rb");
drh22fbcb82004-02-01 01:22:50 +00001874 if( in ){
drhc28490c2006-10-26 14:25:58 +00001875 if( stdin_is_interactive ){
drhb695aca2007-07-30 20:41:52 +00001876 printf("-- Loading resources from %s\n",sqliterc);
drh22fbcb82004-02-01 01:22:50 +00001877 }
persicom7e2dfdd2002-04-18 02:46:52 +00001878 process_input(p,in);
drhdd45df82002-04-18 12:39:03 +00001879 fclose(in);
persicom7e2dfdd2002-04-18 02:46:52 +00001880 }
drh43617e92006-03-06 20:55:46 +00001881 free(zBuf);
persicom7e2dfdd2002-04-18 02:46:52 +00001882 return;
1883}
1884
drh67505e72002-04-19 12:34:06 +00001885/*
drhe1e38c42003-05-04 18:30:59 +00001886** Show available command line options
1887*/
1888static const char zOptions[] =
1889 " -init filename read/process named file\n"
1890 " -echo print commands before execution\n"
1891 " -[no]header turn headers on or off\n"
drhc49f44e2006-10-26 18:15:42 +00001892 " -bail stop after hitting an error\n"
1893 " -interactive force interactive I/O\n"
1894 " -batch force batch I/O\n"
drhe1e38c42003-05-04 18:30:59 +00001895 " -column set output mode to 'column'\n"
drhc49f44e2006-10-26 18:15:42 +00001896 " -csv set output mode to 'csv'\n"
drhe1e38c42003-05-04 18:30:59 +00001897 " -html set output mode to HTML\n"
1898 " -line set output mode to 'line'\n"
1899 " -list set output mode to 'list'\n"
1900 " -separator 'x' set output field separator (|)\n"
1901 " -nullvalue 'text' set text string for NULL values\n"
1902 " -version show SQLite version\n"
drhe1e38c42003-05-04 18:30:59 +00001903;
1904static void usage(int showDetail){
drh80e8be92006-08-29 12:04:19 +00001905 fprintf(stderr,
1906 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
1907 "FILENAME is the name of an SQLite database. A new database is created\n"
1908 "if the file does not previously exist.\n", Argv0);
drhe1e38c42003-05-04 18:30:59 +00001909 if( showDetail ){
drh80e8be92006-08-29 12:04:19 +00001910 fprintf(stderr, "OPTIONS include:\n%s", zOptions);
drhe1e38c42003-05-04 18:30:59 +00001911 }else{
1912 fprintf(stderr, "Use the -help option for additional information\n");
1913 }
1914 exit(1);
1915}
1916
1917/*
drh67505e72002-04-19 12:34:06 +00001918** Initialize the state information in data
1919*/
drh0850b532006-01-31 19:31:43 +00001920static void main_init(struct callback_data *data) {
persicom7e2dfdd2002-04-18 02:46:52 +00001921 memset(data, 0, sizeof(*data));
1922 data->mode = MODE_List;
drh5bb3eb92007-05-04 13:15:55 +00001923 memcpy(data->separator,"|", 2);
persicom7e2dfdd2002-04-18 02:46:52 +00001924 data->showHeader = 0;
drh5bb3eb92007-05-04 13:15:55 +00001925 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
1926 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
persicom7e2dfdd2002-04-18 02:46:52 +00001927}
1928
drh75897232000-05-29 14:26:00 +00001929int main(int argc, char **argv){
drh75897232000-05-29 14:26:00 +00001930 char *zErrMsg = 0;
1931 struct callback_data data;
drh22fbcb82004-02-01 01:22:50 +00001932 const char *zInitFile = 0;
1933 char *zFirstCmd = 0;
drh44c2eb12003-04-30 11:38:26 +00001934 int i;
drhc28490c2006-10-26 14:25:58 +00001935 int rc = 0;
drh75897232000-05-29 14:26:00 +00001936
drhdaffd0e2001-04-11 14:28:42 +00001937 Argv0 = argv[0];
persicom7e2dfdd2002-04-18 02:46:52 +00001938 main_init(&data);
drhc28490c2006-10-26 14:25:58 +00001939 stdin_is_interactive = isatty(0);
persicom7e2dfdd2002-04-18 02:46:52 +00001940
drh44c2eb12003-04-30 11:38:26 +00001941 /* Make sure we have a valid signal handler early, before anything
1942 ** else is done.
1943 */
drh4c504392000-10-16 22:06:40 +00001944#ifdef SIGINT
1945 signal(SIGINT, interrupt_handler);
1946#endif
drh44c2eb12003-04-30 11:38:26 +00001947
drh22fbcb82004-02-01 01:22:50 +00001948 /* Do an initial pass through the command-line argument to locate
1949 ** the name of the database file, the name of the initialization file,
1950 ** and the first command to execute.
drh44c2eb12003-04-30 11:38:26 +00001951 */
drh22fbcb82004-02-01 01:22:50 +00001952 for(i=1; i<argc-1; i++){
drhc28490c2006-10-26 14:25:58 +00001953 char *z;
drh44c2eb12003-04-30 11:38:26 +00001954 if( argv[i][0]!='-' ) break;
drhc28490c2006-10-26 14:25:58 +00001955 z = argv[i];
1956 if( z[0]=='-' && z[1]=='-' ) z++;
drh44c2eb12003-04-30 11:38:26 +00001957 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
1958 i++;
drh22fbcb82004-02-01 01:22:50 +00001959 }else if( strcmp(argv[i],"-init")==0 ){
1960 i++;
1961 zInitFile = argv[i];
drh44c2eb12003-04-30 11:38:26 +00001962 }
1963 }
drh22fbcb82004-02-01 01:22:50 +00001964 if( i<argc ){
danielk197729bafea2008-06-26 10:41:19 +00001965#if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2
pweilbacherd190be82008-04-15 18:50:02 +00001966 data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] );
1967#else
drh22fbcb82004-02-01 01:22:50 +00001968 data.zDbFilename = argv[i++];
pweilbacherd190be82008-04-15 18:50:02 +00001969#endif
drh22fbcb82004-02-01 01:22:50 +00001970 }else{
danielk197703aded42004-11-22 05:26:27 +00001971#ifndef SQLITE_OMIT_MEMORYDB
drh22fbcb82004-02-01 01:22:50 +00001972 data.zDbFilename = ":memory:";
danielk197703aded42004-11-22 05:26:27 +00001973#else
1974 data.zDbFilename = 0;
1975#endif
drh22fbcb82004-02-01 01:22:50 +00001976 }
1977 if( i<argc ){
1978 zFirstCmd = argv[i++];
1979 }
drh44c2eb12003-04-30 11:38:26 +00001980 data.out = stdout;
1981
drh01b41712005-08-29 23:06:23 +00001982#ifdef SQLITE_OMIT_MEMORYDB
1983 if( data.zDbFilename==0 ){
1984 fprintf(stderr,"%s: no database filename specified\n", argv[0]);
1985 exit(1);
1986 }
1987#endif
1988
drh44c2eb12003-04-30 11:38:26 +00001989 /* Go ahead and open the database file if it already exists. If the
1990 ** file does not exist, delay opening it. This prevents empty database
1991 ** files from being created if a user mistypes the database name argument
1992 ** to the sqlite command-line tool.
1993 */
drhc8d74412004-08-31 23:41:26 +00001994 if( access(data.zDbFilename, 0)==0 ){
drh44c2eb12003-04-30 11:38:26 +00001995 open_db(&data);
1996 }
1997
drh22fbcb82004-02-01 01:22:50 +00001998 /* Process the initialization file if there is one. If no -init option
1999 ** is given on the command line, look for a file named ~/.sqliterc and
2000 ** try to process it.
drh44c2eb12003-04-30 11:38:26 +00002001 */
drh22fbcb82004-02-01 01:22:50 +00002002 process_sqliterc(&data,zInitFile);
drh44c2eb12003-04-30 11:38:26 +00002003
drh22fbcb82004-02-01 01:22:50 +00002004 /* Make a second pass through the command-line argument and set
2005 ** options. This second pass is delayed until after the initialization
2006 ** file is processed so that the command-line arguments will override
2007 ** settings in the initialization file.
drh44c2eb12003-04-30 11:38:26 +00002008 */
drh22fbcb82004-02-01 01:22:50 +00002009 for(i=1; i<argc && argv[i][0]=='-'; i++){
2010 char *z = argv[i];
drhc28490c2006-10-26 14:25:58 +00002011 if( z[1]=='-' ){ z++; }
drh2e584cd2006-09-25 13:09:22 +00002012 if( strcmp(z,"-init")==0 ){
drh22fbcb82004-02-01 01:22:50 +00002013 i++;
2014 }else if( strcmp(z,"-html")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00002015 data.mode = MODE_Html;
drh22fbcb82004-02-01 01:22:50 +00002016 }else if( strcmp(z,"-list")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00002017 data.mode = MODE_List;
drh22fbcb82004-02-01 01:22:50 +00002018 }else if( strcmp(z,"-line")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00002019 data.mode = MODE_Line;
drh22fbcb82004-02-01 01:22:50 +00002020 }else if( strcmp(z,"-column")==0 ){
drh8b32e172002-04-08 02:42:57 +00002021 data.mode = MODE_Column;
drhc49f44e2006-10-26 18:15:42 +00002022 }else if( strcmp(z,"-csv")==0 ){
2023 data.mode = MODE_Csv;
drh5bb3eb92007-05-04 13:15:55 +00002024 memcpy(data.separator,",",2);
drh22fbcb82004-02-01 01:22:50 +00002025 }else if( strcmp(z,"-separator")==0 ){
2026 i++;
drh5bb3eb92007-05-04 13:15:55 +00002027 sqlite3_snprintf(sizeof(data.separator), data.separator,
2028 "%.*s",(int)sizeof(data.separator)-1,argv[i]);
drh22fbcb82004-02-01 01:22:50 +00002029 }else if( strcmp(z,"-nullvalue")==0 ){
2030 i++;
drh5bb3eb92007-05-04 13:15:55 +00002031 sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
2032 "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
drh22fbcb82004-02-01 01:22:50 +00002033 }else if( strcmp(z,"-header")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00002034 data.showHeader = 1;
drh22fbcb82004-02-01 01:22:50 +00002035 }else if( strcmp(z,"-noheader")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00002036 data.showHeader = 0;
drh22fbcb82004-02-01 01:22:50 +00002037 }else if( strcmp(z,"-echo")==0 ){
drhdaffd0e2001-04-11 14:28:42 +00002038 data.echoOn = 1;
drhc49f44e2006-10-26 18:15:42 +00002039 }else if( strcmp(z,"-bail")==0 ){
2040 bail_on_error = 1;
drh22fbcb82004-02-01 01:22:50 +00002041 }else if( strcmp(z,"-version")==0 ){
drhc8d74412004-08-31 23:41:26 +00002042 printf("%s\n", sqlite3_libversion());
drh151e3e12006-06-06 12:32:21 +00002043 return 0;
drhc28490c2006-10-26 14:25:58 +00002044 }else if( strcmp(z,"-interactive")==0 ){
2045 stdin_is_interactive = 1;
2046 }else if( strcmp(z,"-batch")==0 ){
2047 stdin_is_interactive = 0;
drh80e8be92006-08-29 12:04:19 +00002048 }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
drhe1e38c42003-05-04 18:30:59 +00002049 usage(1);
drh1e5d0e92000-05-31 23:33:17 +00002050 }else{
drh22fbcb82004-02-01 01:22:50 +00002051 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
drhe1e38c42003-05-04 18:30:59 +00002052 fprintf(stderr,"Use -help for a list of options.\n");
drh1e5d0e92000-05-31 23:33:17 +00002053 return 1;
2054 }
2055 }
drh44c2eb12003-04-30 11:38:26 +00002056
drh22fbcb82004-02-01 01:22:50 +00002057 if( zFirstCmd ){
drh44c2eb12003-04-30 11:38:26 +00002058 /* Run just the command that follows the database name
2059 */
drh22fbcb82004-02-01 01:22:50 +00002060 if( zFirstCmd[0]=='.' ){
2061 do_meta_command(zFirstCmd, &data);
drh6ff13852001-11-25 13:18:23 +00002062 exit(0);
2063 }else{
2064 int rc;
drh44c2eb12003-04-30 11:38:26 +00002065 open_db(&data);
danielk19776f8a5032004-05-10 10:34:51 +00002066 rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
drh6ff13852001-11-25 13:18:23 +00002067 if( rc!=0 && zErrMsg!=0 ){
2068 fprintf(stderr,"SQL error: %s\n", zErrMsg);
2069 exit(1);
2070 }
drh75897232000-05-29 14:26:00 +00002071 }
2072 }else{
drh44c2eb12003-04-30 11:38:26 +00002073 /* Run commands received from standard input
2074 */
drhc28490c2006-10-26 14:25:58 +00002075 if( stdin_is_interactive ){
drh67505e72002-04-19 12:34:06 +00002076 char *zHome;
2077 char *zHistory = 0;
drh5bb3eb92007-05-04 13:15:55 +00002078 int nHistory;
drh75897232000-05-29 14:26:00 +00002079 printf(
drhb217a572000-08-22 13:40:18 +00002080 "SQLite version %s\n"
mihailim65df9db2008-06-28 11:29:22 +00002081 "Enter \".help\" for instructions\n"
2082 "Enter SQL statements terminated with a \";\"\n",
drhc8d74412004-08-31 23:41:26 +00002083 sqlite3_libversion()
drh75897232000-05-29 14:26:00 +00002084 );
drh67505e72002-04-19 12:34:06 +00002085 zHome = find_home_dir();
drh5bb3eb92007-05-04 13:15:55 +00002086 if( zHome && (zHistory = malloc(nHistory = strlen(zHome)+20))!=0 ){
2087 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
drh67505e72002-04-19 12:34:06 +00002088 }
danielk19774af00c62005-01-23 23:43:21 +00002089#if defined(HAVE_READLINE) && HAVE_READLINE==1
drh67505e72002-04-19 12:34:06 +00002090 if( zHistory ) read_history(zHistory);
danielk19774af00c62005-01-23 23:43:21 +00002091#endif
drhc28490c2006-10-26 14:25:58 +00002092 rc = process_input(&data, 0);
drh67505e72002-04-19 12:34:06 +00002093 if( zHistory ){
2094 stifle_history(100);
2095 write_history(zHistory);
adamd0a3daa32006-07-28 20:16:14 +00002096 free(zHistory);
drh67505e72002-04-19 12:34:06 +00002097 }
adamd0a3daa32006-07-28 20:16:14 +00002098 free(zHome);
drhdaffd0e2001-04-11 14:28:42 +00002099 }else{
drhc28490c2006-10-26 14:25:58 +00002100 rc = process_input(&data, stdin);
drh75897232000-05-29 14:26:00 +00002101 }
2102 }
drh33048c02001-10-01 14:29:22 +00002103 set_table_name(&data, 0);
adamd0a3daa32006-07-28 20:16:14 +00002104 if( db ){
2105 if( sqlite3_close(db)!=SQLITE_OK ){
2106 fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
2107 }
2108 }
drhc28490c2006-10-26 14:25:58 +00002109 return rc;
drh75897232000-05-29 14:26:00 +00002110}