blob: 08127474573a09bffaf1bc0eb27ac129d965b244 [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**
27** $Id: shell.c,v 1.1 2000/05/29 14:26:01 drh Exp $
28*/
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)
37#include <readline/readline.h>
38#include <readline/history.h>
39#endif
40
41/*
42** An pointer to an instance of this structure is passed from
43** the main program to the callback. This is used to communicate
44** state and mode information.
45*/
46struct callback_data {
47 int cnt; /* Number of records displayed so far */
48 FILE *out; /* Write results here */
49 int mode; /* An output mode setting */
50 int showHeader; /* True to show column names in List or Column mode */
51 char separator[20];/* Separator character for MODE_List */
52 int colWidth[30]; /* Width of each column when in column mode */
53};
54
55/*
56** These are the allowed modes.
57*/
58#define MODE_Line 0 /* One field per line. Blank line between records */
59#define MODE_Column 1 /* One record per line in neat columns */
60#define MODE_List 2 /* One record per line with a separator */
61
62/*
63** Number of elements in an array
64*/
65#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
66
67/*
68** This is the callback routine that the SQLite library
69** invokes for each row of a query result.
70*/
71static int callback(void *pArg, int nArg, char **azArg, char **azCol){
72 int i;
73 struct callback_data *p = (struct callback_data*)pArg;
74 switch( p->mode ){
75 case MODE_Line: {
76 if( p->cnt++>0 ) fprintf(p->out,"\n");
77 for(i=0; i<nArg; i++){
78 fprintf(p->out,"%s = %s\n", azCol[i], azArg[i]);
79 }
80 break;
81 }
82 case MODE_Column: {
83 if( p->cnt++==0 && p->showHeader ){
84 for(i=0; i<nArg; i++){
85 int w;
86 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
87 w = p->colWidth[i];
88 }else{
89 w = 10;
90 }
91 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
92 }
93 for(i=0; i<nArg; i++){
94 int w;
95 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
96 w = p->colWidth[i];
97 }else{
98 w = 10;
99 }
100 fprintf(p->out,"%-*.*s%s",w,w,"-------------------------------------",
101 i==nArg-1 ? "\n": " ");
102 }
103 }
104 for(i=0; i<nArg; i++){
105 int w;
106 if( i<ArraySize(p->colWidth) && p->colWidth[i]>0 ){
107 w = p->colWidth[i];
108 }else{
109 w = 10;
110 }
111 fprintf(p->out,"%-*.*s%s",w,w,azArg[i], i==nArg-1 ? "\n": " ");
112 }
113 break;
114 }
115 case MODE_List: {
116 if( p->cnt++==0 && p->showHeader ){
117 for(i=0; i<nArg; i++){
118 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
119 }
120 }
121 for(i=0; i<nArg; i++){
122 fprintf(p->out,"%s%s",azArg[i], i==nArg-1 ? "\n" : p->separator);
123 }
124 break;
125 }
126 }
127 return 0;
128}
129
130/*
131** Text of a help message
132*/
133static char zHelp[] =
134 ".exit Exit this program\n"
135 ".explain Set output mode suitable for EXPLAIN\n"
136 ".header ON|OFF Turn display of headers on or off\n"
137 ".help Show this message\n"
138 ".indices TABLE Show names of all indices on TABLE\n"
139 ".mode MODE Set mode to one of \"line\", \"column\", or"
140 " \"list\"\n"
141 ".output FILENAME Send output to FILENAME\n"
142 ".output stdout Send output to the screen\n"
143 ".schema ?TABLE? Show the CREATE statements\n"
144 ".separator STRING Change separator string for \"list\" mode\n"
145 ".tables List names all tables in the database\n"
146 ".width NUM NUM ... Set column widths for \"column\" mode\n"
147;
148
149/*
150** If an input line begins with "." then invoke this routine to
151** process that line.
152*/
153static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
154 int i = 1;
155 int nArg = 0;
156 int n, c;
157 char *azArg[50];
158
159 /* Parse the input line into tokens.
160 */
161 while( zLine[i] && nArg<ArraySize(azArg) ){
162 while( isspace(zLine[i]) ){ i++; }
163 if( zLine[i]=='\'' || zLine[i]=='"' ){
164 int delim = zLine[i++];
165 azArg[nArg++] = &zLine[i];
166 while( zLine[i] && zLine[i]!=delim ){ i++; }
167 if( zLine[i]==delim ){
168 zLine[i++] = 0;
169 }
170 }else{
171 azArg[nArg++] = &zLine[i];
172 while( zLine[i] && !isspace(zLine[i]) ){ i++; }
173 if( zLine[i] ) zLine[i++] = 0;
174 }
175 }
176
177 /* Process the input line.
178 */
179 if( nArg==0 ) return;
180 n = strlen(azArg[0]);
181 c = azArg[0][0];
182
183 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
184 exit(0);
185 }else
186
187 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
188 p->mode = MODE_Column;
189 p->showHeader = 1;
190 p->colWidth[0] = 4;
191 p->colWidth[1] = 12;
192 p->colWidth[2] = 5;
193 p->colWidth[3] = 5;
194 p->colWidth[4] = 40;
195 }else
196
197 if( c=='h' && strncmp(azArg[0], "header", n)==0 && nArg>1 ){
198 int j;
199 char *z = azArg[1];
200 int val = atoi(azArg[1]);
201 for(j=0; z[j]; j++){
202 if( isupper(z[j]) ) z[j] = tolower(z[j]);
203 }
204 if( strcmp(z,"on")==0 ){
205 val = 1;
206 }else if( strcmp(z,"yes")==0 ){
207 val = 1;
208 }
209 p->showHeader = val;
210 }else
211
212 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
213 fprintf(stderr,zHelp);
214 }else
215
216 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
217 struct callback_data data;
218 char *zErrMsg = 0;
219 char zSql[1000];
220 memcpy(&data, p, sizeof(data));
221 data.showHeader = 0;
222 data.mode = MODE_List;
223 sprintf(zSql, "SELECT name FROM sqlite_master "
224 "WHERE type='index' AND tbl_name='%.900s'", azArg[1]);
225 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
226 if( zErrMsg ){
227 fprintf(stderr,"Error: %s\n", zErrMsg);
228 free(zErrMsg);
229 }
230 }else
231
232 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
233 int n2 = strlen(azArg[1]);
234 if( strncmp(azArg[1],"line",n2)==0 ){
235 p->mode = MODE_Line;
236 }else if( strncmp(azArg[1],"column",n2)==0 ){
237 p->mode = MODE_Column;
238 }else if( strncmp(azArg[1],"list",n2)==0 ){
239 p->mode = MODE_List;
240 }
241 }else
242
243 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
244 if( p->out!=stdout ){
245 fclose(p->out);
246 }
247 if( strcmp(azArg[1],"stdout")==0 ){
248 p->out = stdout;
249 }else{
250 p->out = fopen(azArg[1], "w");
251 if( p->out==0 ){
252 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
253 p->out = stdout;
254 }
255 }
256 }else
257
258 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
259 struct callback_data data;
260 char *zErrMsg = 0;
261 char zSql[1000];
262 memcpy(&data, p, sizeof(data));
263 data.showHeader = 0;
264 data.mode = MODE_List;
265 if( nArg>1 ){
266 sprintf(zSql, "SELECT sql FROM sqlite_master WHERE name='%.900s'",
267 azArg[1]);
268 }else{
269 sprintf(zSql, "SELECT sql FROM sqlite_master "
270 "ORDER BY tbl_name, type DESC, name");
271 }
272 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
273 if( zErrMsg ){
274 fprintf(stderr,"Error: %s\n", zErrMsg);
275 free(zErrMsg);
276 }
277 }else
278
279 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
280 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
281 }else
282
283 if( c=='t' && strncmp(azArg[0], "tables", n)==0 ){
284 struct callback_data data;
285 char *zErrMsg = 0;
286 static char zSql[] = "SELECT name FROM sqlite_master WHERE type='table'";
287 memcpy(&data, p, sizeof(data));
288 data.showHeader = 0;
289 data.mode = MODE_List;
290 sqlite_exec(db, zSql, callback, &data, &zErrMsg);
291 if( zErrMsg ){
292 fprintf(stderr,"Error: %s\n", zErrMsg);
293 free(zErrMsg);
294 }
295 }else
296
297 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
298 int j;
299 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
300 p->colWidth[j-1] = atoi(azArg[j]);
301 }
302 }else
303
304 {
305 fprintf(stderr, "unknown command: \"%s\". Enter \".help\" for help\n",
306 azArg[0]);
307 }
308}
309
310int main(int argc, char **argv){
311 sqlite *db;
312 char *zErrMsg = 0;
313 struct callback_data data;
314
315 if( argc!=2 && argc!=3 ){
316 fprintf(stderr,"Usage: %s FILENAME ?SQL?\n", *argv);
317 exit(1);
318 }
319 db = sqlite_open(argv[1], 0666, &zErrMsg);
320 if( db==0 ){
321 fprintf(stderr,"Unable to open database \"%s\": %s\n", argv[1], zErrMsg);
322 exit(1);
323 }
324 memset(&data, 0, sizeof(data));
325 data.out = stdout;
326 if( argc==3 ){
327 data.mode = MODE_List;
328 strcpy(data.separator,"|");
329 if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
330 fprintf(stderr,"SQL error: %s\n", zErrMsg);
331 exit(1);
332 }
333 }else{
334 char *zLine;
335 char *zSql = 0;
336 int nSql = 0;
337 int istty = isatty(0);
338 data.mode = MODE_Line;
339 strcpy(data.separator,"|");
340 data.showHeader = 0;
341 if( istty ){
342 printf(
343 "Enter \".help\" for instructions\n"
344 );
345 }
346 while( (zLine = readline(istty ? (zSql==0 ? "sql> " : ".... ") : 0))!=0 ){
347 if( zLine && zLine[0]=='.' ){
348 do_meta_command(zLine, db, &data);
349 free(zLine);
350 continue;
351 }
352 if( zSql==0 ){
353 nSql = strlen(zLine);
354 zSql = malloc( nSql+1 );
355 strcpy(zSql, zLine);
356 }else{
357 int len = strlen(zLine);
358 zSql = realloc( zSql, nSql + len + 2 );
359 if( zSql==0 ){
360 fprintf(stderr,"%s: out of memory!\n", *argv);
361 exit(1);
362 }
363 strcpy(&zSql[nSql++], "\n");
364 strcpy(&zSql[nSql], zLine);
365 nSql += len;
366 }
367 free(zLine);
368 if( sqlite_complete(zSql) ){
369 data.cnt = 0;
370 if( sqlite_exec(db, zSql, callback, &data, &zErrMsg)!=0
371 && zErrMsg!=0 ){
372 printf("SQL error: %s\n", zErrMsg);
373 free(zErrMsg);
374 zErrMsg = 0;
375 }
376 free(zSql);
377 zSql = 0;
378 nSql = 0;
379 }
380 }
381 }
382 sqlite_close(db);
383 return 0;
384}