source: trunk/src/3rdparty/sqlite/shell.c@ 205

Last change on this file since 205 was 205, checked in by rudi, 14 years ago

Added SQLite 2.8.17 sources. This allows to build at least one of the sql drivers / plugins.

File size: 37.8 KB
Line 
1/*
2** 2001 September 15
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** 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.
10**
11*************************************************************************
12** This file contains code to implement the "sqlite" command line
13** utility for accessing SQLite databases.
14**
15** $Id: shell.c,v 1.93.2.1 2005/02/16 03:53:11 drh Exp $
16*/
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
20#include "sqlite.h"
21#include <ctype.h>
22
23#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
24# include <signal.h>
25# include <pwd.h>
26# include <unistd.h>
27# include <sys/types.h>
28#endif
29
30#ifdef __MACOS__
31# include <console.h>
32# include <signal.h>
33# include <unistd.h>
34# include <extras.h>
35# include <Files.h>
36# include <Folders.h>
37#endif
38
39#if defined(HAVE_READLINE) && HAVE_READLINE==1
40# include <readline/readline.h>
41# include <readline/history.h>
42#else
43# define readline(p) local_getline(p,stdin)
44# define add_history(X)
45# define read_history(X)
46# define write_history(X)
47# define stifle_history(X)
48#endif
49
50/* Make sure isatty() has a prototype.
51*/
52extern int isatty();
53
54/*
55** The following is the open SQLite database. We make a pointer
56** to this database a static variable so that it can be accessed
57** by the SIGINT handler to interrupt database processing.
58*/
59static sqlite *db = 0;
60
61/*
62** True if an interrupt (Control-C) has been received.
63*/
64static int seenInterrupt = 0;
65
66/*
67** This is the name of our program. It is set in main(), used
68** in a number of other places, mostly for error messages.
69*/
70static char *Argv0;
71
72/*
73** Prompt strings. Initialized in main. Settable with
74** .prompt main continue
75*/
76static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
77static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
78
79
80/*
81** Determines if a string is a number of not.
82*/
83extern int sqliteIsNumber(const char*);
84
85/*
86** This routine reads a line of text from standard input, stores
87** the text in memory obtained from malloc() and returns a pointer
88** to the text. NULL is returned at end of file, or if malloc()
89** fails.
90**
91** The interface is like "readline" but no command-line editing
92** is done.
93*/
94static char *local_getline(char *zPrompt, FILE *in){
95 char *zLine;
96 int nLine;
97 int n;
98 int eol;
99
100 if( zPrompt && *zPrompt ){
101 printf("%s",zPrompt);
102 fflush(stdout);
103 }
104 nLine = 100;
105 zLine = malloc( nLine );
106 if( zLine==0 ) return 0;
107 n = 0;
108 eol = 0;
109 while( !eol ){
110 if( n+100>nLine ){
111 nLine = nLine*2 + 100;
112 zLine = realloc(zLine, nLine);
113 if( zLine==0 ) return 0;
114 }
115 if( fgets(&zLine[n], nLine - n, in)==0 ){
116 if( n==0 ){
117 free(zLine);
118 return 0;
119 }
120 zLine[n] = 0;
121 eol = 1;
122 break;
123 }
124 while( zLine[n] ){ n++; }
125 if( n>0 && zLine[n-1]=='\n' ){
126 n--;
127 zLine[n] = 0;
128 eol = 1;
129 }
130 }
131 zLine = realloc( zLine, n+1 );
132 return zLine;
133}
134
135/*
136** Retrieve a single line of input text. "isatty" is true if text
137** is coming from a terminal. In that case, we issue a prompt and
138** attempt to use "readline" for command-line editing. If "isatty"
139** is false, use "local_getline" instead of "readline" and issue no prompt.
140**
141** zPrior is a string of prior text retrieved. If not the empty
142** string, then issue a continuation prompt.
143*/
144static char *one_input_line(const char *zPrior, FILE *in){
145 char *zPrompt;
146 char *zResult;
147 if( in!=0 ){
148 return local_getline(0, in);
149 }
150 if( zPrior && zPrior[0] ){
151 zPrompt = continuePrompt;
152 }else{
153 zPrompt = mainPrompt;
154 }
155 zResult = readline(zPrompt);
156 if( zResult ) add_history(zResult);
157 return zResult;
158}
159
160struct previous_mode_data {
161 int valid; /* Is there legit data in here? */
162 int mode;
163 int showHeader;
164 int colWidth[100];
165};
166/*
167** An pointer to an instance of this structure is passed from
168** the main program to the callback. This is used to communicate
169** state and mode information.
170*/
171struct callback_data {
172 sqlite *db; /* The database */
173 int echoOn; /* True to echo input commands */
174 int cnt; /* Number of records displayed so far */
175 FILE *out; /* Write results here */
176 int mode; /* An output mode setting */
177 int showHeader; /* True to show column names in List or Column mode */
178 char *zDestTable; /* Name of destination table when MODE_Insert */
179 char separator[20]; /* Separator character for MODE_List */
180 int colWidth[100]; /* Requested width of each column when in column mode*/
181 int actualWidth[100]; /* Actual width of each column */
182 char nullvalue[20]; /* The text to print when a NULL comes back from
183 ** the database */
184 struct previous_mode_data explainPrev;
185 /* Holds the mode information just before
186 ** .explain ON */
187 char outfile[FILENAME_MAX]; /* Filename for *out */
188 const char *zDbFilename; /* name of the database file */
189 char *zKey; /* Encryption key */
190};
191
192/*
193** These are the allowed modes.
194*/
195#define MODE_Line 0 /* One column per line. Blank line between records */
196#define MODE_Column 1 /* One record per line in neat columns */
197#define MODE_List 2 /* One record per line with a separator */
198#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
199#define MODE_Html 4 /* Generate an XHTML table */
200#define MODE_Insert 5 /* Generate SQL "insert" statements */
201#define MODE_NUM_OF 6 /* The number of modes (not a mode itself) */
202
203char *modeDescr[MODE_NUM_OF] = {
204 "line",
205 "column",
206 "list",
207 "semi",
208 "html",
209 "insert"
210};
211
212/*
213** Number of elements in an array
214*/
215#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
216
217/*
218** Output the given string as a quoted string using SQL quoting conventions.
219*/
220static void output_quoted_string(FILE *out, const char *z){
221 int i;
222 int nSingle = 0;
223 for(i=0; z[i]; i++){
224 if( z[i]=='\'' ) nSingle++;
225 }
226 if( nSingle==0 ){
227 fprintf(out,"'%s'",z);
228 }else{
229 fprintf(out,"'");
230 while( *z ){
231 for(i=0; z[i] && z[i]!='\''; i++){}
232 if( i==0 ){
233 fprintf(out,"''");
234 z++;
235 }else if( z[i]=='\'' ){
236 fprintf(out,"%.*s''",i,z);
237 z += i+1;
238 }else{
239 fprintf(out,"%s",z);
240 break;
241 }
242 }
243 fprintf(out,"'");
244 }
245}
246
247/*
248** Output the given string with characters that are special to
249** HTML escaped.
250*/
251static void output_html_string(FILE *out, const char *z){
252 int i;
253 while( *z ){
254 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
255 if( i>0 ){
256 fprintf(out,"%.*s",i,z);
257 }
258 if( z[i]=='<' ){
259 fprintf(out,"&lt;");
260 }else if( z[i]=='&' ){
261 fprintf(out,"&amp;");
262 }else{
263 break;
264 }
265 z += i + 1;
266 }
267}
268
269/*
270** This routine runs when the user presses Ctrl-C
271*/
272static void interrupt_handler(int NotUsed){
273 seenInterrupt = 1;
274 if( db ) sqlite_interrupt(db);
275}
276
277/*
278** This is the callback routine that the SQLite library
279** invokes for each row of a query result.
280*/
281static int callback(void *pArg, int nArg, char **azArg, char **azCol){
282 int i;
283 struct callback_data *p = (struct callback_data*)pArg;
284 switch( p->mode ){
285 case MODE_Line: {
286 int w = 5;
287 if( azArg==0 ) break;
288 for(i=0; i<nArg; i++){
289 int len = strlen(azCol[i]);
290 if( len>w ) w = len;
291 }
292 if( p->cnt++>0 ) fprintf(p->out,"\n");
293 for(i=0; i<nArg; i++){
294 fprintf(p->out,"%*s = %s\n", w, azCol[i],
295 azArg[i] ? azArg[i] : p->nullvalue);
296 }
297 break;
298 }
299 case MODE_Column: {
300 if( p->cnt++==0 ){
301 for(i=0; i<nArg; i++){
302 int w, n;
303 if( i<ArraySize(p->colWidth) ){
304 w = p->colWidth[i];
305 }else{
306 w = 0;
307 }
308 if( w<=0 ){
309 w = strlen(azCol[i] ? azCol[i] : "");
310 if( w<10 ) w = 10;
311 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
312 if( w<n ) w = n;
313 }
314 if( i<ArraySize(p->actualWidth) ){
315 p->actualWidth[i] = w;
316 }
317 if( p->showHeader ){
318 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
319 }
320 }
321 if( p->showHeader ){
322 for(i=0; i<nArg; i++){
323 int w;
324 if( i<ArraySize(p->actualWidth) ){
325 w = p->actualWidth[i];
326 }else{
327 w = 10;
328 }
329 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
330 "----------------------------------------------------------",
331 i==nArg-1 ? "\n": " ");
332 }
333 }
334 }
335 if( azArg==0 ) break;
336 for(i=0; i<nArg; i++){
337 int w;
338 if( i<ArraySize(p->actualWidth) ){
339 w = p->actualWidth[i];
340 }else{
341 w = 10;
342 }
343 fprintf(p->out,"%-*.*s%s",w,w,
344 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
345 }
346 break;
347 }
348 case MODE_Semi:
349 case MODE_List: {
350 if( p->cnt++==0 && p->showHeader ){
351 for(i=0; i<nArg; i++){
352 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
353 }
354 }
355 if( azArg==0 ) break;
356 for(i=0; i<nArg; i++){
357 char *z = azArg[i];
358 if( z==0 ) z = p->nullvalue;
359 fprintf(p->out, "%s", z);
360 if( i<nArg-1 ){
361 fprintf(p->out, "%s", p->separator);
362 }else if( p->mode==MODE_Semi ){
363 fprintf(p->out, ";\n");
364 }else{
365 fprintf(p->out, "\n");
366 }
367 }
368 break;
369 }
370 case MODE_Html: {
371 if( p->cnt++==0 && p->showHeader ){
372 fprintf(p->out,"<TR>");
373 for(i=0; i<nArg; i++){
374 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
375 }
376 fprintf(p->out,"</TR>\n");
377 }
378 if( azArg==0 ) break;
379 fprintf(p->out,"<TR>");
380 for(i=0; i<nArg; i++){
381 fprintf(p->out,"<TD>");
382 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
383 fprintf(p->out,"</TD>\n");
384 }
385 fprintf(p->out,"</TR>\n");
386 break;
387 }
388 case MODE_Insert: {
389 if( azArg==0 ) break;
390 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
391 for(i=0; i<nArg; i++){
392 char *zSep = i>0 ? ",": "";
393 if( azArg[i]==0 ){
394 fprintf(p->out,"%sNULL",zSep);
395 }else if( sqliteIsNumber(azArg[i]) ){
396 fprintf(p->out,"%s%s",zSep, azArg[i]);
397 }else{
398 if( zSep[0] ) fprintf(p->out,"%s",zSep);
399 output_quoted_string(p->out, azArg[i]);
400 }
401 }
402 fprintf(p->out,");\n");
403 break;
404 }
405 }
406 return 0;
407}
408
409/*
410** Set the destination table field of the callback_data structure to
411** the name of the table given. Escape any quote characters in the
412** table name.
413*/
414static void set_table_name(struct callback_data *p, const char *zName){
415 int i, n;
416 int needQuote;
417 char *z;
418
419 if( p->zDestTable ){
420 free(p->zDestTable);
421 p->zDestTable = 0;
422 }
423 if( zName==0 ) return;
424 needQuote = !isalpha(*zName) && *zName!='_';
425 for(i=n=0; zName[i]; i++, n++){
426 if( !isalnum(zName[i]) && zName[i]!='_' ){
427 needQuote = 1;
428 if( zName[i]=='\'' ) n++;
429 }
430 }
431 if( needQuote ) n += 2;
432 z = p->zDestTable = malloc( n+1 );
433 if( z==0 ){
434 fprintf(stderr,"Out of memory!\n");
435 exit(1);
436 }
437 n = 0;
438 if( needQuote ) z[n++] = '\'';
439 for(i=0; zName[i]; i++){
440 z[n++] = zName[i];
441 if( zName[i]=='\'' ) z[n++] = '\'';
442 }
443 if( needQuote ) z[n++] = '\'';
444 z[n] = 0;
445}
446
447/*
448** This is a different callback routine used for dumping the database.
449** Each row received by this callback consists of a table name,
450** the table type ("index" or "table") and SQL to create the table.
451** This routine should print text sufficient to recreate the table.
452*/
453static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
454 struct callback_data *p = (struct callback_data *)pArg;
455 if( nArg!=3 ) return 1;
456 fprintf(p->out, "%s;\n", azArg[2]);
457 if( strcmp(azArg[1],"table")==0 ){
458 struct callback_data d2;
459 d2 = *p;
460 d2.mode = MODE_Insert;
461 d2.zDestTable = 0;
462 set_table_name(&d2, azArg[0]);
463 sqlite_exec_printf(p->db,
464 "SELECT * FROM '%q'",
465 callback, &d2, 0, azArg[0]
466 );
467 set_table_name(&d2, 0);
468 }
469 return 0;
470}
471
472/*
473** Text of a help message
474*/
475static char zHelp[] =
476 ".databases List names and files of attached databases\n"
477 ".dump ?TABLE? ... Dump the database in a text format\n"
478 ".echo ON|OFF Turn command echo on or off\n"
479 ".exit Exit this program\n"
480 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
481 ".header(s) ON|OFF Turn display of headers on or off\n"
482 ".help Show this message\n"
483 ".indices TABLE Show names of all indices on TABLE\n"
484 ".mode MODE Set mode to one of \"line(s)\", \"column(s)\", \n"
485 " \"insert\", \"list\", or \"html\"\n"
486 ".mode insert TABLE Generate SQL insert statements for TABLE\n"
487 ".nullvalue STRING Print STRING instead of nothing for NULL data\n"
488 ".output FILENAME Send output to FILENAME\n"
489 ".output stdout Send output to the screen\n"
490 ".prompt MAIN CONTINUE Replace the standard prompts\n"
491 ".quit Exit this program\n"
492 ".read FILENAME Execute SQL in FILENAME\n"
493#ifdef SQLITE_HAS_CODEC
494 ".rekey OLD NEW NEW Change the encryption key\n"
495#endif
496 ".schema ?TABLE? Show the CREATE statements\n"
497 ".separator STRING Change separator string for \"list\" mode\n"
498 ".show Show the current values for various settings\n"
499 ".tables ?PATTERN? List names of tables matching a pattern\n"
500 ".timeout MS Try opening locked tables for MS milliseconds\n"
501 ".width NUM NUM ... Set column widths for \"column\" mode\n"
502;
503
504/* Forward reference */
505static void process_input(struct callback_data *p, FILE *in);
506
507/*
508** Make sure the database is open. If it is not, then open it. If
509** the database fails to open, print an error message and exit.
510*/
511static void open_db(struct callback_data *p){
512 if( p->db==0 ){
513 char *zErrMsg = 0;
514#ifdef SQLITE_HAS_CODEC
515 int n = p->zKey ? strlen(p->zKey) : 0;
516 db = p->db = sqlite_open_encrypted(p->zDbFilename, p->zKey, n, 0, &zErrMsg);
517#else
518 db = p->db = sqlite_open(p->zDbFilename, 0, &zErrMsg);
519#endif
520 if( p->db==0 ){
521 if( zErrMsg ){
522 fprintf(stderr,"Unable to open database \"%s\": %s\n",
523 p->zDbFilename, zErrMsg);
524 }else{
525 fprintf(stderr,"Unable to open database %s\n", p->zDbFilename);
526 }
527 exit(1);
528 }
529 }
530}
531
532/*
533** If an input line begins with "." then invoke this routine to
534** process that line.
535**
536** Return 1 to exit and 0 to continue.
537*/
538static int do_meta_command(char *zLine, struct callback_data *p){
539 int i = 1;
540 int nArg = 0;
541 int n, c;
542 int rc = 0;
543 char *azArg[50];
544
545 /* Parse the input line into tokens.
546 */
547 while( zLine[i] && nArg<ArraySize(azArg) ){
548 while( isspace(zLine[i]) ){ i++; }
549 if( zLine[i]==0 ) break;
550 if( zLine[i]=='\'' || zLine[i]=='"' ){
551 int delim = zLine[i++];
552 azArg[nArg++] = &zLine[i];
553 while( zLine[i] && zLine[i]!=delim ){ i++; }
554 if( zLine[i]==delim ){
555 zLine[i++] = 0;
556 }
557 }else{
558 azArg[nArg++] = &zLine[i];
559 while( zLine[i] && !isspace(zLine[i]) ){ i++; }
560 if( zLine[i] ) zLine[i++] = 0;
561 }
562 }
563
564 /* Process the input line.
565 */
566 if( nArg==0 ) return rc;
567 n = strlen(azArg[0]);
568 c = azArg[0][0];
569 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
570 struct callback_data data;
571 char *zErrMsg = 0;
572 open_db(p);
573 memcpy(&data, p, sizeof(data));
574 data.showHeader = 1;
575 data.mode = MODE_Column;
576 data.colWidth[0] = 3;
577 data.colWidth[1] = 15;
578 data.colWidth[2] = 58;
579 sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
580 if( zErrMsg ){
581 fprintf(stderr,"Error: %s\n", zErrMsg);
582 sqlite_freemem(zErrMsg);
583 }
584 }else
585
586 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
587 char *zErrMsg = 0;
588 open_db(p);
589 fprintf(p->out, "BEGIN TRANSACTION;\n");
590 if( nArg==1 ){
591 sqlite_exec(p->db,
592 "SELECT name, type, sql FROM sqlite_master "
593 "WHERE type!='meta' AND sql NOT NULL "
594 "ORDER BY substr(type,2,1), rowid",
595 dump_callback, p, &zErrMsg
596 );
597 }else{
598 int i;
599 for(i=1; i<nArg && zErrMsg==0; i++){
600 sqlite_exec_printf(p->db,
601 "SELECT name, type, sql FROM sqlite_master "
602 "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
603 "ORDER BY substr(type,2,1), rowid",
604 dump_callback, p, &zErrMsg, azArg[i]
605 );
606 }
607 }
608 if( zErrMsg ){
609 fprintf(stderr,"Error: %s\n", zErrMsg);
610 sqlite_freemem(zErrMsg);
611 }else{
612 fprintf(p->out, "COMMIT;\n");
613 }
614 }else
615
616 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
617 int j;
618 char *z = azArg[1];
619 int val = atoi(azArg[1]);
620 for(j=0; z[j]; j++){
621 if( isupper(z[j]) ) z[j] = tolower(z[j]);
622 }
623 if( strcmp(z,"on")==0 ){
624 val = 1;
625 }else if( strcmp(z,"yes")==0 ){
626 val = 1;
627 }
628 p->echoOn = val;
629 }else
630
631 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
632 rc = 1;
633 }else
634
635 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
636 int j;
637 char *z = nArg>=2 ? azArg[1] : "1";
638 int val = atoi(z);
639 for(j=0; z[j]; j++){
640 if( isupper(z[j]) ) z[j] = tolower(z[j]);
641 }
642 if( strcmp(z,"on")==0 ){
643 val = 1;
644 }else if( strcmp(z,"yes")==0 ){
645 val = 1;
646 }
647 if(val == 1) {
648 if(!p->explainPrev.valid) {
649 p->explainPrev.valid = 1;
650 p->explainPrev.mode = p->mode;
651 p->explainPrev.showHeader = p->showHeader;
652 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
653 }
654 /* We could put this code under the !p->explainValid
655 ** condition so that it does not execute if we are already in
656 ** explain mode. However, always executing it allows us an easy
657 ** was to reset to explain mode in case the user previously
658 ** did an .explain followed by a .width, .mode or .header
659 ** command.
660 */
661 p->mode = MODE_Column;
662 p->showHeader = 1;
663 memset(p->colWidth,0,ArraySize(p->colWidth));
664 p->colWidth[0] = 4;
665 p->colWidth[1] = 12;
666 p->colWidth[2] = 10;
667 p->colWidth[3] = 10;
668 p->colWidth[4] = 35;
669 }else if (p->explainPrev.valid) {
670 p->explainPrev.valid = 0;
671 p->mode = p->explainPrev.mode;
672 p->showHeader = p->explainPrev.showHeader;
673 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
674 }
675 }else
676
677 if( c=='h' && (strncmp(azArg[0], "header", n)==0
678 ||
679 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
680 int j;
681 char *z = azArg[1];
682 int val = atoi(azArg[1]);
683 for(j=0; z[j]; j++){
684 if( isupper(z[j]) ) z[j] = tolower(z[j]);
685 }
686 if( strcmp(z,"on")==0 ){
687 val = 1;
688 }else if( strcmp(z,"yes")==0 ){
689 val = 1;
690 }
691 p->showHeader = val;
692 }else
693
694 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
695 fprintf(stderr,zHelp);
696 }else
697
698 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
699 struct callback_data data;
700 char *zErrMsg = 0;
701 open_db(p);
702 memcpy(&data, p, sizeof(data));
703 data.showHeader = 0;
704 data.mode = MODE_List;
705 sqlite_exec_printf(p->db,
706 "SELECT name FROM sqlite_master "
707 "WHERE type='index' AND tbl_name LIKE '%q' "
708 "UNION ALL "
709 "SELECT name FROM sqlite_temp_master "
710 "WHERE type='index' AND tbl_name LIKE '%q' "
711 "ORDER BY 1",
712 callback, &data, &zErrMsg, azArg[1], azArg[1]
713 );
714 if( zErrMsg ){
715 fprintf(stderr,"Error: %s\n", zErrMsg);
716 sqlite_freemem(zErrMsg);
717 }
718 }else
719
720 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
721 int n2 = strlen(azArg[1]);
722 if( strncmp(azArg[1],"line",n2)==0
723 ||
724 strncmp(azArg[1],"lines",n2)==0 ){
725 p->mode = MODE_Line;
726 }else if( strncmp(azArg[1],"column",n2)==0
727 ||
728 strncmp(azArg[1],"columns",n2)==0 ){
729 p->mode = MODE_Column;
730 }else if( strncmp(azArg[1],"list",n2)==0 ){
731 p->mode = MODE_List;
732 }else if( strncmp(azArg[1],"html",n2)==0 ){
733 p->mode = MODE_Html;
734 }else if( strncmp(azArg[1],"insert",n2)==0 ){
735 p->mode = MODE_Insert;
736 if( nArg>=3 ){
737 set_table_name(p, azArg[2]);
738 }else{
739 set_table_name(p, "table");
740 }
741 }else {
742 fprintf(stderr,"mode should be on of: column html insert line list\n");
743 }
744 }else
745
746 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
747 sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
748 }else
749
750 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
751 if( p->out!=stdout ){
752 fclose(p->out);
753 }
754 if( strcmp(azArg[1],"stdout")==0 ){
755 p->out = stdout;
756 strcpy(p->outfile,"stdout");
757 }else{
758 p->out = fopen(azArg[1], "wb");
759 if( p->out==0 ){
760 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
761 p->out = stdout;
762 } else {
763 strcpy(p->outfile,azArg[1]);
764 }
765 }
766 }else
767
768 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
769 if( nArg >= 2) {
770 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
771 }
772 if( nArg >= 3) {
773 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
774 }
775 }else
776
777 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
778 rc = 1;
779 }else
780
781 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
782 FILE *alt = fopen(azArg[1], "rb");
783 if( alt==0 ){
784 fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
785 }else{
786 process_input(p, alt);
787 fclose(alt);
788 }
789 }else
790
791#ifdef SQLITE_HAS_CODEC
792 if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){
793 char *zOld = p->zKey;
794 if( zOld==0 ) zOld = "";
795 if( strcmp(azArg[1],zOld) ){
796 fprintf(stderr,"old key is incorrect\n");
797 }else if( strcmp(azArg[2], azArg[3]) ){
798 fprintf(stderr,"2nd copy of new key does not match the 1st\n");
799 }else{
800 sqlite_freemem(p->zKey);
801 p->zKey = sqlite_mprintf("%s", azArg[2]);
802 sqlite_rekey(p->db, p->zKey, strlen(p->zKey));
803 }
804 }else
805#endif
806
807 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
808 struct callback_data data;
809 char *zErrMsg = 0;
810 open_db(p);
811 memcpy(&data, p, sizeof(data));
812 data.showHeader = 0;
813 data.mode = MODE_Semi;
814 if( nArg>1 ){
815 extern int sqliteStrICmp(const char*,const char*);
816 if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){
817 char *new_argv[2], *new_colv[2];
818 new_argv[0] = "CREATE TABLE sqlite_master (\n"
819 " type text,\n"
820 " name text,\n"
821 " tbl_name text,\n"
822 " rootpage integer,\n"
823 " sql text\n"
824 ")";
825 new_argv[1] = 0;
826 new_colv[0] = "sql";
827 new_colv[1] = 0;
828 callback(&data, 1, new_argv, new_colv);
829 }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){
830 char *new_argv[2], *new_colv[2];
831 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
832 " type text,\n"
833 " name text,\n"
834 " tbl_name text,\n"
835 " rootpage integer,\n"
836 " sql text\n"
837 ")";
838 new_argv[1] = 0;
839 new_colv[0] = "sql";
840 new_colv[1] = 0;
841 callback(&data, 1, new_argv, new_colv);
842 }else{
843 sqlite_exec_printf(p->db,
844 "SELECT sql FROM "
845 " (SELECT * FROM sqlite_master UNION ALL"
846 " SELECT * FROM sqlite_temp_master) "
847 "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL "
848 "ORDER BY substr(type,2,1), name",
849 callback, &data, &zErrMsg, azArg[1]);
850 }
851 }else{
852 sqlite_exec(p->db,
853 "SELECT sql FROM "
854 " (SELECT * FROM sqlite_master UNION ALL"
855 " SELECT * FROM sqlite_temp_master) "
856 "WHERE type!='meta' AND sql NOTNULL "
857 "ORDER BY substr(type,2,1), name",
858 callback, &data, &zErrMsg
859 );
860 }
861 if( zErrMsg ){
862 fprintf(stderr,"Error: %s\n", zErrMsg);
863 sqlite_freemem(zErrMsg);
864 }
865 }else
866
867 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
868 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
869 }else
870
871 if( c=='s' && strncmp(azArg[0], "show", n)==0){
872 int i;
873 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
874 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
875 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
876 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
877 fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue);
878 fprintf(p->out,"%9.9s: %s\n","output",
879 strlen(p->outfile) ? p->outfile : "stdout");
880 fprintf(p->out,"%9.9s: %s\n","separator", p->separator);
881 fprintf(p->out,"%9.9s: ","width");
882 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
883 fprintf(p->out,"%d ",p->colWidth[i]);
884 }
885 fprintf(p->out,"\n\n");
886 }else
887
888 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
889 char **azResult;
890 int nRow, rc;
891 char *zErrMsg;
892 open_db(p);
893 if( nArg==1 ){
894 rc = sqlite_get_table(p->db,
895 "SELECT name FROM sqlite_master "
896 "WHERE type IN ('table','view') "
897 "UNION ALL "
898 "SELECT name FROM sqlite_temp_master "
899 "WHERE type IN ('table','view') "
900 "ORDER BY 1",
901 &azResult, &nRow, 0, &zErrMsg
902 );
903 }else{
904 rc = sqlite_get_table_printf(p->db,
905 "SELECT name FROM sqlite_master "
906 "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
907 "UNION ALL "
908 "SELECT name FROM sqlite_temp_master "
909 "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
910 "ORDER BY 1",
911 &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1]
912 );
913 }
914 if( zErrMsg ){
915 fprintf(stderr,"Error: %s\n", zErrMsg);
916 sqlite_freemem(zErrMsg);
917 }
918 if( rc==SQLITE_OK ){
919 int len, maxlen = 0;
920 int i, j;
921 int nPrintCol, nPrintRow;
922 for(i=1; i<=nRow; i++){
923 if( azResult[i]==0 ) continue;
924 len = strlen(azResult[i]);
925 if( len>maxlen ) maxlen = len;
926 }
927 nPrintCol = 80/(maxlen+2);
928 if( nPrintCol<1 ) nPrintCol = 1;
929 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
930 for(i=0; i<nPrintRow; i++){
931 for(j=i+1; j<=nRow; j+=nPrintRow){
932 char *zSp = j<=nPrintRow ? "" : " ";
933 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
934 }
935 printf("\n");
936 }
937 }
938 sqlite_free_table(azResult);
939 }else
940
941 if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
942 open_db(p);
943 sqlite_busy_timeout(p->db, atoi(azArg[1]));
944 }else
945
946 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
947 int j;
948 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
949 p->colWidth[j-1] = atoi(azArg[j]);
950 }
951 }else
952
953 {
954 fprintf(stderr, "unknown command or invalid arguments: "
955 " \"%s\". Enter \".help\" for help\n", azArg[0]);
956 }
957
958 return rc;
959}
960
961/*
962** Return TRUE if the last non-whitespace character in z[] is a semicolon.
963** z[] is N characters long.
964*/
965static int _ends_with_semicolon(const char *z, int N){
966 while( N>0 && isspace(z[N-1]) ){ N--; }
967 return N>0 && z[N-1]==';';
968}
969
970/*
971** Test to see if a line consists entirely of whitespace.
972*/
973static int _all_whitespace(const char *z){
974 for(; *z; z++){
975 if( isspace(*z) ) continue;
976 if( *z=='/' && z[1]=='*' ){
977 z += 2;
978 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
979 if( *z==0 ) return 0;
980 z++;
981 continue;
982 }
983 if( *z=='-' && z[1]=='-' ){
984 z += 2;
985 while( *z && *z!='\n' ){ z++; }
986 if( *z==0 ) return 1;
987 continue;
988 }
989 return 0;
990 }
991 return 1;
992}
993
994/*
995** Return TRUE if the line typed in is an SQL command terminator other
996** than a semi-colon. The SQL Server style "go" command is understood
997** as is the Oracle "/".
998*/
999static int _is_command_terminator(const char *zLine){
1000 extern int sqliteStrNICmp(const char*,const char*,int);
1001 while( isspace(*zLine) ){ zLine++; };
1002 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */
1003 if( sqliteStrNICmp(zLine,"go",2)==0 && _all_whitespace(&zLine[2]) ){
1004 return 1; /* SQL Server */
1005 }
1006 return 0;
1007}
1008
1009/*
1010** Read input from *in and process it. If *in==0 then input
1011** is interactive - the user is typing it it. Otherwise, input
1012** is coming from a file or device. A prompt is issued and history
1013** is saved only if input is interactive. An interrupt signal will
1014** cause this routine to exit immediately, unless input is interactive.
1015*/
1016static void process_input(struct callback_data *p, FILE *in){
1017 char *zLine;
1018 char *zSql = 0;
1019 int nSql = 0;
1020 char *zErrMsg;
1021 int rc;
1022 while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
1023 if( seenInterrupt ){
1024 if( in!=0 ) break;
1025 seenInterrupt = 0;
1026 }
1027 if( p->echoOn ) printf("%s\n", zLine);
1028 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
1029 if( zLine && zLine[0]=='.' && nSql==0 ){
1030 int rc = do_meta_command(zLine, p);
1031 free(zLine);
1032 if( rc ) break;
1033 continue;
1034 }
1035 if( _is_command_terminator(zLine) ){
1036 strcpy(zLine,";");
1037 }
1038 if( zSql==0 ){
1039 int i;
1040 for(i=0; zLine[i] && isspace(zLine[i]); i++){}
1041 if( zLine[i]!=0 ){
1042 nSql = strlen(zLine);
1043 zSql = malloc( nSql+1 );
1044 strcpy(zSql, zLine);
1045 }
1046 }else{
1047 int len = strlen(zLine);
1048 zSql = realloc( zSql, nSql + len + 2 );
1049 if( zSql==0 ){
1050 fprintf(stderr,"%s: out of memory!\n", Argv0);
1051 exit(1);
1052 }
1053 strcpy(&zSql[nSql++], "\n");
1054 strcpy(&zSql[nSql], zLine);
1055 nSql += len;
1056 }
1057 free(zLine);
1058 if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite_complete(zSql) ){
1059 p->cnt = 0;
1060 open_db(p);
1061 rc = sqlite_exec(p->db, zSql, callback, p, &zErrMsg);
1062 if( rc || zErrMsg ){
1063 if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
1064 if( zErrMsg!=0 ){
1065 printf("SQL error: %s\n", zErrMsg);
1066 sqlite_freemem(zErrMsg);
1067 zErrMsg = 0;
1068 }else{
1069 printf("SQL error: %s\n", sqlite_error_string(rc));
1070 }
1071 }
1072 free(zSql);
1073 zSql = 0;
1074 nSql = 0;
1075 }
1076 }
1077 if( zSql ){
1078 if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
1079 free(zSql);
1080 }
1081}
1082
1083/*
1084** Return a pathname which is the user's home directory. A
1085** 0 return indicates an error of some kind. Space to hold the
1086** resulting string is obtained from malloc(). The calling
1087** function should free the result.
1088*/
1089static char *find_home_dir(void){
1090 char *home_dir = NULL;
1091
1092#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
1093 struct passwd *pwent;
1094 uid_t uid = getuid();
1095 if( (pwent=getpwuid(uid)) != NULL) {
1096 home_dir = pwent->pw_dir;
1097 }
1098#endif
1099
1100#ifdef __MACOS__
1101 char home_path[_MAX_PATH+1];
1102 home_dir = getcwd(home_path, _MAX_PATH);
1103#endif
1104
1105 if (!home_dir) {
1106 home_dir = getenv("HOME");
1107 if (!home_dir) {
1108 home_dir = getenv("HOMEPATH"); /* Windows? */
1109 }
1110 }
1111
1112#if defined(_WIN32) || defined(WIN32)
1113 if (!home_dir) {
1114 home_dir = "c:";
1115 }
1116#endif
1117
1118 if( home_dir ){
1119 char *z = malloc( strlen(home_dir)+1 );
1120 if( z ) strcpy(z, home_dir);
1121 home_dir = z;
1122 }
1123
1124 return home_dir;
1125}
1126
1127/*
1128** Read input from the file given by sqliterc_override. Or if that
1129** parameter is NULL, take input from ~/.sqliterc
1130*/
1131static void process_sqliterc(
1132 struct callback_data *p, /* Configuration data */
1133 const char *sqliterc_override /* Name of config file. NULL to use default */
1134){
1135 char *home_dir = NULL;
1136 const char *sqliterc = sqliterc_override;
1137 char *zBuf;
1138 FILE *in = NULL;
1139
1140 if (sqliterc == NULL) {
1141 home_dir = find_home_dir();
1142 if( home_dir==0 ){
1143 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
1144 return;
1145 }
1146 zBuf = malloc(strlen(home_dir) + 15);
1147 if( zBuf==0 ){
1148 fprintf(stderr,"%s: out of memory!\n", Argv0);
1149 exit(1);
1150 }
1151 sprintf(zBuf,"%s/.sqliterc",home_dir);
1152 free(home_dir);
1153 sqliterc = (const char*)zBuf;
1154 }
1155 in = fopen(sqliterc,"rb");
1156 if( in ){
1157 if( isatty(fileno(stdout)) ){
1158 printf("Loading resources from %s\n",sqliterc);
1159 }
1160 process_input(p,in);
1161 fclose(in);
1162 }
1163 return;
1164}
1165
1166/*
1167** Show available command line options
1168*/
1169static const char zOptions[] =
1170 " -init filename read/process named file\n"
1171 " -echo print commands before execution\n"
1172 " -[no]header turn headers on or off\n"
1173 " -column set output mode to 'column'\n"
1174 " -html set output mode to HTML\n"
1175#ifdef SQLITE_HAS_CODEC
1176 " -key KEY encryption key\n"
1177#endif
1178 " -line set output mode to 'line'\n"
1179 " -list set output mode to 'list'\n"
1180 " -separator 'x' set output field separator (|)\n"
1181 " -nullvalue 'text' set text string for NULL values\n"
1182 " -version show SQLite version\n"
1183 " -help show this text, also show dot-commands\n"
1184;
1185static void usage(int showDetail){
1186 fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0);
1187 if( showDetail ){
1188 fprintf(stderr, "Options are:\n%s", zOptions);
1189 }else{
1190 fprintf(stderr, "Use the -help option for additional information\n");
1191 }
1192 exit(1);
1193}
1194
1195/*
1196** Initialize the state information in data
1197*/
1198void main_init(struct callback_data *data) {
1199 memset(data, 0, sizeof(*data));
1200 data->mode = MODE_List;
1201 strcpy(data->separator,"|");
1202 data->showHeader = 0;
1203 strcpy(mainPrompt,"sqlite> ");
1204 strcpy(continuePrompt," ...> ");
1205}
1206
1207int main(int argc, char **argv){
1208 char *zErrMsg = 0;
1209 struct callback_data data;
1210 const char *zInitFile = 0;
1211 char *zFirstCmd = 0;
1212 int i;
1213 extern int sqliteOsFileExists(const char*);
1214
1215#ifdef __MACOS__
1216 argc = ccommand(&argv);
1217#endif
1218
1219 Argv0 = argv[0];
1220 main_init(&data);
1221
1222 /* Make sure we have a valid signal handler early, before anything
1223 ** else is done.
1224 */
1225#ifdef SIGINT
1226 signal(SIGINT, interrupt_handler);
1227#endif
1228
1229 /* Do an initial pass through the command-line argument to locate
1230 ** the name of the database file, the name of the initialization file,
1231 ** and the first command to execute.
1232 */
1233 for(i=1; i<argc-1; i++){
1234 if( argv[i][0]!='-' ) break;
1235 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
1236 i++;
1237 }else if( strcmp(argv[i],"-init")==0 ){
1238 i++;
1239 zInitFile = argv[i];
1240 }else if( strcmp(argv[i],"-key")==0 ){
1241 i++;
1242 data.zKey = sqlite_mprintf("%s",argv[i]);
1243 }
1244 }
1245 if( i<argc ){
1246 data.zDbFilename = argv[i++];
1247 }else{
1248 data.zDbFilename = ":memory:";
1249 }
1250 if( i<argc ){
1251 zFirstCmd = argv[i++];
1252 }
1253 data.out = stdout;
1254
1255 /* Go ahead and open the database file if it already exists. If the
1256 ** file does not exist, delay opening it. This prevents empty database
1257 ** files from being created if a user mistypes the database name argument
1258 ** to the sqlite command-line tool.
1259 */
1260 if( sqliteOsFileExists(data.zDbFilename) ){
1261 open_db(&data);
1262 }
1263
1264 /* Process the initialization file if there is one. If no -init option
1265 ** is given on the command line, look for a file named ~/.sqliterc and
1266 ** try to process it.
1267 */
1268 process_sqliterc(&data,zInitFile);
1269
1270 /* Make a second pass through the command-line argument and set
1271 ** options. This second pass is delayed until after the initialization
1272 ** file is processed so that the command-line arguments will override
1273 ** settings in the initialization file.
1274 */
1275 for(i=1; i<argc && argv[i][0]=='-'; i++){
1276 char *z = argv[i];
1277 if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){
1278 i++;
1279 }else if( strcmp(z,"-html")==0 ){
1280 data.mode = MODE_Html;
1281 }else if( strcmp(z,"-list")==0 ){
1282 data.mode = MODE_List;
1283 }else if( strcmp(z,"-line")==0 ){
1284 data.mode = MODE_Line;
1285 }else if( strcmp(z,"-column")==0 ){
1286 data.mode = MODE_Column;
1287 }else if( strcmp(z,"-separator")==0 ){
1288 i++;
1289 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
1290 }else if( strcmp(z,"-nullvalue")==0 ){
1291 i++;
1292 sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
1293 }else if( strcmp(z,"-header")==0 ){
1294 data.showHeader = 1;
1295 }else if( strcmp(z,"-noheader")==0 ){
1296 data.showHeader = 0;
1297 }else if( strcmp(z,"-echo")==0 ){
1298 data.echoOn = 1;
1299 }else if( strcmp(z,"-version")==0 ){
1300 printf("%s\n", sqlite_version);
1301 return 1;
1302 }else if( strcmp(z,"-help")==0 ){
1303 usage(1);
1304 }else{
1305 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
1306 fprintf(stderr,"Use -help for a list of options.\n");
1307 return 1;
1308 }
1309 }
1310
1311 if( zFirstCmd ){
1312 /* Run just the command that follows the database name
1313 */
1314 if( zFirstCmd[0]=='.' ){
1315 do_meta_command(zFirstCmd, &data);
1316 exit(0);
1317 }else{
1318 int rc;
1319 open_db(&data);
1320 rc = sqlite_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
1321 if( rc!=0 && zErrMsg!=0 ){
1322 fprintf(stderr,"SQL error: %s\n", zErrMsg);
1323 exit(1);
1324 }
1325 }
1326 }else{
1327 /* Run commands received from standard input
1328 */
1329 if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
1330 char *zHome;
1331 char *zHistory = 0;
1332 printf(
1333 "SQLite version %s\n"
1334 "Enter \".help\" for instructions\n",
1335 sqlite_version
1336 );
1337 zHome = find_home_dir();
1338 if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
1339 sprintf(zHistory,"%s/.sqlite_history", zHome);
1340 }
1341 if( zHistory ) read_history(zHistory);
1342 process_input(&data, 0);
1343 if( zHistory ){
1344 stifle_history(100);
1345 write_history(zHistory);
1346 }
1347 }else{
1348 process_input(&data, stdin);
1349 }
1350 }
1351 set_table_name(&data, 0);
1352 if( db ) sqlite_close(db);
1353 return 0;
1354}
Note: See TracBrowser for help on using the repository browser.