blob: 25214012194e3437b868496796dab3cec66253da [file] [log] [blame]
drh75897232000-05-29 14:26:00 +00001/*
2** Copyright (c) 1999, 2000 D. Richard Hipp
3**
4** This program is free software; you can redistribute it and/or
5** modify it under the terms of the GNU General Public
6** License as published by the Free Software Foundation; either
7** version 2 of the License, or (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12** General Public License for more details.
13**
14** You should have received a copy of the GNU General Public
15** License along with this library; if not, write to the
16** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17** Boston, MA 02111-1307, USA.
18**
19** Author contact information:
20** drh@hwaci.com
21** http://www.hwaci.com/drh/
22**
23*************************************************************************
24** This file contains code to implement the "sqlite" command line
25** utility for accessing SQLite databases.
26**
drhbed86902000-06-02 13:27:59 +000027** $Id: shell.c,v 1.6 2000/06/02 13:27:59 drh Exp $
drh75897232000-05-29 14:26:00 +000028*/
29#include <stdlib.h>
30#include <string.h>
31#include <stdio.h>
32#include "sqlite.h"
33#include <unistd.h>
34#include <ctype.h>
35
36#if !defined(NO_READLINE)
drh8e7e7a22000-05-30 18:45:23 +000037# include <readline/readline.h>
38# include <readline/history.h>
39#else
40# define readline getline
41# define add_history(X)
drh75897232000-05-29 14:26:00 +000042#endif
43
44/*
drh8e7e7a22000-05-30 18:45:23 +000045** This routine reads a line of text from standard input, stores
46** the text in memory obtained from malloc() and returns a pointer
47** to the text. NULL is returned at end of file, or if malloc()
48** fails.
49**
50** The interface is like "readline" but no command-line editing
51** is done.
52*/
53static char *getline(char *zPrompt){
54 char *zLine;
55 int nLine;
drh8e7e7a22000-05-30 18:45:23 +000056 int n;
57 int eol;
58
59 if( zPrompt && *zPrompt ){
60 printf("%s",zPrompt);
61 fflush(stdout);
62 }
63 nLine = 100;
64 zLine = malloc( nLine );
65 if( zLine==0 ) return 0;
66 n = 0;
67 eol = 0;
68 while( !eol ){
69 if( n+100>nLine ){
70 nLine = nLine*2 + 100;
71 zLine = realloc(zLine, nLine);
72 if( zLine==0 ) return 0;
73 }
74 if( fgets(&zLine[n], nLine - n, stdin)==0 ){
75 if( n==0 ){
76 free(zLine);
77 return 0;
78 }
79 zLine[n] = 0;
80 eol = 1;
81 break;
82 }
83 while( zLine[n] ){ n++; }
84 if( n>0 && zLine[n-1]=='\n' ){
85 n--;
86 zLine[n] = 0;
87 eol = 1;
88 }
89 }
90 zLine = realloc( zLine, n+1 );
91 return zLine;
92}
93
94/*
95** Retrieve a single line of input text. "isatty" is true if text
96** is coming from a terminal. In that case, we issue a prompt and
97** attempt to use "readline" for command-line editing. If "isatty"
98** is false, use "getline" instead of "readline" and issue to prompt.
99**
100** zPrior is a string of prior text retrieved. If not the empty
101** string, then issue a continuation prompt.
102*/
103static char *one_input_line(const char *zPrior, int isatty){
104 char *zPrompt;
105 char *zResult;
106 if( !isatty ){
107 return getline(0);
108 }
109 if( zPrior && zPrior[0] ){
110 zPrompt = " ...> ";
111 }else{
112 zPrompt = "sqlite> ";
113 }
114 zResult = readline(zPrompt);
115 add_history(zResult);
116 return zResult;
117}
118
119/*
drh75897232000-05-29 14:26:00 +0000120** An pointer to an instance of this structure is passed from
121** the main program to the callback. This is used to communicate
122** state and mode information.
123*/
124struct callback_data {
125 int cnt; /* Number of records displayed so far */
126 FILE *out; /* Write results here */
127 int mode; /* An output mode setting */
128 int showHeader; /* True to show column names in List or Column mode */
129 char separator[20];/* Separator character for MODE_List */
130 int colWidth[30]; /* Width of each column when in column mode */
131};
132
133/*
134** These are the allowed modes.
135*/
136#define MODE_Line 0 /* One field per line. Blank line between records */
137#define MODE_Column 1 /* One record per line in neat columns */
138#define MODE_List 2 /* One record per line with a separator */
drh1e5d0e92000-05-31 23:33:17 +0000139#define MODE_Html 3 /* Generate an XHTML table */
drh75897232000-05-29 14:26:00 +0000140
141/*
142** Number of elements in an array
143*/
144#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
145
146/*
147** This is the callback routine that the SQLite library
148** invokes for each row of a query result.
149*/
150static int callback(void *pArg, int nArg, char **azArg, char **azCol){
151 int i;
152 struct callback_data *p = (struct callback_data*)pArg;
153 switch( p->mode ){
154 case MODE_Line: {
155 if( p->cnt++>0 ) fprintf(p->out,"\n");
156 for(i=0; i<nArg; i++){
157 fprintf(p->out,"%s = %s\n", azCol[i], azArg[i]);
158 }
159 break;
160 }
161 case MODE_Column: {
162 if( p->cnt++==0 && p->showHeader ){
163 for(i=0; i<nArg; i++){
164 int w;
165 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
166 w = p->colWidth[i];
167 }else{
168 w = 10;
169 }
170 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
171 }
172 for(i=0; i<nArg; i++){
173 int w;
174 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
175 w = p->colWidth[i];
176 }else{
177 w = 10;
178 }
drh1e5d0e92000-05-31 23:33:17 +0000179 fprintf(p->out,"%-*.*s%s",w,w,"-------------------------------------"
180 "------------------------------------------------------------",
drh75897232000-05-29 14:26:00 +0000181 i==nArg-1 ? "\n": " ");
182 }
183 }
184 for(i=0; i<nArg; i++){
185 int w;
186 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
187 w = p->colWidth[i];
188 }else{
189 w = 10;
190 }
191 fprintf(p->out,"%-*.*s%s",w,w,azArg[i], i==nArg-1 ? "\n": " ");
192 }
193 break;
194 }
195 case MODE_List: {
196 if( p->cnt++==0 && p->showHeader ){
197 for(i=0; i<nArg; i++){
198 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
199 }
200 }
201 for(i=0; i<nArg; i++){
202 fprintf(p->out,"%s%s",azArg[i], i==nArg-1 ? "\n" : p->separator);
203 }
204 break;
205 }
drh1e5d0e92000-05-31 23:33:17 +0000206 case MODE_Html: {
207 if( p->cnt++==0 && p->showHeader ){
208 fprintf(p->out,"<TR>");
209 for(i=0; i<nArg; i++){
210 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
211 }
212 fprintf(p->out,"</TR>\n");
213 }
214 for(i=0; i<nArg; i++){
215 fprintf(p->out,"<TR>");
216 for(i=0; i<nArg; i++){
217 fprintf(p->out,"<TD>%s</TD>",azArg[i]);
218 }
219 fprintf(p->out,"</TD>\n");
220 }
221 break;
222 }
drh75897232000-05-29 14:26:00 +0000223 }
224 return 0;
225}
226
227/*
228** Text of a help message
229*/
230static char zHelp[] =
231 ".exit Exit this program\n"
232 ".explain Set output mode suitable for EXPLAIN\n"
233 ".header ON|OFF Turn display of headers on or off\n"
234 ".help Show this message\n"
235 ".indices TABLE Show names of all indices on TABLE\n"
drh1e5d0e92000-05-31 23:33:17 +0000236 ".mode MODE Set mode to one of \"line\", \"column\", "
237 "\"list\", or \"html\"\n"
drh75897232000-05-29 14:26:00 +0000238 ".output FILENAME Send output to FILENAME\n"
239 ".output stdout Send output to the screen\n"
240 ".schema ?TABLE? Show the CREATE statements\n"
241 ".separator STRING Change separator string for \"list\" mode\n"
242 ".tables List names all tables in the database\n"
243 ".width NUM NUM ... Set column widths for \"column\" mode\n"
244;
245
246/*
247** If an input line begins with "." then invoke this routine to
248** process that line.
249*/
250static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
251 int i = 1;
252 int nArg = 0;
253 int n, c;
254 char *azArg[50];
255
256 /* Parse the input line into tokens.
257 */
258 while( zLine[i] && nArg<ArraySize(azArg) ){
259 while( isspace(zLine[i]) ){ i++; }
260 if( zLine[i]=='\'' || zLine[i]=='"' ){
261 int delim = zLine[i++];
262 azArg[nArg++] = &zLine[i];
263 while( zLine[i] && zLine[i]!=delim ){ i++; }
264 if( zLine[i]==delim ){
265 zLine[i++] = 0;
266 }
267 }else{
268 azArg[nArg++] = &zLine[i];
269 while( zLine[i] && !isspace(zLine[i]) ){ i++; }
270 if( zLine[i] ) zLine[i++] = 0;
271 }
272 }
273
274 /* Process the input line.
275 */
276 if( nArg==0 ) return;
277 n = strlen(azArg[0]);
278 c = azArg[0][0];
279
280 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
281 exit(0);
282 }else
283
284 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
285 p->mode = MODE_Column;
286 p->showHeader = 1;
287 p->colWidth[0] = 4;
288 p->colWidth[1] = 12;
289 p->colWidth[2] = 5;
290 p->colWidth[3] = 5;
291 p->colWidth[4] = 40;
292 }else
293
294 if( c=='h' && strncmp(azArg[0], "header", n)==0 && nArg>1 ){
295 int j;
296 char *z = azArg[1];
297 int val = atoi(azArg[1]);
298 for(j=0; z[j]; j++){
299 if( isupper(z[j]) ) z[j] = tolower(z[j]);
300 }
301 if( strcmp(z,"on")==0 ){
302 val = 1;
303 }else if( strcmp(z,"yes")==0 ){
304 val = 1;
305 }
306 p->showHeader = val;
307 }else
308
309 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
310 fprintf(stderr,zHelp);
311 }else
312
313 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
314 struct callback_data data;
315 char *zErrMsg = 0;
316 char zSql[1000];
317 memcpy(&data, p, sizeof(data));
318 data.showHeader = 0;
319 data.mode = MODE_List;
320 sprintf(zSql, "SELECT name FROM sqlite_master "
drhdce2cbe2000-05-31 02:27:49 +0000321 "WHERE type='index' AND tbl_name LIKE '%.00s' "
drh305cea62000-05-29 17:44:25 +0000322 "ORDER BY name", azArg[1]);
drh75897232000-05-29 14:26:00 +0000323 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
324 if( zErrMsg ){
325 fprintf(stderr,"Error: %s\n", zErrMsg);
326 free(zErrMsg);
327 }
328 }else
329
330 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
331 int n2 = strlen(azArg[1]);
332 if( strncmp(azArg[1],"line",n2)==0 ){
333 p->mode = MODE_Line;
334 }else if( strncmp(azArg[1],"column",n2)==0 ){
335 p->mode = MODE_Column;
336 }else if( strncmp(azArg[1],"list",n2)==0 ){
337 p->mode = MODE_List;
drh1e5d0e92000-05-31 23:33:17 +0000338 }else if( strncmp(azArg[1],"html",n2)==0 ){
339 p->mode = MODE_Html;
drh75897232000-05-29 14:26:00 +0000340 }
341 }else
342
343 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
344 if( p->out!=stdout ){
345 fclose(p->out);
346 }
347 if( strcmp(azArg[1],"stdout")==0 ){
348 p->out = stdout;
349 }else{
350 p->out = fopen(azArg[1], "w");
351 if( p->out==0 ){
352 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
353 p->out = stdout;
354 }
355 }
356 }else
357
358 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
359 struct callback_data data;
360 char *zErrMsg = 0;
361 char zSql[1000];
362 memcpy(&data, p, sizeof(data));
363 data.showHeader = 0;
364 data.mode = MODE_List;
365 if( nArg>1 ){
drhdce2cbe2000-05-31 02:27:49 +0000366 sprintf(zSql, "SELECT sql FROM sqlite_master WHERE name LIKE '%.900s'",
drh75897232000-05-29 14:26:00 +0000367 azArg[1]);
368 }else{
369 sprintf(zSql, "SELECT sql FROM sqlite_master "
370 "ORDER BY tbl_name, type DESC, name");
371 }
372 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
373 if( zErrMsg ){
374 fprintf(stderr,"Error: %s\n", zErrMsg);
375 free(zErrMsg);
376 }
377 }else
378
379 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
380 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
381 }else
382
383 if( c=='t' && strncmp(azArg[0], "tables", n)==0 ){
384 struct callback_data data;
385 char *zErrMsg = 0;
drh305cea62000-05-29 17:44:25 +0000386 static char zSql[] =
387 "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
drh75897232000-05-29 14:26:00 +0000388 memcpy(&data, p, sizeof(data));
389 data.showHeader = 0;
390 data.mode = MODE_List;
391 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
392 if( zErrMsg ){
393 fprintf(stderr,"Error: %s\n", zErrMsg);
394 free(zErrMsg);
395 }
396 }else
397
398 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
399 int j;
400 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
401 p->colWidth[j-1] = atoi(azArg[j]);
402 }
403 }else
404
405 {
406 fprintf(stderr, "unknown command: \"%s\". Enter \".help\" for help\n",
407 azArg[0]);
408 }
409}
410
411int main(int argc, char **argv){
412 sqlite *db;
413 char *zErrMsg = 0;
drh1e5d0e92000-05-31 23:33:17 +0000414 char *argv0 = argv[0];
drh75897232000-05-29 14:26:00 +0000415 struct callback_data data;
416
drh1e5d0e92000-05-31 23:33:17 +0000417 memset(&data, 0, sizeof(data));
418 data.mode = MODE_List;
419 strcpy(data.separator,"|");
420 data.showHeader = 0;
421 while( argc>=2 && argv[1][0]=='-' ){
422 if( strcmp(argv[1],"-html")==0 ){
423 data.mode = MODE_Html;
424 argc--;
425 argv++;
426 }else if( strcmp(argv[1],"-list")==0 ){
427 data.mode = MODE_List;
428 argc--;
429 argv++;
430 }else if( strcmp(argv[1],"-line")==0 ){
431 data.mode = MODE_Line;
432 argc--;
433 argv++;
434 }else if( argc>=3 && strcmp(argv[0],"-separator")==0 ){
drhbed86902000-06-02 13:27:59 +0000435 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[2]);
drh1e5d0e92000-05-31 23:33:17 +0000436 argc -= 2;
437 argv += 2;
438 }else if( strcmp(argv[1],"-header")==0 ){
439 data.showHeader = 1;
440 argc--;
441 argv++;
442 }else if( strcmp(argv[1],"-noheader")==0 ){
443 data.showHeader = 0;
444 argc--;
445 argv++;
446 }else{
447 fprintf(stderr,"%s: unknown option: %s\n", argv0, argv[1]);
448 return 1;
449 }
450 }
drh75897232000-05-29 14:26:00 +0000451 if( argc!=2 && argc!=3 ){
drh1e5d0e92000-05-31 23:33:17 +0000452 fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
drh75897232000-05-29 14:26:00 +0000453 exit(1);
454 }
455 db = sqlite_open(argv[1], 0666, &zErrMsg);
456 if( db==0 ){
457 fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1], zErrMsg);
458 exit(1);
459 }
drh75897232000-05-29 14:26:00 +0000460 data.out = stdout;
461 if( argc==3 ){
drh75897232000-05-29 14:26:00 +0000462 if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
463 fprintf(stderr,"SQL error: %s\n", zErrMsg);
464 exit(1);
465 }
466 }else{
467 char *zLine;
468 char *zSql = 0;
469 int nSql = 0;
470 int istty = isatty(0);
drh75897232000-05-29 14:26:00 +0000471 if( istty ){
472 printf(
473 "Enter \".help\" for instructions\n"
474 );
475 }
drh8e7e7a22000-05-30 18:45:23 +0000476 while( (zLine = one_input_line(zSql, istty))!=0 ){
drh75897232000-05-29 14:26:00 +0000477 if( zLine && zLine[0]=='.' ){
478 do_meta_command(zLine, db, &data);
479 free(zLine);
480 continue;
481 }
482 if( zSql==0 ){
483 nSql = strlen(zLine);
484 zSql = malloc( nSql+1 );
485 strcpy(zSql, zLine);
486 }else{
487 int len = strlen(zLine);
488 zSql = realloc( zSql, nSql + len + 2 );
489 if( zSql==0 ){
drh1e5d0e92000-05-31 23:33:17 +0000490 fprintf(stderr,"%s: out of memory!\n", argv0);
drh75897232000-05-29 14:26:00 +0000491 exit(1);
492 }
493 strcpy(&zSql[nSql++], "\n");
494 strcpy(&zSql[nSql], zLine);
495 nSql += len;
496 }
497 free(zLine);
498 if( sqlite_complete(zSql) ){
499 data.cnt = 0;
500 if( sqlite_exec(db, zSql, callback, &data, &zErrMsg)!=0
501 && zErrMsg!=0 ){
502 printf("SQL error: %s\n", zErrMsg);
503 free(zErrMsg);
504 zErrMsg = 0;
505 }
506 free(zSql);
507 zSql = 0;
508 nSql = 0;
509 }
510 }
511 }
512 sqlite_close(db);
513 return 0;
514}