blob: 6f651350a6b17efabae7313264714dcd4891a762 [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**
drh45e29d82006-11-20 16:21:10 +000015** $Id: shell.c,v 1.156 2006/11/20 16:21:10 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};
drh45e29d82006-11-20 16:21:10 +0000228
drh8e7e7a22000-05-30 18:45:23 +0000229/*
drh75897232000-05-29 14:26:00 +0000230** An pointer to an instance of this structure is passed from
231** the main program to the callback. This is used to communicate
232** state and mode information.
233*/
234struct callback_data {
danielk197792f9a1b2004-06-19 09:08:16 +0000235 sqlite3 *db; /* The database */
drhdaffd0e2001-04-11 14:28:42 +0000236 int echoOn; /* True to echo input commands */
drh28bd4bc2000-06-15 15:57:22 +0000237 int cnt; /* Number of records displayed so far */
238 FILE *out; /* Write results here */
239 int mode; /* An output mode setting */
drh45e29d82006-11-20 16:21:10 +0000240 int writableSchema; /* True if PRAGMA writable_schema=ON */
drh28bd4bc2000-06-15 15:57:22 +0000241 int showHeader; /* True to show column names in List or Column mode */
drh33048c02001-10-01 14:29:22 +0000242 char *zDestTable; /* Name of destination table when MODE_Insert */
drh28bd4bc2000-06-15 15:57:22 +0000243 char separator[20]; /* Separator character for MODE_List */
drha0c66f52000-07-29 13:20:21 +0000244 int colWidth[100]; /* Requested width of each column when in column mode*/
245 int actualWidth[100]; /* Actual width of each column */
drh83965662003-04-17 02:54:13 +0000246 char nullvalue[20]; /* The text to print when a NULL comes back from
247 ** the database */
persicom7e2dfdd2002-04-18 02:46:52 +0000248 struct previous_mode_data explainPrev;
drh83965662003-04-17 02:54:13 +0000249 /* Holds the mode information just before
250 ** .explain ON */
drh44c2eb12003-04-30 11:38:26 +0000251 char outfile[FILENAME_MAX]; /* Filename for *out */
252 const char *zDbFilename; /* name of the database file */
drh75897232000-05-29 14:26:00 +0000253};
254
255/*
256** These are the allowed modes.
257*/
drh967e8b72000-06-21 13:59:10 +0000258#define MODE_Line 0 /* One column per line. Blank line between records */
drh75897232000-05-29 14:26:00 +0000259#define MODE_Column 1 /* One record per line in neat columns */
260#define MODE_List 2 /* One record per line with a separator */
drhe3710332000-09-29 13:30:53 +0000261#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
262#define MODE_Html 4 /* Generate an XHTML table */
263#define MODE_Insert 5 /* Generate SQL "insert" statements */
drhfeac5f82004-08-01 00:10:45 +0000264#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
drh8e64d1c2004-10-07 00:32:39 +0000265#define MODE_Csv 7 /* Quote strings, numbers are plain */
266#define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */
persicom7e2dfdd2002-04-18 02:46:52 +0000267
drh0850b532006-01-31 19:31:43 +0000268static const char *modeDescr[MODE_NUM_OF] = {
persicom7e2dfdd2002-04-18 02:46:52 +0000269 "line",
270 "column",
271 "list",
272 "semi",
273 "html",
drhfeac5f82004-08-01 00:10:45 +0000274 "insert",
275 "tcl",
drh8e64d1c2004-10-07 00:32:39 +0000276 "csv",
persicom7e2dfdd2002-04-18 02:46:52 +0000277};
drh75897232000-05-29 14:26:00 +0000278
279/*
280** Number of elements in an array
281*/
282#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
283
284/*
drh28bd4bc2000-06-15 15:57:22 +0000285** Output the given string as a quoted string using SQL quoting conventions.
286*/
287static void output_quoted_string(FILE *out, const char *z){
288 int i;
289 int nSingle = 0;
drh28bd4bc2000-06-15 15:57:22 +0000290 for(i=0; z[i]; i++){
291 if( z[i]=='\'' ) nSingle++;
drh28bd4bc2000-06-15 15:57:22 +0000292 }
293 if( nSingle==0 ){
294 fprintf(out,"'%s'",z);
drh28bd4bc2000-06-15 15:57:22 +0000295 }else{
296 fprintf(out,"'");
297 while( *z ){
298 for(i=0; z[i] && z[i]!='\''; i++){}
299 if( i==0 ){
300 fprintf(out,"''");
301 z++;
302 }else if( z[i]=='\'' ){
303 fprintf(out,"%.*s''",i,z);
304 z += i+1;
305 }else{
drhcd7d2732002-02-26 23:24:26 +0000306 fprintf(out,"%s",z);
drh28bd4bc2000-06-15 15:57:22 +0000307 break;
308 }
309 }
drhcd7d2732002-02-26 23:24:26 +0000310 fprintf(out,"'");
drh28bd4bc2000-06-15 15:57:22 +0000311 }
312}
313
314/*
drhfeac5f82004-08-01 00:10:45 +0000315** Output the given string as a quoted according to C or TCL quoting rules.
316*/
317static void output_c_string(FILE *out, const char *z){
318 unsigned int c;
319 fputc('"', out);
320 while( (c = *(z++))!=0 ){
321 if( c=='\\' ){
322 fputc(c, out);
323 fputc(c, out);
324 }else if( c=='\t' ){
325 fputc('\\', out);
326 fputc('t', out);
327 }else if( c=='\n' ){
328 fputc('\\', out);
329 fputc('n', out);
330 }else if( c=='\r' ){
331 fputc('\\', out);
332 fputc('r', out);
333 }else if( !isprint(c) ){
drh0a8640d2005-08-30 20:12:02 +0000334 fprintf(out, "\\%03o", c&0xff);
drhfeac5f82004-08-01 00:10:45 +0000335 }else{
336 fputc(c, out);
337 }
338 }
339 fputc('"', out);
340}
341
342/*
drhc08a4f12000-06-15 16:49:48 +0000343** Output the given string with characters that are special to
344** HTML escaped.
345*/
346static void output_html_string(FILE *out, const char *z){
347 int i;
348 while( *z ){
349 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
350 if( i>0 ){
351 fprintf(out,"%.*s",i,z);
352 }
353 if( z[i]=='<' ){
354 fprintf(out,"&lt;");
355 }else if( z[i]=='&' ){
356 fprintf(out,"&amp;");
357 }else{
358 break;
359 }
360 z += i + 1;
361 }
362}
363
364/*
drhc49f44e2006-10-26 18:15:42 +0000365** If a field contains any character identified by a 1 in the following
366** array, then the string must be quoted for CSV.
367*/
368static const char needCsvQuote[] = {
369 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
370 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
371 1, 0, 1, 0, 0, 0, 0, 1, 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, 0,
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
384 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
385};
386
387/*
drh8e64d1c2004-10-07 00:32:39 +0000388** Output a single term of CSV. Actually, p->separator is used for
389** the separator, which may or may not be a comma. p->nullvalue is
390** the null value. Strings are quoted using ANSI-C rules. Numbers
391** appear outside of quotes.
392*/
393static void output_csv(struct callback_data *p, const char *z, int bSep){
drhc49f44e2006-10-26 18:15:42 +0000394 FILE *out = p->out;
drh8e64d1c2004-10-07 00:32:39 +0000395 if( z==0 ){
drhc49f44e2006-10-26 18:15:42 +0000396 fprintf(out,"%s",p->nullvalue);
drh8e64d1c2004-10-07 00:32:39 +0000397 }else{
drhc49f44e2006-10-26 18:15:42 +0000398 int i;
399 for(i=0; z[i]; i++){
400 if( needCsvQuote[((unsigned char*)z)[i]] ){
401 i = 0;
402 break;
403 }
404 }
405 if( i==0 ){
406 putc('"', out);
407 for(i=0; z[i]; i++){
408 if( z[i]=='"' ) putc('"', out);
409 putc(z[i], out);
410 }
411 putc('"', out);
412 }else{
413 fprintf(out, "%s", z);
414 }
drh8e64d1c2004-10-07 00:32:39 +0000415 }
416 if( bSep ){
417 fprintf(p->out, p->separator);
418 }
419}
420
danielk19774af00c62005-01-23 23:43:21 +0000421#ifdef SIGINT
drh8e64d1c2004-10-07 00:32:39 +0000422/*
drh4c504392000-10-16 22:06:40 +0000423** This routine runs when the user presses Ctrl-C
424*/
425static void interrupt_handler(int NotUsed){
drh67505e72002-04-19 12:34:06 +0000426 seenInterrupt = 1;
danielk19776f8a5032004-05-10 10:34:51 +0000427 if( db ) sqlite3_interrupt(db);
drh4c504392000-10-16 22:06:40 +0000428}
danielk19774af00c62005-01-23 23:43:21 +0000429#endif
drh4c504392000-10-16 22:06:40 +0000430
431/*
drh75897232000-05-29 14:26:00 +0000432** This is the callback routine that the SQLite library
433** invokes for each row of a query result.
434*/
435static int callback(void *pArg, int nArg, char **azArg, char **azCol){
436 int i;
437 struct callback_data *p = (struct callback_data*)pArg;
438 switch( p->mode ){
439 case MODE_Line: {
drhe3710332000-09-29 13:30:53 +0000440 int w = 5;
drh6a535342001-10-19 16:44:56 +0000441 if( azArg==0 ) break;
drhe3710332000-09-29 13:30:53 +0000442 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000443 int len = strlen(azCol[i] ? azCol[i] : "");
drhe3710332000-09-29 13:30:53 +0000444 if( len>w ) w = len;
445 }
drh75897232000-05-29 14:26:00 +0000446 if( p->cnt++>0 ) fprintf(p->out,"\n");
447 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000448 fprintf(p->out,"%*s = %s\n", w, azCol[i],
drha69d9162003-04-17 22:57:53 +0000449 azArg[i] ? azArg[i] : p->nullvalue);
drh75897232000-05-29 14:26:00 +0000450 }
451 break;
452 }
453 case MODE_Column: {
drha0c66f52000-07-29 13:20:21 +0000454 if( p->cnt++==0 ){
drh75897232000-05-29 14:26:00 +0000455 for(i=0; i<nArg; i++){
drha0c66f52000-07-29 13:20:21 +0000456 int w, n;
457 if( i<ArraySize(p->colWidth) ){
drh75897232000-05-29 14:26:00 +0000458 w = p->colWidth[i];
459 }else{
drha0c66f52000-07-29 13:20:21 +0000460 w = 0;
drh75897232000-05-29 14:26:00 +0000461 }
drha0c66f52000-07-29 13:20:21 +0000462 if( w<=0 ){
drhff6e9112000-08-28 16:21:58 +0000463 w = strlen(azCol[i] ? azCol[i] : "");
drha0c66f52000-07-29 13:20:21 +0000464 if( w<10 ) w = 10;
persicom7e2dfdd2002-04-18 02:46:52 +0000465 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
drha0c66f52000-07-29 13:20:21 +0000466 if( w<n ) w = n;
467 }
468 if( i<ArraySize(p->actualWidth) ){
persicom1d0b8722002-04-18 02:53:04 +0000469 p->actualWidth[i] = w;
drha0c66f52000-07-29 13:20:21 +0000470 }
471 if( p->showHeader ){
472 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
473 }
474 }
475 if( p->showHeader ){
476 for(i=0; i<nArg; i++){
477 int w;
478 if( i<ArraySize(p->actualWidth) ){
479 w = p->actualWidth[i];
480 }else{
481 w = 10;
482 }
483 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
484 "----------------------------------------------------------",
485 i==nArg-1 ? "\n": " ");
486 }
drh75897232000-05-29 14:26:00 +0000487 }
488 }
drh6a535342001-10-19 16:44:56 +0000489 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000490 for(i=0; i<nArg; i++){
491 int w;
drha0c66f52000-07-29 13:20:21 +0000492 if( i<ArraySize(p->actualWidth) ){
493 w = p->actualWidth[i];
drh75897232000-05-29 14:26:00 +0000494 }else{
495 w = 10;
496 }
drhc61053b2000-06-04 12:58:36 +0000497 fprintf(p->out,"%-*.*s%s",w,w,
persicom7e2dfdd2002-04-18 02:46:52 +0000498 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
drh75897232000-05-29 14:26:00 +0000499 }
500 break;
501 }
drhe3710332000-09-29 13:30:53 +0000502 case MODE_Semi:
drh75897232000-05-29 14:26:00 +0000503 case MODE_List: {
504 if( p->cnt++==0 && p->showHeader ){
505 for(i=0; i<nArg; i++){
506 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
507 }
508 }
drh6a535342001-10-19 16:44:56 +0000509 if( azArg==0 ) break;
drh75897232000-05-29 14:26:00 +0000510 for(i=0; i<nArg; i++){
drh4c653a02000-06-07 01:27:47 +0000511 char *z = azArg[i];
persicom7e2dfdd2002-04-18 02:46:52 +0000512 if( z==0 ) z = p->nullvalue;
drh71172c52002-01-24 00:00:21 +0000513 fprintf(p->out, "%s", z);
drhe3710332000-09-29 13:30:53 +0000514 if( i<nArg-1 ){
515 fprintf(p->out, "%s", p->separator);
516 }else if( p->mode==MODE_Semi ){
517 fprintf(p->out, ";\n");
518 }else{
519 fprintf(p->out, "\n");
520 }
drh75897232000-05-29 14:26:00 +0000521 }
522 break;
523 }
drh1e5d0e92000-05-31 23:33:17 +0000524 case MODE_Html: {
525 if( p->cnt++==0 && p->showHeader ){
526 fprintf(p->out,"<TR>");
527 for(i=0; i<nArg; i++){
528 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
529 }
530 fprintf(p->out,"</TR>\n");
531 }
drh6a535342001-10-19 16:44:56 +0000532 if( azArg==0 ) break;
drh28bd4bc2000-06-15 15:57:22 +0000533 fprintf(p->out,"<TR>");
drh1e5d0e92000-05-31 23:33:17 +0000534 for(i=0; i<nArg; i++){
drhc08a4f12000-06-15 16:49:48 +0000535 fprintf(p->out,"<TD>");
persicom7e2dfdd2002-04-18 02:46:52 +0000536 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
drhc08a4f12000-06-15 16:49:48 +0000537 fprintf(p->out,"</TD>\n");
drh1e5d0e92000-05-31 23:33:17 +0000538 }
drh7d686b22002-11-11 13:56:47 +0000539 fprintf(p->out,"</TR>\n");
drh1e5d0e92000-05-31 23:33:17 +0000540 break;
541 }
drhfeac5f82004-08-01 00:10:45 +0000542 case MODE_Tcl: {
543 if( p->cnt++==0 && p->showHeader ){
544 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000545 output_c_string(p->out,azCol[i] ? azCol[i] : "");
drhfeac5f82004-08-01 00:10:45 +0000546 fprintf(p->out, "%s", p->separator);
547 }
548 fprintf(p->out,"\n");
549 }
550 if( azArg==0 ) break;
551 for(i=0; i<nArg; i++){
552 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
553 fprintf(p->out, "%s", p->separator);
554 }
555 fprintf(p->out,"\n");
556 break;
557 }
drh8e64d1c2004-10-07 00:32:39 +0000558 case MODE_Csv: {
559 if( p->cnt++==0 && p->showHeader ){
560 for(i=0; i<nArg; i++){
drh2cc55692006-06-27 20:39:04 +0000561 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
drh8e64d1c2004-10-07 00:32:39 +0000562 }
563 fprintf(p->out,"\n");
564 }
565 if( azArg==0 ) break;
566 for(i=0; i<nArg; i++){
567 output_csv(p, azArg[i], i<nArg-1);
568 }
569 fprintf(p->out,"\n");
570 break;
571 }
drh28bd4bc2000-06-15 15:57:22 +0000572 case MODE_Insert: {
drh6a535342001-10-19 16:44:56 +0000573 if( azArg==0 ) break;
drh33048c02001-10-01 14:29:22 +0000574 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
drh28bd4bc2000-06-15 15:57:22 +0000575 for(i=0; i<nArg; i++){
576 char *zSep = i>0 ? ",": "";
577 if( azArg[i]==0 ){
578 fprintf(p->out,"%sNULL",zSep);
drhc8d74412004-08-31 23:41:26 +0000579 }else if( isNumber(azArg[i], 0) ){
drh28bd4bc2000-06-15 15:57:22 +0000580 fprintf(p->out,"%s%s",zSep, azArg[i]);
581 }else{
582 if( zSep[0] ) fprintf(p->out,"%s",zSep);
583 output_quoted_string(p->out, azArg[i]);
584 }
585 }
586 fprintf(p->out,");\n");
drh6a535342001-10-19 16:44:56 +0000587 break;
drh28bd4bc2000-06-15 15:57:22 +0000588 }
persicom1d0b8722002-04-18 02:53:04 +0000589 }
drh75897232000-05-29 14:26:00 +0000590 return 0;
591}
592
593/*
drh33048c02001-10-01 14:29:22 +0000594** Set the destination table field of the callback_data structure to
595** the name of the table given. Escape any quote characters in the
596** table name.
597*/
598static void set_table_name(struct callback_data *p, const char *zName){
599 int i, n;
600 int needQuote;
601 char *z;
602
603 if( p->zDestTable ){
604 free(p->zDestTable);
605 p->zDestTable = 0;
606 }
607 if( zName==0 ) return;
drh4c755c02004-08-08 20:22:17 +0000608 needQuote = !isalpha((unsigned char)*zName) && *zName!='_';
drh33048c02001-10-01 14:29:22 +0000609 for(i=n=0; zName[i]; i++, n++){
drh4c755c02004-08-08 20:22:17 +0000610 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){
drh33048c02001-10-01 14:29:22 +0000611 needQuote = 1;
612 if( zName[i]=='\'' ) n++;
613 }
614 }
615 if( needQuote ) n += 2;
616 z = p->zDestTable = malloc( n+1 );
617 if( z==0 ){
618 fprintf(stderr,"Out of memory!\n");
619 exit(1);
620 }
621 n = 0;
622 if( needQuote ) z[n++] = '\'';
623 for(i=0; zName[i]; i++){
624 z[n++] = zName[i];
625 if( zName[i]=='\'' ) z[n++] = '\'';
626 }
627 if( needQuote ) z[n++] = '\'';
628 z[n] = 0;
629}
630
danielk19772a02e332004-06-05 08:04:36 +0000631/* zIn is either a pointer to a NULL-terminated string in memory obtained
632** from malloc(), or a NULL pointer. The string pointed to by zAppend is
633** added to zIn, and the result returned in memory obtained from malloc().
634** zIn, if it was not NULL, is freed.
635**
636** If the third argument, quote, is not '\0', then it is used as a
637** quote character for zAppend.
638*/
drhc28490c2006-10-26 14:25:58 +0000639static char *appendText(char *zIn, char const *zAppend, char quote){
danielk19772a02e332004-06-05 08:04:36 +0000640 int len;
641 int i;
642 int nAppend = strlen(zAppend);
643 int nIn = (zIn?strlen(zIn):0);
644
645 len = nAppend+nIn+1;
646 if( quote ){
647 len += 2;
648 for(i=0; i<nAppend; i++){
649 if( zAppend[i]==quote ) len++;
650 }
651 }
652
653 zIn = (char *)realloc(zIn, len);
654 if( !zIn ){
655 return 0;
656 }
657
658 if( quote ){
659 char *zCsr = &zIn[nIn];
660 *zCsr++ = quote;
661 for(i=0; i<nAppend; i++){
662 *zCsr++ = zAppend[i];
663 if( zAppend[i]==quote ) *zCsr++ = quote;
664 }
665 *zCsr++ = quote;
666 *zCsr++ = '\0';
667 assert( (zCsr-zIn)==len );
668 }else{
669 memcpy(&zIn[nIn], zAppend, nAppend);
670 zIn[len-1] = '\0';
671 }
672
673 return zIn;
674}
675
drhdd3d4592004-08-30 01:54:05 +0000676
677/*
678** Execute a query statement that has a single result column. Print
679** that result column on a line by itself with a semicolon terminator.
drh45e29d82006-11-20 16:21:10 +0000680**
681** This is used, for example, to show the schema of the database by
682** querying the SQLITE_MASTER table.
drhdd3d4592004-08-30 01:54:05 +0000683*/
684static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
685 sqlite3_stmt *pSelect;
686 int rc;
687 rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
688 if( rc!=SQLITE_OK || !pSelect ){
689 return rc;
690 }
691 rc = sqlite3_step(pSelect);
692 while( rc==SQLITE_ROW ){
693 fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
694 rc = sqlite3_step(pSelect);
695 }
696 return sqlite3_finalize(pSelect);
697}
698
699
drh33048c02001-10-01 14:29:22 +0000700/*
drh4c653a02000-06-07 01:27:47 +0000701** This is a different callback routine used for dumping the database.
702** Each row received by this callback consists of a table name,
703** the table type ("index" or "table") and SQL to create the table.
704** This routine should print text sufficient to recreate the table.
705*/
706static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
danielk19772a02e332004-06-05 08:04:36 +0000707 int rc;
708 const char *zTable;
709 const char *zType;
710 const char *zSql;
drhdaffd0e2001-04-11 14:28:42 +0000711 struct callback_data *p = (struct callback_data *)pArg;
danielk19772a02e332004-06-05 08:04:36 +0000712
drh4c653a02000-06-07 01:27:47 +0000713 if( nArg!=3 ) return 1;
danielk19772a02e332004-06-05 08:04:36 +0000714 zTable = azArg[0];
715 zType = azArg[1];
716 zSql = azArg[2];
717
drh00b950d2005-09-11 02:03:03 +0000718 if( strcmp(zTable, "sqlite_sequence")==0 ){
drhf8eb96a2005-02-03 00:42:34 +0000719 fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
drh00b950d2005-09-11 02:03:03 +0000720 }else if( strcmp(zTable, "sqlite_stat1")==0 ){
721 fprintf(p->out, "ANALYZE sqlite_master;\n");
722 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
723 return 0;
drh45e29d82006-11-20 16:21:10 +0000724 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
725 char *zIns;
726 if( !p->writableSchema ){
727 fprintf(p->out, "PRAGMA writable_schema=ON;\n");
728 p->writableSchema = 1;
729 }
730 zIns = sqlite3_mprintf(
731 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
732 "VALUES('table','%q','%q',0,'%q');",
733 zTable, zTable, zSql);
734 fprintf(p->out, "%s\n", zIns);
735 sqlite3_free(zIns);
736 return 0;
drh00b950d2005-09-11 02:03:03 +0000737 }else{
738 fprintf(p->out, "%s;\n", zSql);
drhf8eb96a2005-02-03 00:42:34 +0000739 }
danielk19772a02e332004-06-05 08:04:36 +0000740
741 if( strcmp(zType, "table")==0 ){
742 sqlite3_stmt *pTableInfo = 0;
danielk19772a02e332004-06-05 08:04:36 +0000743 char *zSelect = 0;
744 char *zTableInfo = 0;
745 char *zTmp = 0;
746
747 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
748 zTableInfo = appendText(zTableInfo, zTable, '"');
749 zTableInfo = appendText(zTableInfo, ");", 0);
750
751 rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
752 if( zTableInfo ) free(zTableInfo);
753 if( rc!=SQLITE_OK || !pTableInfo ){
754 return 1;
755 }
756
757 zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
758 zTmp = appendText(zTmp, zTable, '"');
759 if( zTmp ){
760 zSelect = appendText(zSelect, zTmp, '\'');
761 }
762 zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
763 rc = sqlite3_step(pTableInfo);
764 while( rc==SQLITE_ROW ){
danielk19772e588c72005-12-09 14:25:08 +0000765 const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
danielk19773f41e972004-06-08 00:39:01 +0000766 zSelect = appendText(zSelect, "quote(", 0);
danielk19772e588c72005-12-09 14:25:08 +0000767 zSelect = appendText(zSelect, zText, '"');
danielk19772a02e332004-06-05 08:04:36 +0000768 rc = sqlite3_step(pTableInfo);
769 if( rc==SQLITE_ROW ){
drh45e29d82006-11-20 16:21:10 +0000770 zSelect = appendText(zSelect, ") || ',' || ", 0);
danielk19772a02e332004-06-05 08:04:36 +0000771 }else{
772 zSelect = appendText(zSelect, ") ", 0);
773 }
774 }
775 rc = sqlite3_finalize(pTableInfo);
776 if( rc!=SQLITE_OK ){
777 if( zSelect ) free(zSelect);
778 return 1;
779 }
780 zSelect = appendText(zSelect, "|| ')' FROM ", 0);
781 zSelect = appendText(zSelect, zTable, '"');
782
drhdd3d4592004-08-30 01:54:05 +0000783 rc = run_table_dump_query(p->out, p->db, zSelect);
784 if( rc==SQLITE_CORRUPT ){
785 zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
786 rc = run_table_dump_query(p->out, p->db, zSelect);
787 }
danielk19772a02e332004-06-05 08:04:36 +0000788 if( zSelect ) free(zSelect);
drh4c653a02000-06-07 01:27:47 +0000789 }
drh4c653a02000-06-07 01:27:47 +0000790 return 0;
791}
792
793/*
drh45e29d82006-11-20 16:21:10 +0000794** Run zQuery. Use dump_callback() as the callback routine so that
795** the contents of the query are output as SQL statements.
796**
drhdd3d4592004-08-30 01:54:05 +0000797** If we get a SQLITE_CORRUPT error, rerun the query after appending
798** "ORDER BY rowid DESC" to the end.
799*/
800static int run_schema_dump_query(
801 struct callback_data *p,
802 const char *zQuery,
803 char **pzErrMsg
804){
805 int rc;
806 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
807 if( rc==SQLITE_CORRUPT ){
808 char *zQ2;
809 int len = strlen(zQuery);
810 if( pzErrMsg ) sqlite3_free(*pzErrMsg);
811 zQ2 = malloc( len+100 );
812 if( zQ2==0 ) return rc;
813 sprintf(zQ2, "%s ORDER BY rowid DESC", zQuery);
814 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
815 free(zQ2);
816 }
817 return rc;
818}
819
820/*
drh75897232000-05-29 14:26:00 +0000821** Text of a help message
822*/
persicom1d0b8722002-04-18 02:53:04 +0000823static char zHelp[] =
jplyon6a65bb32003-05-04 07:25:57 +0000824 ".databases List names and files of attached databases\n"
drhb860bc92004-08-04 15:16:55 +0000825 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
drhdaffd0e2001-04-11 14:28:42 +0000826 ".echo ON|OFF Turn command echo on or off\n"
drh75897232000-05-29 14:26:00 +0000827 ".exit Exit this program\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000828 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000829 ".header(s) ON|OFF Turn display of headers on or off\n"
drh75897232000-05-29 14:26:00 +0000830 ".help Show this message\n"
drhb860bc92004-08-04 15:16:55 +0000831 ".import FILE TABLE Import data from FILE into TABLE\n"
drh75897232000-05-29 14:26:00 +0000832 ".indices TABLE Show names of all indices on TABLE\n"
drh70df4fe2006-06-13 15:12:21 +0000833#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +0000834 ".load FILE ?ENTRY? Load an extension library\n"
drh70df4fe2006-06-13 15:12:21 +0000835#endif
danielk19776b77a362005-01-13 11:10:25 +0000836 ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
drh3b584fa2004-09-24 12:50:03 +0000837 " csv Comma-separated values\n"
drhb860bc92004-08-04 15:16:55 +0000838 " column Left-aligned columns. (See .width)\n"
839 " html HTML <table> code\n"
840 " insert SQL insert statements for TABLE\n"
841 " line One value per line\n"
842 " list Values delimited by .separator string\n"
843 " tabs Tab-separated values\n"
844 " tcl TCL list elements\n"
845 ".nullvalue STRING Print STRING in place of NULL values\n"
drh75897232000-05-29 14:26:00 +0000846 ".output FILENAME Send output to FILENAME\n"
847 ".output stdout Send output to the screen\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000848 ".prompt MAIN CONTINUE Replace the standard prompts\n"
persicom7e2dfdd2002-04-18 02:46:52 +0000849 ".quit Exit this program\n"
drhdaffd0e2001-04-11 14:28:42 +0000850 ".read FILENAME Execute SQL in FILENAME\n"
drh75897232000-05-29 14:26:00 +0000851 ".schema ?TABLE? Show the CREATE statements\n"
drhb860bc92004-08-04 15:16:55 +0000852 ".separator STRING Change separator used by output mode and .import\n"
drhdd45df82002-04-18 12:39:03 +0000853 ".show Show the current values for various settings\n"
drhfeac5f82004-08-01 00:10:45 +0000854 ".tables ?PATTERN? List names of tables matching a LIKE pattern\n"
drh2dfbbca2000-07-28 14:32:48 +0000855 ".timeout MS Try opening locked tables for MS milliseconds\n"
drh75897232000-05-29 14:26:00 +0000856 ".width NUM NUM ... Set column widths for \"column\" mode\n"
857;
858
drhdaffd0e2001-04-11 14:28:42 +0000859/* Forward reference */
drhc28490c2006-10-26 14:25:58 +0000860static int process_input(struct callback_data *p, FILE *in);
drhdaffd0e2001-04-11 14:28:42 +0000861
drh75897232000-05-29 14:26:00 +0000862/*
drh44c2eb12003-04-30 11:38:26 +0000863** Make sure the database is open. If it is not, then open it. If
864** the database fails to open, print an error message and exit.
865*/
866static void open_db(struct callback_data *p){
867 if( p->db==0 ){
danielk19774f057f92004-06-08 00:02:33 +0000868 sqlite3_open(p->zDbFilename, &p->db);
danielk197780290862004-05-22 09:21:21 +0000869 db = p->db;
danielk1977bc6ada42004-06-30 08:20:16 +0000870 sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
871 shellstaticFunc, 0, 0);
danielk197780290862004-05-22 09:21:21 +0000872 if( SQLITE_OK!=sqlite3_errcode(db) ){
873 fprintf(stderr,"Unable to open database \"%s\": %s\n",
874 p->zDbFilename, sqlite3_errmsg(db));
drh22fbcb82004-02-01 01:22:50 +0000875 exit(1);
drh44c2eb12003-04-30 11:38:26 +0000876 }
drhc2e87a32006-06-27 15:16:14 +0000877#ifndef SQLITE_OMIT_LOAD_EXTENSION
878 sqlite3_enable_load_extension(p->db, 1);
879#endif
drh44c2eb12003-04-30 11:38:26 +0000880 }
881}
882
883/*
drhfeac5f82004-08-01 00:10:45 +0000884** Do C-language style dequoting.
885**
886** \t -> tab
887** \n -> newline
888** \r -> carriage return
889** \NNN -> ascii character NNN in octal
890** \\ -> backslash
891*/
892static void resolve_backslashes(char *z){
893 int i, j, c;
894 for(i=j=0; (c = z[i])!=0; i++, j++){
895 if( c=='\\' ){
896 c = z[++i];
897 if( c=='n' ){
898 c = '\n';
899 }else if( c=='t' ){
900 c = '\t';
901 }else if( c=='r' ){
902 c = '\r';
903 }else if( c>='0' && c<='7' ){
drhaa816082005-12-29 12:53:09 +0000904 c -= '0';
drhfeac5f82004-08-01 00:10:45 +0000905 if( z[i+1]>='0' && z[i+1]<='7' ){
906 i++;
907 c = (c<<3) + z[i] - '0';
908 if( z[i+1]>='0' && z[i+1]<='7' ){
909 i++;
910 c = (c<<3) + z[i] - '0';
911 }
912 }
913 }
914 }
915 z[j] = c;
916 }
917 z[j] = 0;
918}
919
920/*
drhc28490c2006-10-26 14:25:58 +0000921** Interpret zArg as a boolean value. Return either 0 or 1.
922*/
923static int booleanValue(char *zArg){
924 int val = atoi(zArg);
925 int j;
926 for(j=0; zArg[j]; j++){
927 zArg[j] = tolower(zArg[j]);
928 }
929 if( strcmp(zArg,"on")==0 ){
930 val = 1;
931 }else if( strcmp(zArg,"yes")==0 ){
932 val = 1;
933 }
934 return val;
935}
936
937/*
drh75897232000-05-29 14:26:00 +0000938** If an input line begins with "." then invoke this routine to
939** process that line.
drh67505e72002-04-19 12:34:06 +0000940**
drh47ad6842006-11-08 12:25:42 +0000941** Return 1 on error, 2 to exit, and 0 otherwise.
drh75897232000-05-29 14:26:00 +0000942*/
drh44c2eb12003-04-30 11:38:26 +0000943static int do_meta_command(char *zLine, struct callback_data *p){
drh75897232000-05-29 14:26:00 +0000944 int i = 1;
945 int nArg = 0;
946 int n, c;
drh67505e72002-04-19 12:34:06 +0000947 int rc = 0;
drh75897232000-05-29 14:26:00 +0000948 char *azArg[50];
949
950 /* Parse the input line into tokens.
951 */
952 while( zLine[i] && nArg<ArraySize(azArg) ){
drh4c755c02004-08-08 20:22:17 +0000953 while( isspace((unsigned char)zLine[i]) ){ i++; }
drh06333682004-03-09 13:37:45 +0000954 if( zLine[i]==0 ) break;
drh75897232000-05-29 14:26:00 +0000955 if( zLine[i]=='\'' || zLine[i]=='"' ){
956 int delim = zLine[i++];
957 azArg[nArg++] = &zLine[i];
958 while( zLine[i] && zLine[i]!=delim ){ i++; }
959 if( zLine[i]==delim ){
960 zLine[i++] = 0;
961 }
drhfeac5f82004-08-01 00:10:45 +0000962 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +0000963 }else{
964 azArg[nArg++] = &zLine[i];
drh4c755c02004-08-08 20:22:17 +0000965 while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; }
drh75897232000-05-29 14:26:00 +0000966 if( zLine[i] ) zLine[i++] = 0;
drhfeac5f82004-08-01 00:10:45 +0000967 resolve_backslashes(azArg[nArg-1]);
drh75897232000-05-29 14:26:00 +0000968 }
969 }
970
971 /* Process the input line.
972 */
drh67505e72002-04-19 12:34:06 +0000973 if( nArg==0 ) return rc;
drh75897232000-05-29 14:26:00 +0000974 n = strlen(azArg[0]);
975 c = azArg[0][0];
drhc49f44e2006-10-26 18:15:42 +0000976 if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
977 bail_on_error = booleanValue(azArg[1]);
978 }else
979
jplyon6a65bb32003-05-04 07:25:57 +0000980 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
jplyon672a1ed2003-05-11 20:07:05 +0000981 struct callback_data data;
982 char *zErrMsg = 0;
jplyon6a65bb32003-05-04 07:25:57 +0000983 open_db(p);
jplyon672a1ed2003-05-11 20:07:05 +0000984 memcpy(&data, p, sizeof(data));
drhd8885442004-03-17 23:42:12 +0000985 data.showHeader = 1;
jplyon672a1ed2003-05-11 20:07:05 +0000986 data.mode = MODE_Column;
drhd8885442004-03-17 23:42:12 +0000987 data.colWidth[0] = 3;
988 data.colWidth[1] = 15;
989 data.colWidth[2] = 58;
drh0b2110c2004-10-26 00:08:10 +0000990 data.cnt = 0;
danielk19776f8a5032004-05-10 10:34:51 +0000991 sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
jplyon672a1ed2003-05-11 20:07:05 +0000992 if( zErrMsg ){
993 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +0000994 sqlite3_free(zErrMsg);
jplyon6a65bb32003-05-04 07:25:57 +0000995 }
996 }else
997
drh4c653a02000-06-07 01:27:47 +0000998 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
999 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001000 open_db(p);
drh33048c02001-10-01 14:29:22 +00001001 fprintf(p->out, "BEGIN TRANSACTION;\n");
drh45e29d82006-11-20 16:21:10 +00001002 p->writableSchema = 0;
drh4c653a02000-06-07 01:27:47 +00001003 if( nArg==1 ){
drhdd3d4592004-08-30 01:54:05 +00001004 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +00001005 "SELECT name, type, sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001006 "WHERE sql NOT NULL AND type=='table'", 0
drh0b9a5942006-09-13 20:22:02 +00001007 );
1008 run_table_dump_query(p->out, p->db,
1009 "SELECT sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001010 "WHERE sql NOT NULL AND type IN ('index','trigger','view')"
drha18c5682000-10-08 22:20:57 +00001011 );
drh4c653a02000-06-07 01:27:47 +00001012 }else{
1013 int i;
drhdd3d4592004-08-30 01:54:05 +00001014 for(i=1; i<nArg; i++){
danielk1977bc6ada42004-06-30 08:20:16 +00001015 zShellStatic = azArg[i];
drhdd3d4592004-08-30 01:54:05 +00001016 run_schema_dump_query(p,
drha18c5682000-10-08 22:20:57 +00001017 "SELECT name, type, sql FROM sqlite_master "
drhdd3d4592004-08-30 01:54:05 +00001018 "WHERE tbl_name LIKE shellstatic() AND type=='table'"
drh45e29d82006-11-20 16:21:10 +00001019 " AND sql NOT NULL", 0);
drh0b9a5942006-09-13 20:22:02 +00001020 run_table_dump_query(p->out, p->db,
1021 "SELECT sql FROM sqlite_master "
drh45e29d82006-11-20 16:21:10 +00001022 "WHERE sql NOT NULL"
1023 " AND type IN ('index','trigger','view')"
drh0b9a5942006-09-13 20:22:02 +00001024 " AND tbl_name LIKE shellstatic()"
1025 );
danielk1977bc6ada42004-06-30 08:20:16 +00001026 zShellStatic = 0;
drh4c653a02000-06-07 01:27:47 +00001027 }
1028 }
drh45e29d82006-11-20 16:21:10 +00001029 if( p->writableSchema ){
1030 fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
1031 p->writableSchema = 0;
1032 }
drh4c653a02000-06-07 01:27:47 +00001033 if( zErrMsg ){
1034 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001035 sqlite3_free(zErrMsg);
drh33048c02001-10-01 14:29:22 +00001036 }else{
1037 fprintf(p->out, "COMMIT;\n");
drh4c653a02000-06-07 01:27:47 +00001038 }
1039 }else
drh75897232000-05-29 14:26:00 +00001040
drhdaffd0e2001-04-11 14:28:42 +00001041 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001042 p->echoOn = booleanValue(azArg[1]);
drhdaffd0e2001-04-11 14:28:42 +00001043 }else
1044
drh75897232000-05-29 14:26:00 +00001045 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
drh47ad6842006-11-08 12:25:42 +00001046 rc = 2;
drh75897232000-05-29 14:26:00 +00001047 }else
1048
drhdd45df82002-04-18 12:39:03 +00001049 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
drhc28490c2006-10-26 14:25:58 +00001050 int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
persicom7e2dfdd2002-04-18 02:46:52 +00001051 if(val == 1) {
1052 if(!p->explainPrev.valid) {
1053 p->explainPrev.valid = 1;
1054 p->explainPrev.mode = p->mode;
1055 p->explainPrev.showHeader = p->showHeader;
1056 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
1057 }
1058 /* We could put this code under the !p->explainValid
1059 ** condition so that it does not execute if we are already in
1060 ** explain mode. However, always executing it allows us an easy
1061 ** was to reset to explain mode in case the user previously
1062 ** did an .explain followed by a .width, .mode or .header
1063 ** command.
1064 */
1065 p->mode = MODE_Column;
1066 p->showHeader = 1;
1067 memset(p->colWidth,0,ArraySize(p->colWidth));
1068 p->colWidth[0] = 4;
drhe69cc5b2005-08-27 01:50:53 +00001069 p->colWidth[1] = 14;
persicom7e2dfdd2002-04-18 02:46:52 +00001070 p->colWidth[2] = 10;
1071 p->colWidth[3] = 10;
drhe69cc5b2005-08-27 01:50:53 +00001072 p->colWidth[4] = 33;
persicom7e2dfdd2002-04-18 02:46:52 +00001073 }else if (p->explainPrev.valid) {
1074 p->explainPrev.valid = 0;
1075 p->mode = p->explainPrev.mode;
1076 p->showHeader = p->explainPrev.showHeader;
1077 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
1078 }
drh75897232000-05-29 14:26:00 +00001079 }else
1080
drhc28490c2006-10-26 14:25:58 +00001081 if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
persicom7e2dfdd2002-04-18 02:46:52 +00001082 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
drhc28490c2006-10-26 14:25:58 +00001083 p->showHeader = booleanValue(azArg[1]);
drh75897232000-05-29 14:26:00 +00001084 }else
1085
1086 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
1087 fprintf(stderr,zHelp);
1088 }else
1089
drhfeac5f82004-08-01 00:10:45 +00001090 if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
1091 char *zTable = azArg[2]; /* Insert data into this table */
1092 char *zFile = azArg[1]; /* The file from which to extract data */
1093 sqlite3_stmt *pStmt; /* A statement */
1094 int rc; /* Result code */
1095 int nCol; /* Number of columns in the table */
1096 int nByte; /* Number of bytes in an SQL string */
1097 int i, j; /* Loop counters */
1098 int nSep; /* Number of bytes in p->separator[] */
1099 char *zSql; /* An SQL statement */
1100 char *zLine; /* A single line of input from the file */
1101 char **azCol; /* zLine[] broken up into columns */
1102 char *zCommit; /* How to commit changes */
drhb860bc92004-08-04 15:16:55 +00001103 FILE *in; /* The input file */
1104 int lineno = 0; /* Line number of input file */
drhfeac5f82004-08-01 00:10:45 +00001105
drha543c822006-06-08 16:10:14 +00001106 open_db(p);
drhfeac5f82004-08-01 00:10:45 +00001107 nSep = strlen(p->separator);
1108 if( nSep==0 ){
1109 fprintf(stderr, "non-null separator required for import\n");
1110 return 0;
1111 }
1112 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
1113 if( zSql==0 ) return 0;
1114 nByte = strlen(zSql);
drh5e6078b2006-01-31 19:07:22 +00001115 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001116 sqlite3_free(zSql);
1117 if( rc ){
1118 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1119 nCol = 0;
drh47ad6842006-11-08 12:25:42 +00001120 rc = 1;
drhfeac5f82004-08-01 00:10:45 +00001121 }else{
1122 nCol = sqlite3_column_count(pStmt);
1123 }
1124 sqlite3_finalize(pStmt);
1125 if( nCol==0 ) return 0;
1126 zSql = malloc( nByte + 20 + nCol*2 );
1127 if( zSql==0 ) return 0;
1128 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
1129 j = strlen(zSql);
1130 for(i=1; i<nCol; i++){
1131 zSql[j++] = ',';
1132 zSql[j++] = '?';
1133 }
1134 zSql[j++] = ')';
1135 zSql[j] = 0;
drh5e6078b2006-01-31 19:07:22 +00001136 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
drhfeac5f82004-08-01 00:10:45 +00001137 free(zSql);
1138 if( rc ){
1139 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
1140 sqlite3_finalize(pStmt);
drh47ad6842006-11-08 12:25:42 +00001141 return 1;
drhfeac5f82004-08-01 00:10:45 +00001142 }
1143 in = fopen(zFile, "rb");
1144 if( in==0 ){
1145 fprintf(stderr, "cannot open file: %s\n", zFile);
1146 sqlite3_finalize(pStmt);
1147 return 0;
1148 }
1149 azCol = malloc( sizeof(azCol[0])*(nCol+1) );
drh43617e92006-03-06 20:55:46 +00001150 if( azCol==0 ){
1151 fclose(in);
1152 return 0;
1153 }
drhfeac5f82004-08-01 00:10:45 +00001154 sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
1155 zCommit = "COMMIT";
1156 while( (zLine = local_getline(0, in))!=0 ){
1157 char *z;
1158 i = 0;
drhb860bc92004-08-04 15:16:55 +00001159 lineno++;
drhfeac5f82004-08-01 00:10:45 +00001160 azCol[0] = zLine;
drh36d4e972004-10-06 14:39:06 +00001161 for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){
drhfeac5f82004-08-01 00:10:45 +00001162 if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){
1163 *z = 0;
1164 i++;
drhb860bc92004-08-04 15:16:55 +00001165 if( i<nCol ){
1166 azCol[i] = &z[nSep];
1167 z += nSep-1;
1168 }
drhfeac5f82004-08-01 00:10:45 +00001169 }
1170 }
drh1cd7f832005-08-05 18:50:51 +00001171 *z = 0;
drhb860bc92004-08-04 15:16:55 +00001172 if( i+1!=nCol ){
1173 fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
1174 zFile, lineno, nCol, i+1);
1175 zCommit = "ROLLBACK";
1176 break;
1177 }
drhfeac5f82004-08-01 00:10:45 +00001178 for(i=0; i<nCol; i++){
1179 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
1180 }
1181 sqlite3_step(pStmt);
1182 rc = sqlite3_reset(pStmt);
1183 free(zLine);
1184 if( rc!=SQLITE_OK ){
1185 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
1186 zCommit = "ROLLBACK";
drh47ad6842006-11-08 12:25:42 +00001187 rc = 1;
drhfeac5f82004-08-01 00:10:45 +00001188 break;
1189 }
1190 }
1191 free(azCol);
1192 fclose(in);
1193 sqlite3_finalize(pStmt);
drhb860bc92004-08-04 15:16:55 +00001194 sqlite3_exec(p->db, zCommit, 0, 0, 0);
drhfeac5f82004-08-01 00:10:45 +00001195 }else
1196
drh75897232000-05-29 14:26:00 +00001197 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
1198 struct callback_data data;
1199 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001200 open_db(p);
drh75897232000-05-29 14:26:00 +00001201 memcpy(&data, p, sizeof(data));
1202 data.showHeader = 0;
1203 data.mode = MODE_List;
danielk1977bc6ada42004-06-30 08:20:16 +00001204 zShellStatic = azArg[1];
1205 sqlite3_exec(p->db,
drha18c5682000-10-08 22:20:57 +00001206 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001207 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001208 "UNION ALL "
1209 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001210 "WHERE type='index' AND tbl_name LIKE shellstatic() "
drhe0bc4042002-06-25 01:09:11 +00001211 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001212 callback, &data, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001213 );
danielk1977bc6ada42004-06-30 08:20:16 +00001214 zShellStatic = 0;
drh75897232000-05-29 14:26:00 +00001215 if( zErrMsg ){
1216 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001217 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001218 }
1219 }else
1220
drh70df4fe2006-06-13 15:12:21 +00001221#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh1e397f82006-06-08 15:28:43 +00001222 if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
1223 const char *zFile, *zProc;
1224 char *zErrMsg = 0;
1225 int rc;
1226 zFile = azArg[1];
1227 zProc = nArg>=3 ? azArg[2] : 0;
1228 open_db(p);
1229 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
1230 if( rc!=SQLITE_OK ){
1231 fprintf(stderr, "%s\n", zErrMsg);
1232 sqlite3_free(zErrMsg);
drh47ad6842006-11-08 12:25:42 +00001233 rc = 1;
drh1e397f82006-06-08 15:28:43 +00001234 }
1235 }else
drh70df4fe2006-06-13 15:12:21 +00001236#endif
drh1e397f82006-06-08 15:28:43 +00001237
drh28bd4bc2000-06-15 15:57:22 +00001238 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
drh75897232000-05-29 14:26:00 +00001239 int n2 = strlen(azArg[1]);
persicom7e2dfdd2002-04-18 02:46:52 +00001240 if( strncmp(azArg[1],"line",n2)==0
1241 ||
1242 strncmp(azArg[1],"lines",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001243 p->mode = MODE_Line;
persicom7e2dfdd2002-04-18 02:46:52 +00001244 }else if( strncmp(azArg[1],"column",n2)==0
1245 ||
1246 strncmp(azArg[1],"columns",n2)==0 ){
drh75897232000-05-29 14:26:00 +00001247 p->mode = MODE_Column;
1248 }else if( strncmp(azArg[1],"list",n2)==0 ){
1249 p->mode = MODE_List;
drh1e5d0e92000-05-31 23:33:17 +00001250 }else if( strncmp(azArg[1],"html",n2)==0 ){
1251 p->mode = MODE_Html;
drhfeac5f82004-08-01 00:10:45 +00001252 }else if( strncmp(azArg[1],"tcl",n2)==0 ){
1253 p->mode = MODE_Tcl;
1254 }else if( strncmp(azArg[1],"csv",n2)==0 ){
drh8e64d1c2004-10-07 00:32:39 +00001255 p->mode = MODE_Csv;
drhfeac5f82004-08-01 00:10:45 +00001256 strcpy(p->separator, ",");
1257 }else if( strncmp(azArg[1],"tabs",n2)==0 ){
1258 p->mode = MODE_List;
1259 strcpy(p->separator, "\t");
drh28bd4bc2000-06-15 15:57:22 +00001260 }else if( strncmp(azArg[1],"insert",n2)==0 ){
1261 p->mode = MODE_Insert;
1262 if( nArg>=3 ){
drh33048c02001-10-01 14:29:22 +00001263 set_table_name(p, azArg[2]);
drh28bd4bc2000-06-15 15:57:22 +00001264 }else{
drh33048c02001-10-01 14:29:22 +00001265 set_table_name(p, "table");
drh28bd4bc2000-06-15 15:57:22 +00001266 }
drhdaffd0e2001-04-11 14:28:42 +00001267 }else {
drhfeac5f82004-08-01 00:10:45 +00001268 fprintf(stderr,"mode should be on of: "
1269 "column csv html insert line list tabs tcl\n");
drh75897232000-05-29 14:26:00 +00001270 }
1271 }else
1272
persicom7e2dfdd2002-04-18 02:46:52 +00001273 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
1274 sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
1275 }else
1276
drh75897232000-05-29 14:26:00 +00001277 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
1278 if( p->out!=stdout ){
1279 fclose(p->out);
1280 }
1281 if( strcmp(azArg[1],"stdout")==0 ){
1282 p->out = stdout;
persicom7e2dfdd2002-04-18 02:46:52 +00001283 strcpy(p->outfile,"stdout");
drh75897232000-05-29 14:26:00 +00001284 }else{
drha1f9b5e2004-02-14 16:31:02 +00001285 p->out = fopen(azArg[1], "wb");
drh75897232000-05-29 14:26:00 +00001286 if( p->out==0 ){
1287 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
1288 p->out = stdout;
persicom7e2dfdd2002-04-18 02:46:52 +00001289 } else {
1290 strcpy(p->outfile,azArg[1]);
drh75897232000-05-29 14:26:00 +00001291 }
1292 }
1293 }else
1294
drhdd45df82002-04-18 12:39:03 +00001295 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
persicom7e2dfdd2002-04-18 02:46:52 +00001296 if( nArg >= 2) {
1297 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
1298 }
1299 if( nArg >= 3) {
1300 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
1301 }
1302 }else
1303
1304 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
drh47ad6842006-11-08 12:25:42 +00001305 rc = 2;
persicom7e2dfdd2002-04-18 02:46:52 +00001306 }else
1307
drhdaffd0e2001-04-11 14:28:42 +00001308 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
drha1f9b5e2004-02-14 16:31:02 +00001309 FILE *alt = fopen(azArg[1], "rb");
drhdaffd0e2001-04-11 14:28:42 +00001310 if( alt==0 ){
1311 fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
1312 }else{
1313 process_input(p, alt);
1314 fclose(alt);
1315 }
1316 }else
1317
drh75897232000-05-29 14:26:00 +00001318 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
1319 struct callback_data data;
1320 char *zErrMsg = 0;
drh44c2eb12003-04-30 11:38:26 +00001321 open_db(p);
drh75897232000-05-29 14:26:00 +00001322 memcpy(&data, p, sizeof(data));
1323 data.showHeader = 0;
drhe3710332000-09-29 13:30:53 +00001324 data.mode = MODE_Semi;
drh75897232000-05-29 14:26:00 +00001325 if( nArg>1 ){
drhc8d74412004-08-31 23:41:26 +00001326 int i;
1327 for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]);
1328 if( strcmp(azArg[1],"sqlite_master")==0 ){
drha18c5682000-10-08 22:20:57 +00001329 char *new_argv[2], *new_colv[2];
1330 new_argv[0] = "CREATE TABLE sqlite_master (\n"
1331 " type text,\n"
1332 " name text,\n"
1333 " tbl_name text,\n"
drhadbca9c2001-09-27 15:11:53 +00001334 " rootpage integer,\n"
drha18c5682000-10-08 22:20:57 +00001335 " sql text\n"
1336 ")";
1337 new_argv[1] = 0;
1338 new_colv[0] = "sql";
1339 new_colv[1] = 0;
1340 callback(&data, 1, new_argv, new_colv);
drhc8d74412004-08-31 23:41:26 +00001341 }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){
drhe0bc4042002-06-25 01:09:11 +00001342 char *new_argv[2], *new_colv[2];
1343 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
1344 " type text,\n"
1345 " name text,\n"
1346 " tbl_name text,\n"
1347 " rootpage integer,\n"
1348 " sql text\n"
1349 ")";
1350 new_argv[1] = 0;
1351 new_colv[0] = "sql";
1352 new_colv[1] = 0;
1353 callback(&data, 1, new_argv, new_colv);
drha18c5682000-10-08 22:20:57 +00001354 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001355 zShellStatic = azArg[1];
1356 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001357 "SELECT sql FROM "
1358 " (SELECT * FROM sqlite_master UNION ALL"
1359 " SELECT * FROM sqlite_temp_master) "
danielk1977bc6ada42004-06-30 08:20:16 +00001360 "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL "
drhe0bc4042002-06-25 01:09:11 +00001361 "ORDER BY substr(type,2,1), name",
danielk1977bc6ada42004-06-30 08:20:16 +00001362 callback, &data, &zErrMsg);
1363 zShellStatic = 0;
drha18c5682000-10-08 22:20:57 +00001364 }
drh75897232000-05-29 14:26:00 +00001365 }else{
danielk19776f8a5032004-05-10 10:34:51 +00001366 sqlite3_exec(p->db,
drhe0bc4042002-06-25 01:09:11 +00001367 "SELECT sql FROM "
1368 " (SELECT * FROM sqlite_master UNION ALL"
1369 " SELECT * FROM sqlite_temp_master) "
drh0c356672005-09-10 22:40:53 +00001370 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001371 "ORDER BY substr(type,2,1), name",
drha18c5682000-10-08 22:20:57 +00001372 callback, &data, &zErrMsg
1373 );
drh75897232000-05-29 14:26:00 +00001374 }
drh75897232000-05-29 14:26:00 +00001375 if( zErrMsg ){
1376 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001377 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001378 }
1379 }else
1380
1381 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
1382 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
1383 }else
1384
persicom7e2dfdd2002-04-18 02:46:52 +00001385 if( c=='s' && strncmp(azArg[0], "show", n)==0){
1386 int i;
1387 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
drh67505e72002-04-19 12:34:06 +00001388 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
drhdd45df82002-04-18 12:39:03 +00001389 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
persicom7e2dfdd2002-04-18 02:46:52 +00001390 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
drhfeac5f82004-08-01 00:10:45 +00001391 fprintf(p->out,"%9.9s: ", "nullvalue");
1392 output_c_string(p->out, p->nullvalue);
1393 fprintf(p->out, "\n");
drh67505e72002-04-19 12:34:06 +00001394 fprintf(p->out,"%9.9s: %s\n","output",
1395 strlen(p->outfile) ? p->outfile : "stdout");
drhfeac5f82004-08-01 00:10:45 +00001396 fprintf(p->out,"%9.9s: ", "separator");
1397 output_c_string(p->out, p->separator);
1398 fprintf(p->out, "\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001399 fprintf(p->out,"%9.9s: ","width");
1400 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
drhfeac5f82004-08-01 00:10:45 +00001401 fprintf(p->out,"%d ",p->colWidth[i]);
persicom7e2dfdd2002-04-18 02:46:52 +00001402 }
drhfeac5f82004-08-01 00:10:45 +00001403 fprintf(p->out,"\n");
persicom7e2dfdd2002-04-18 02:46:52 +00001404 }else
1405
drh2dfbbca2000-07-28 14:32:48 +00001406 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
drhe3710332000-09-29 13:30:53 +00001407 char **azResult;
1408 int nRow, rc;
1409 char *zErrMsg;
drh44c2eb12003-04-30 11:38:26 +00001410 open_db(p);
drha50da102000-08-08 20:19:09 +00001411 if( nArg==1 ){
danielk19776f8a5032004-05-10 10:34:51 +00001412 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001413 "SELECT name FROM sqlite_master "
drh0c356672005-09-10 22:40:53 +00001414 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'"
drhe0bc4042002-06-25 01:09:11 +00001415 "UNION ALL "
1416 "SELECT name FROM sqlite_temp_master "
1417 "WHERE type IN ('table','view') "
1418 "ORDER BY 1",
drha18c5682000-10-08 22:20:57 +00001419 &azResult, &nRow, 0, &zErrMsg
1420 );
drha50da102000-08-08 20:19:09 +00001421 }else{
danielk1977bc6ada42004-06-30 08:20:16 +00001422 zShellStatic = azArg[1];
1423 rc = sqlite3_get_table(p->db,
drha50da102000-08-08 20:19:09 +00001424 "SELECT name FROM sqlite_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001425 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001426 "UNION ALL "
1427 "SELECT name FROM sqlite_temp_master "
danielk1977bc6ada42004-06-30 08:20:16 +00001428 "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' "
drhe0bc4042002-06-25 01:09:11 +00001429 "ORDER BY 1",
danielk1977bc6ada42004-06-30 08:20:16 +00001430 &azResult, &nRow, 0, &zErrMsg
drha18c5682000-10-08 22:20:57 +00001431 );
danielk1977bc6ada42004-06-30 08:20:16 +00001432 zShellStatic = 0;
drha50da102000-08-08 20:19:09 +00001433 }
drh75897232000-05-29 14:26:00 +00001434 if( zErrMsg ){
1435 fprintf(stderr,"Error: %s\n", zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001436 sqlite3_free(zErrMsg);
drh75897232000-05-29 14:26:00 +00001437 }
drhe3710332000-09-29 13:30:53 +00001438 if( rc==SQLITE_OK ){
1439 int len, maxlen = 0;
1440 int i, j;
1441 int nPrintCol, nPrintRow;
1442 for(i=1; i<=nRow; i++){
1443 if( azResult[i]==0 ) continue;
1444 len = strlen(azResult[i]);
1445 if( len>maxlen ) maxlen = len;
1446 }
1447 nPrintCol = 80/(maxlen+2);
1448 if( nPrintCol<1 ) nPrintCol = 1;
1449 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
1450 for(i=0; i<nPrintRow; i++){
1451 for(j=i+1; j<=nRow; j+=nPrintRow){
1452 char *zSp = j<=nPrintRow ? "" : " ";
1453 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
1454 }
1455 printf("\n");
1456 }
drh47ad6842006-11-08 12:25:42 +00001457 }else{
1458 rc = 1;
drhe3710332000-09-29 13:30:53 +00001459 }
danielk19776f8a5032004-05-10 10:34:51 +00001460 sqlite3_free_table(azResult);
drh75897232000-05-29 14:26:00 +00001461 }else
1462
drh2dfbbca2000-07-28 14:32:48 +00001463 if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
drh44c2eb12003-04-30 11:38:26 +00001464 open_db(p);
danielk19776f8a5032004-05-10 10:34:51 +00001465 sqlite3_busy_timeout(p->db, atoi(azArg[1]));
drh2dfbbca2000-07-28 14:32:48 +00001466 }else
1467
drh75897232000-05-29 14:26:00 +00001468 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
1469 int j;
drh43617e92006-03-06 20:55:46 +00001470 assert( nArg<=ArraySize(azArg) );
drh75897232000-05-29 14:26:00 +00001471 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
1472 p->colWidth[j-1] = atoi(azArg[j]);
1473 }
1474 }else
1475
1476 {
drh67505e72002-04-19 12:34:06 +00001477 fprintf(stderr, "unknown command or invalid arguments: "
1478 " \"%s\". Enter \".help\" for help\n", azArg[0]);
drh75897232000-05-29 14:26:00 +00001479 }
drh67505e72002-04-19 12:34:06 +00001480
1481 return rc;
drh75897232000-05-29 14:26:00 +00001482}
1483
drh67505e72002-04-19 12:34:06 +00001484/*
drh324ccef2003-02-05 14:06:20 +00001485** Return TRUE if the last non-whitespace character in z[] is a semicolon.
1486** z[] is N characters long.
1487*/
1488static int _ends_with_semicolon(const char *z, int N){
drh4c755c02004-08-08 20:22:17 +00001489 while( N>0 && isspace((unsigned char)z[N-1]) ){ N--; }
drh324ccef2003-02-05 14:06:20 +00001490 return N>0 && z[N-1]==';';
1491}
1492
1493/*
drh70c7a4b2003-04-26 03:03:06 +00001494** Test to see if a line consists entirely of whitespace.
1495*/
1496static int _all_whitespace(const char *z){
1497 for(; *z; z++){
drh4c755c02004-08-08 20:22:17 +00001498 if( isspace(*(unsigned char*)z) ) continue;
drh70c7a4b2003-04-26 03:03:06 +00001499 if( *z=='/' && z[1]=='*' ){
1500 z += 2;
1501 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
1502 if( *z==0 ) return 0;
1503 z++;
1504 continue;
1505 }
1506 if( *z=='-' && z[1]=='-' ){
1507 z += 2;
1508 while( *z && *z!='\n' ){ z++; }
1509 if( *z==0 ) return 1;
1510 continue;
1511 }
1512 return 0;
1513 }
1514 return 1;
1515}
1516
1517/*
drha9b17162003-04-29 18:01:28 +00001518** Return TRUE if the line typed in is an SQL command terminator other
1519** than a semi-colon. The SQL Server style "go" command is understood
1520** as is the Oracle "/".
1521*/
1522static int _is_command_terminator(const char *zLine){
drh4c755c02004-08-08 20:22:17 +00001523 while( isspace(*(unsigned char*)zLine) ){ zLine++; };
drha9b17162003-04-29 18:01:28 +00001524 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */
drhc8d74412004-08-31 23:41:26 +00001525 if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o'
1526 && _all_whitespace(&zLine[2]) ){
drha9b17162003-04-29 18:01:28 +00001527 return 1; /* SQL Server */
1528 }
1529 return 0;
1530}
1531
1532/*
drh67505e72002-04-19 12:34:06 +00001533** Read input from *in and process it. If *in==0 then input
1534** is interactive - the user is typing it it. Otherwise, input
1535** is coming from a file or device. A prompt is issued and history
1536** is saved only if input is interactive. An interrupt signal will
1537** cause this routine to exit immediately, unless input is interactive.
drhc28490c2006-10-26 14:25:58 +00001538**
1539** Return the number of errors.
drh67505e72002-04-19 12:34:06 +00001540*/
drhc28490c2006-10-26 14:25:58 +00001541static int process_input(struct callback_data *p, FILE *in){
drhdaffd0e2001-04-11 14:28:42 +00001542 char *zLine;
1543 char *zSql = 0;
1544 int nSql = 0;
1545 char *zErrMsg;
drhc49f44e2006-10-26 18:15:42 +00001546 int rc;
1547 int errCnt = 0;
drhc28490c2006-10-26 14:25:58 +00001548 int lineno = 0;
1549 int startline = 0;
drhc49f44e2006-10-26 18:15:42 +00001550
1551 while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
1552 fflush(p->out);
1553 zLine = one_input_line(zSql, in);
1554 if( zLine==0 ){
1555 break; /* We have reached EOF */
1556 }
drh67505e72002-04-19 12:34:06 +00001557 if( seenInterrupt ){
1558 if( in!=0 ) break;
1559 seenInterrupt = 0;
1560 }
drhc28490c2006-10-26 14:25:58 +00001561 lineno++;
drhdaffd0e2001-04-11 14:28:42 +00001562 if( p->echoOn ) printf("%s\n", zLine);
drhf817b6b2003-06-16 00:16:41 +00001563 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
drh2af0b2d2002-02-21 02:25:02 +00001564 if( zLine && zLine[0]=='.' && nSql==0 ){
drhc49f44e2006-10-26 18:15:42 +00001565 rc = do_meta_command(zLine, p);
drhdaffd0e2001-04-11 14:28:42 +00001566 free(zLine);
drh47ad6842006-11-08 12:25:42 +00001567 if( rc==2 ){
1568 break;
1569 }else if( rc ){
drhc49f44e2006-10-26 18:15:42 +00001570 errCnt++;
1571 }
drhdaffd0e2001-04-11 14:28:42 +00001572 continue;
1573 }
drha9b17162003-04-29 18:01:28 +00001574 if( _is_command_terminator(zLine) ){
1575 strcpy(zLine,";");
1576 }
drhdaffd0e2001-04-11 14:28:42 +00001577 if( zSql==0 ){
1578 int i;
drh4c755c02004-08-08 20:22:17 +00001579 for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){}
drhdaffd0e2001-04-11 14:28:42 +00001580 if( zLine[i]!=0 ){
1581 nSql = strlen(zLine);
1582 zSql = malloc( nSql+1 );
drhc1f44942006-05-10 14:39:13 +00001583 if( zSql==0 ){
1584 fprintf(stderr, "out of memory\n");
1585 exit(1);
1586 }
drhdaffd0e2001-04-11 14:28:42 +00001587 strcpy(zSql, zLine);
drhc28490c2006-10-26 14:25:58 +00001588 startline = lineno;
drhdaffd0e2001-04-11 14:28:42 +00001589 }
1590 }else{
1591 int len = strlen(zLine);
1592 zSql = realloc( zSql, nSql + len + 2 );
1593 if( zSql==0 ){
1594 fprintf(stderr,"%s: out of memory!\n", Argv0);
1595 exit(1);
1596 }
1597 strcpy(&zSql[nSql++], "\n");
1598 strcpy(&zSql[nSql], zLine);
1599 nSql += len;
1600 }
1601 free(zLine);
danielk19776f8a5032004-05-10 10:34:51 +00001602 if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){
drhdaffd0e2001-04-11 14:28:42 +00001603 p->cnt = 0;
drh44c2eb12003-04-30 11:38:26 +00001604 open_db(p);
danielk19776f8a5032004-05-10 10:34:51 +00001605 rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
drh7f953e22002-07-13 17:33:45 +00001606 if( rc || zErrMsg ){
drhc28490c2006-10-26 14:25:58 +00001607 char zPrefix[100];
1608 if( in!=0 || !stdin_is_interactive ){
1609 sprintf(zPrefix, "SQL error near line %d:", startline);
1610 }else{
1611 sprintf(zPrefix, "SQL error:");
1612 }
drh7f953e22002-07-13 17:33:45 +00001613 if( zErrMsg!=0 ){
drhc28490c2006-10-26 14:25:58 +00001614 printf("%s %s\n", zPrefix, zErrMsg);
drh3f4fedb2004-05-31 19:34:33 +00001615 sqlite3_free(zErrMsg);
drh7f953e22002-07-13 17:33:45 +00001616 zErrMsg = 0;
1617 }else{
drhc28490c2006-10-26 14:25:58 +00001618 printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
drh7f953e22002-07-13 17:33:45 +00001619 }
drhc49f44e2006-10-26 18:15:42 +00001620 errCnt++;
drhdaffd0e2001-04-11 14:28:42 +00001621 }
1622 free(zSql);
1623 zSql = 0;
1624 nSql = 0;
1625 }
1626 }
1627 if( zSql ){
drh70c7a4b2003-04-26 03:03:06 +00001628 if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
drhdaffd0e2001-04-11 14:28:42 +00001629 free(zSql);
1630 }
drhc49f44e2006-10-26 18:15:42 +00001631 return errCnt;
drhdaffd0e2001-04-11 14:28:42 +00001632}
1633
drh67505e72002-04-19 12:34:06 +00001634/*
1635** Return a pathname which is the user's home directory. A
1636** 0 return indicates an error of some kind. Space to hold the
1637** resulting string is obtained from malloc(). The calling
1638** function should free the result.
1639*/
1640static char *find_home_dir(void){
1641 char *home_dir = NULL;
persicom7e2dfdd2002-04-18 02:46:52 +00001642
drhcdb36b72006-06-12 12:57:45 +00001643#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
drh67505e72002-04-19 12:34:06 +00001644 struct passwd *pwent;
1645 uid_t uid = getuid();
drhbd842ba2002-08-21 11:26:41 +00001646 if( (pwent=getpwuid(uid)) != NULL) {
1647 home_dir = pwent->pw_dir;
drh67505e72002-04-19 12:34:06 +00001648 }
1649#endif
1650
drh820f3812003-01-08 13:02:52 +00001651#ifdef __MACOS__
1652 char home_path[_MAX_PATH+1];
1653 home_dir = getcwd(home_path, _MAX_PATH);
1654#endif
1655
drh164a1b62006-08-19 11:15:20 +00001656#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
1657 if (!home_dir) {
1658 home_dir = getenv("USERPROFILE");
1659 }
1660#endif
1661
drh67505e72002-04-19 12:34:06 +00001662 if (!home_dir) {
1663 home_dir = getenv("HOME");
drh67505e72002-04-19 12:34:06 +00001664 }
1665
drhcdb36b72006-06-12 12:57:45 +00001666#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
drhe98d4fa2002-04-21 19:06:22 +00001667 if (!home_dir) {
drh164a1b62006-08-19 11:15:20 +00001668 char *zDrive, *zPath;
1669 int n;
1670 zDrive = getenv("HOMEDRIVE");
1671 zPath = getenv("HOMEPATH");
1672 if( zDrive && zPath ){
1673 n = strlen(zDrive) + strlen(zPath) + 1;
1674 home_dir = malloc( n );
1675 if( home_dir==0 ) return 0;
1676 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
1677 return home_dir;
1678 }
1679 home_dir = "c:\\";
drhe98d4fa2002-04-21 19:06:22 +00001680 }
1681#endif
1682
drh67505e72002-04-19 12:34:06 +00001683 if( home_dir ){
1684 char *z = malloc( strlen(home_dir)+1 );
1685 if( z ) strcpy(z, home_dir);
1686 home_dir = z;
1687 }
drhe98d4fa2002-04-21 19:06:22 +00001688
drh67505e72002-04-19 12:34:06 +00001689 return home_dir;
1690}
1691
1692/*
1693** Read input from the file given by sqliterc_override. Or if that
1694** parameter is NULL, take input from ~/.sqliterc
1695*/
drh22fbcb82004-02-01 01:22:50 +00001696static void process_sqliterc(
1697 struct callback_data *p, /* Configuration data */
1698 const char *sqliterc_override /* Name of config file. NULL to use default */
1699){
persicom7e2dfdd2002-04-18 02:46:52 +00001700 char *home_dir = NULL;
drh22fbcb82004-02-01 01:22:50 +00001701 const char *sqliterc = sqliterc_override;
drh43617e92006-03-06 20:55:46 +00001702 char *zBuf = 0;
persicom7e2dfdd2002-04-18 02:46:52 +00001703 FILE *in = NULL;
1704
1705 if (sqliterc == NULL) {
drh67505e72002-04-19 12:34:06 +00001706 home_dir = find_home_dir();
drhe98d4fa2002-04-21 19:06:22 +00001707 if( home_dir==0 ){
1708 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
1709 return;
1710 }
drh22fbcb82004-02-01 01:22:50 +00001711 zBuf = malloc(strlen(home_dir) + 15);
1712 if( zBuf==0 ){
persicom7e2dfdd2002-04-18 02:46:52 +00001713 fprintf(stderr,"%s: out of memory!\n", Argv0);
1714 exit(1);
1715 }
drh22fbcb82004-02-01 01:22:50 +00001716 sprintf(zBuf,"%s/.sqliterc",home_dir);
drh67505e72002-04-19 12:34:06 +00001717 free(home_dir);
drh22fbcb82004-02-01 01:22:50 +00001718 sqliterc = (const char*)zBuf;
persicom7e2dfdd2002-04-18 02:46:52 +00001719 }
drha1f9b5e2004-02-14 16:31:02 +00001720 in = fopen(sqliterc,"rb");
drh22fbcb82004-02-01 01:22:50 +00001721 if( in ){
drhc28490c2006-10-26 14:25:58 +00001722 if( stdin_is_interactive ){
drh22fbcb82004-02-01 01:22:50 +00001723 printf("Loading resources from %s\n",sqliterc);
1724 }
persicom7e2dfdd2002-04-18 02:46:52 +00001725 process_input(p,in);
drhdd45df82002-04-18 12:39:03 +00001726 fclose(in);
persicom7e2dfdd2002-04-18 02:46:52 +00001727 }
drh43617e92006-03-06 20:55:46 +00001728 free(zBuf);
persicom7e2dfdd2002-04-18 02:46:52 +00001729 return;
1730}
1731
drh67505e72002-04-19 12:34:06 +00001732/*
drhe1e38c42003-05-04 18:30:59 +00001733** Show available command line options
1734*/
1735static const char zOptions[] =
1736 " -init filename read/process named file\n"
1737 " -echo print commands before execution\n"
1738 " -[no]header turn headers on or off\n"
drhc49f44e2006-10-26 18:15:42 +00001739 " -bail stop after hitting an error\n"
1740 " -interactive force interactive I/O\n"
1741 " -batch force batch I/O\n"
drhe1e38c42003-05-04 18:30:59 +00001742 " -column set output mode to 'column'\n"
drhc49f44e2006-10-26 18:15:42 +00001743 " -csv set output mode to 'csv'\n"
drhe1e38c42003-05-04 18:30:59 +00001744 " -html set output mode to HTML\n"
1745 " -line set output mode to 'line'\n"
1746 " -list set output mode to 'list'\n"
1747 " -separator 'x' set output field separator (|)\n"
1748 " -nullvalue 'text' set text string for NULL values\n"
1749 " -version show SQLite version\n"
drhe1e38c42003-05-04 18:30:59 +00001750;
1751static void usage(int showDetail){
drh80e8be92006-08-29 12:04:19 +00001752 fprintf(stderr,
1753 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
1754 "FILENAME is the name of an SQLite database. A new database is created\n"
1755 "if the file does not previously exist.\n", Argv0);
drhe1e38c42003-05-04 18:30:59 +00001756 if( showDetail ){
drh80e8be92006-08-29 12:04:19 +00001757 fprintf(stderr, "OPTIONS include:\n%s", zOptions);
drhe1e38c42003-05-04 18:30:59 +00001758 }else{
1759 fprintf(stderr, "Use the -help option for additional information\n");
1760 }
1761 exit(1);
1762}
1763
1764/*
drh67505e72002-04-19 12:34:06 +00001765** Initialize the state information in data
1766*/
drh0850b532006-01-31 19:31:43 +00001767static void main_init(struct callback_data *data) {
persicom7e2dfdd2002-04-18 02:46:52 +00001768 memset(data, 0, sizeof(*data));
1769 data->mode = MODE_List;
1770 strcpy(data->separator,"|");
1771 data->showHeader = 0;
1772 strcpy(mainPrompt,"sqlite> ");
1773 strcpy(continuePrompt," ...> ");
1774}
1775
drh75897232000-05-29 14:26:00 +00001776int main(int argc, char **argv){
drh75897232000-05-29 14:26:00 +00001777 char *zErrMsg = 0;
1778 struct callback_data data;
drh22fbcb82004-02-01 01:22:50 +00001779 const char *zInitFile = 0;
1780 char *zFirstCmd = 0;
drh44c2eb12003-04-30 11:38:26 +00001781 int i;
drhc28490c2006-10-26 14:25:58 +00001782 int rc = 0;
drh75897232000-05-29 14:26:00 +00001783
drh820f3812003-01-08 13:02:52 +00001784#ifdef __MACOS__
1785 argc = ccommand(&argv);
drh820f3812003-01-08 13:02:52 +00001786#endif
1787
drhdaffd0e2001-04-11 14:28:42 +00001788 Argv0 = argv[0];
persicom7e2dfdd2002-04-18 02:46:52 +00001789 main_init(&data);
drhc28490c2006-10-26 14:25:58 +00001790 stdin_is_interactive = isatty(0);
persicom7e2dfdd2002-04-18 02:46:52 +00001791
drh44c2eb12003-04-30 11:38:26 +00001792 /* Make sure we have a valid signal handler early, before anything
1793 ** else is done.
1794 */
drh4c504392000-10-16 22:06:40 +00001795#ifdef SIGINT
1796 signal(SIGINT, interrupt_handler);
1797#endif
drh44c2eb12003-04-30 11:38:26 +00001798
drh22fbcb82004-02-01 01:22:50 +00001799 /* Do an initial pass through the command-line argument to locate
1800 ** the name of the database file, the name of the initialization file,
1801 ** and the first command to execute.
drh44c2eb12003-04-30 11:38:26 +00001802 */
drh22fbcb82004-02-01 01:22:50 +00001803 for(i=1; i<argc-1; i++){
drhc28490c2006-10-26 14:25:58 +00001804 char *z;
drh44c2eb12003-04-30 11:38:26 +00001805 if( argv[i][0]!='-' ) break;
drhc28490c2006-10-26 14:25:58 +00001806 z = argv[i];
1807 if( z[0]=='-' && z[1]=='-' ) z++;
drh44c2eb12003-04-30 11:38:26 +00001808 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
1809 i++;
drh22fbcb82004-02-01 01:22:50 +00001810 }else if( strcmp(argv[i],"-init")==0 ){
1811 i++;
1812 zInitFile = argv[i];
drh44c2eb12003-04-30 11:38:26 +00001813 }
1814 }
drh22fbcb82004-02-01 01:22:50 +00001815 if( i<argc ){
1816 data.zDbFilename = argv[i++];
1817 }else{
danielk197703aded42004-11-22 05:26:27 +00001818#ifndef SQLITE_OMIT_MEMORYDB
drh22fbcb82004-02-01 01:22:50 +00001819 data.zDbFilename = ":memory:";
danielk197703aded42004-11-22 05:26:27 +00001820#else
1821 data.zDbFilename = 0;
1822#endif
drh22fbcb82004-02-01 01:22:50 +00001823 }
1824 if( i<argc ){
1825 zFirstCmd = argv[i++];
1826 }
drh44c2eb12003-04-30 11:38:26 +00001827 data.out = stdout;
1828
drh01b41712005-08-29 23:06:23 +00001829#ifdef SQLITE_OMIT_MEMORYDB
1830 if( data.zDbFilename==0 ){
1831 fprintf(stderr,"%s: no database filename specified\n", argv[0]);
1832 exit(1);
1833 }
1834#endif
1835
drh44c2eb12003-04-30 11:38:26 +00001836 /* Go ahead and open the database file if it already exists. If the
1837 ** file does not exist, delay opening it. This prevents empty database
1838 ** files from being created if a user mistypes the database name argument
1839 ** to the sqlite command-line tool.
1840 */
drhc8d74412004-08-31 23:41:26 +00001841 if( access(data.zDbFilename, 0)==0 ){
drh44c2eb12003-04-30 11:38:26 +00001842 open_db(&data);
1843 }
1844
drh22fbcb82004-02-01 01:22:50 +00001845 /* Process the initialization file if there is one. If no -init option
1846 ** is given on the command line, look for a file named ~/.sqliterc and
1847 ** try to process it.
drh44c2eb12003-04-30 11:38:26 +00001848 */
drh22fbcb82004-02-01 01:22:50 +00001849 process_sqliterc(&data,zInitFile);
drh44c2eb12003-04-30 11:38:26 +00001850
drh22fbcb82004-02-01 01:22:50 +00001851 /* Make a second pass through the command-line argument and set
1852 ** options. This second pass is delayed until after the initialization
1853 ** file is processed so that the command-line arguments will override
1854 ** settings in the initialization file.
drh44c2eb12003-04-30 11:38:26 +00001855 */
drh22fbcb82004-02-01 01:22:50 +00001856 for(i=1; i<argc && argv[i][0]=='-'; i++){
1857 char *z = argv[i];
drhc28490c2006-10-26 14:25:58 +00001858 if( z[1]=='-' ){ z++; }
drh2e584cd2006-09-25 13:09:22 +00001859 if( strcmp(z,"-init")==0 ){
drh22fbcb82004-02-01 01:22:50 +00001860 i++;
1861 }else if( strcmp(z,"-html")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001862 data.mode = MODE_Html;
drh22fbcb82004-02-01 01:22:50 +00001863 }else if( strcmp(z,"-list")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001864 data.mode = MODE_List;
drh22fbcb82004-02-01 01:22:50 +00001865 }else if( strcmp(z,"-line")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001866 data.mode = MODE_Line;
drh22fbcb82004-02-01 01:22:50 +00001867 }else if( strcmp(z,"-column")==0 ){
drh8b32e172002-04-08 02:42:57 +00001868 data.mode = MODE_Column;
drhc49f44e2006-10-26 18:15:42 +00001869 }else if( strcmp(z,"-csv")==0 ){
1870 data.mode = MODE_Csv;
1871 strcpy(data.separator,",");
drh22fbcb82004-02-01 01:22:50 +00001872 }else if( strcmp(z,"-separator")==0 ){
1873 i++;
1874 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
1875 }else if( strcmp(z,"-nullvalue")==0 ){
1876 i++;
1877 sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
1878 }else if( strcmp(z,"-header")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001879 data.showHeader = 1;
drh22fbcb82004-02-01 01:22:50 +00001880 }else if( strcmp(z,"-noheader")==0 ){
drh1e5d0e92000-05-31 23:33:17 +00001881 data.showHeader = 0;
drh22fbcb82004-02-01 01:22:50 +00001882 }else if( strcmp(z,"-echo")==0 ){
drhdaffd0e2001-04-11 14:28:42 +00001883 data.echoOn = 1;
drhc49f44e2006-10-26 18:15:42 +00001884 }else if( strcmp(z,"-bail")==0 ){
1885 bail_on_error = 1;
drh22fbcb82004-02-01 01:22:50 +00001886 }else if( strcmp(z,"-version")==0 ){
drhc8d74412004-08-31 23:41:26 +00001887 printf("%s\n", sqlite3_libversion());
drh151e3e12006-06-06 12:32:21 +00001888 return 0;
drhc28490c2006-10-26 14:25:58 +00001889 }else if( strcmp(z,"-interactive")==0 ){
1890 stdin_is_interactive = 1;
1891 }else if( strcmp(z,"-batch")==0 ){
1892 stdin_is_interactive = 0;
drh80e8be92006-08-29 12:04:19 +00001893 }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
drhe1e38c42003-05-04 18:30:59 +00001894 usage(1);
drh1e5d0e92000-05-31 23:33:17 +00001895 }else{
drh22fbcb82004-02-01 01:22:50 +00001896 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
drhe1e38c42003-05-04 18:30:59 +00001897 fprintf(stderr,"Use -help for a list of options.\n");
drh1e5d0e92000-05-31 23:33:17 +00001898 return 1;
1899 }
1900 }
drh44c2eb12003-04-30 11:38:26 +00001901
drh22fbcb82004-02-01 01:22:50 +00001902 if( zFirstCmd ){
drh44c2eb12003-04-30 11:38:26 +00001903 /* Run just the command that follows the database name
1904 */
drh22fbcb82004-02-01 01:22:50 +00001905 if( zFirstCmd[0]=='.' ){
1906 do_meta_command(zFirstCmd, &data);
drh6ff13852001-11-25 13:18:23 +00001907 exit(0);
1908 }else{
1909 int rc;
drh44c2eb12003-04-30 11:38:26 +00001910 open_db(&data);
danielk19776f8a5032004-05-10 10:34:51 +00001911 rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
drh6ff13852001-11-25 13:18:23 +00001912 if( rc!=0 && zErrMsg!=0 ){
1913 fprintf(stderr,"SQL error: %s\n", zErrMsg);
1914 exit(1);
1915 }
drh75897232000-05-29 14:26:00 +00001916 }
1917 }else{
drh44c2eb12003-04-30 11:38:26 +00001918 /* Run commands received from standard input
1919 */
drhc28490c2006-10-26 14:25:58 +00001920 if( stdin_is_interactive ){
drh67505e72002-04-19 12:34:06 +00001921 char *zHome;
1922 char *zHistory = 0;
drh75897232000-05-29 14:26:00 +00001923 printf(
drhb217a572000-08-22 13:40:18 +00001924 "SQLite version %s\n"
1925 "Enter \".help\" for instructions\n",
drhc8d74412004-08-31 23:41:26 +00001926 sqlite3_libversion()
drh75897232000-05-29 14:26:00 +00001927 );
drh67505e72002-04-19 12:34:06 +00001928 zHome = find_home_dir();
1929 if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
1930 sprintf(zHistory,"%s/.sqlite_history", zHome);
1931 }
danielk19774af00c62005-01-23 23:43:21 +00001932#if defined(HAVE_READLINE) && HAVE_READLINE==1
drh67505e72002-04-19 12:34:06 +00001933 if( zHistory ) read_history(zHistory);
danielk19774af00c62005-01-23 23:43:21 +00001934#endif
drhc28490c2006-10-26 14:25:58 +00001935 rc = process_input(&data, 0);
drh67505e72002-04-19 12:34:06 +00001936 if( zHistory ){
1937 stifle_history(100);
1938 write_history(zHistory);
adamd0a3daa32006-07-28 20:16:14 +00001939 free(zHistory);
drh67505e72002-04-19 12:34:06 +00001940 }
adamd0a3daa32006-07-28 20:16:14 +00001941 free(zHome);
drhdaffd0e2001-04-11 14:28:42 +00001942 }else{
drhc28490c2006-10-26 14:25:58 +00001943 rc = process_input(&data, stdin);
drh75897232000-05-29 14:26:00 +00001944 }
1945 }
drh33048c02001-10-01 14:29:22 +00001946 set_table_name(&data, 0);
adamd0a3daa32006-07-28 20:16:14 +00001947 if( db ){
1948 if( sqlite3_close(db)!=SQLITE_OK ){
1949 fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
1950 }
1951 }
drhc28490c2006-10-26 14:25:58 +00001952 return rc;
drh75897232000-05-29 14:26:00 +00001953}