00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include "sqlite.h"
00021 #include <ctype.h>
00022
00023 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
00024 # include <signal.h>
00025 # include <pwd.h>
00026 # include <unistd.h>
00027 # include <sys/types.h>
00028 #endif
00029
00030 #ifdef __MACOS__
00031 # include <console.h>
00032 # include <signal.h>
00033 # include <unistd.h>
00034 # include <extras.h>
00035 # include <Files.h>
00036 # include <Folders.h>
00037 #endif
00038
00039 #if defined(HAVE_READLINE) && HAVE_READLINE==1
00040 # include <readline/readline.h>
00041 # include <readline/history.h>
00042 #else
00043 # define readline(p) local_getline(p,stdin)
00044 # define add_history(X)
00045 # define read_history(X)
00046 # define write_history(X)
00047 # define stifle_history(X)
00048 #endif
00049
00050
00051
00052 extern int isatty();
00053
00054
00055
00056
00057
00058
00059 static sqlite *db = 0;
00060
00061
00062
00063
00064 static int seenInterrupt = 0;
00065
00066
00067
00068
00069
00070 static char *Argv0;
00071
00072
00073
00074
00075
00076 static char mainPrompt[20];
00077 static char continuePrompt[20];
00078
00079
00080
00081
00082
00083 extern int sqliteIsNumber(const char*);
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static char *local_getline(char *zPrompt, FILE *in){
00095 char *zLine;
00096 int nLine;
00097 int n;
00098 int eol;
00099
00100 if( zPrompt && *zPrompt ){
00101 printf("%s",zPrompt);
00102 fflush(stdout);
00103 }
00104 nLine = 100;
00105 zLine = malloc( nLine );
00106 if( zLine==0 ) return 0;
00107 n = 0;
00108 eol = 0;
00109 while( !eol ){
00110 if( n+100>nLine ){
00111 nLine = nLine*2 + 100;
00112 zLine = realloc(zLine, nLine);
00113 if( zLine==0 ) return 0;
00114 }
00115 if( fgets(&zLine[n], nLine - n, in)==0 ){
00116 if( n==0 ){
00117 free(zLine);
00118 return 0;
00119 }
00120 zLine[n] = 0;
00121 eol = 1;
00122 break;
00123 }
00124 while( zLine[n] ){ n++; }
00125 if( n>0 && zLine[n-1]=='\n' ){
00126 n--;
00127 zLine[n] = 0;
00128 eol = 1;
00129 }
00130 }
00131 zLine = realloc( zLine, n+1 );
00132 return zLine;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 static char *one_input_line(const char *zPrior, FILE *in){
00145 char *zPrompt;
00146 char *zResult;
00147 if( in!=0 ){
00148 return local_getline(0, in);
00149 }
00150 if( zPrior && zPrior[0] ){
00151 zPrompt = continuePrompt;
00152 }else{
00153 zPrompt = mainPrompt;
00154 }
00155 zResult = readline(zPrompt);
00156 if( zResult ) add_history(zResult);
00157 return zResult;
00158 }
00159
00160 struct previous_mode_data {
00161 int valid;
00162 int mode;
00163 int showHeader;
00164 int colWidth[100];
00165 };
00166
00167
00168
00169
00170
00171 struct callback_data {
00172 sqlite *db;
00173 int echoOn;
00174 int cnt;
00175 FILE *out;
00176 int mode;
00177 int showHeader;
00178 char *zDestTable;
00179 char separator[20];
00180 int colWidth[100];
00181 int actualWidth[100];
00182 char nullvalue[20];
00183
00184 struct previous_mode_data explainPrev;
00185
00186
00187 char outfile[FILENAME_MAX];
00188 const char *zDbFilename;
00189 char *zKey;
00190 };
00191
00192
00193
00194
00195 #define MODE_Line 0
00196 #define MODE_Column 1
00197 #define MODE_List 2
00198 #define MODE_Semi 3
00199 #define MODE_Html 4
00200 #define MODE_Insert 5
00201 #define MODE_NUM_OF 6
00202
00203 char *modeDescr[MODE_NUM_OF] = {
00204 "line",
00205 "column",
00206 "list",
00207 "semi",
00208 "html",
00209 "insert"
00210 };
00211
00212
00213
00214
00215 #define ArraySize(X) (sizeof(X)/sizeof(X[0]))
00216
00217
00218
00219
00220 static void output_quoted_string(FILE *out, const char *z){
00221 int i;
00222 int nSingle = 0;
00223 for(i=0; z[i]; i++){
00224 if( z[i]=='\'' ) nSingle++;
00225 }
00226 if( nSingle==0 ){
00227 fprintf(out,"'%s'",z);
00228 }else{
00229 fprintf(out,"'");
00230 while( *z ){
00231 for(i=0; z[i] && z[i]!='\''; i++){}
00232 if( i==0 ){
00233 fprintf(out,"''");
00234 z++;
00235 }else if( z[i]=='\'' ){
00236 fprintf(out,"%.*s''",i,z);
00237 z += i+1;
00238 }else{
00239 fprintf(out,"%s",z);
00240 break;
00241 }
00242 }
00243 fprintf(out,"'");
00244 }
00245 }
00246
00247
00248
00249
00250
00251 static void output_html_string(FILE *out, const char *z){
00252 int i;
00253 while( *z ){
00254 for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
00255 if( i>0 ){
00256 fprintf(out,"%.*s",i,z);
00257 }
00258 if( z[i]=='<' ){
00259 fprintf(out,"<");
00260 }else if( z[i]=='&' ){
00261 fprintf(out,"&");
00262 }else{
00263 break;
00264 }
00265 z += i + 1;
00266 }
00267 }
00268
00269
00270
00271
00272 static void interrupt_handler(int NotUsed){
00273 seenInterrupt = 1;
00274 if( db ) sqlite_interrupt(db);
00275 }
00276
00277
00278
00279
00280
00281 static int callback(void *pArg, int nArg, char **azArg, char **azCol){
00282 int i;
00283 struct callback_data *p = (struct callback_data*)pArg;
00284 switch( p->mode ){
00285 case MODE_Line: {
00286 int w = 5;
00287 if( azArg==0 ) break;
00288 for(i=0; i<nArg; i++){
00289 int len = strlen(azCol[i]);
00290 if( len>w ) w = len;
00291 }
00292 if( p->cnt++>0 ) fprintf(p->out,"\n");
00293 for(i=0; i<nArg; i++){
00294 fprintf(p->out,"%*s = %s\n", w, azCol[i],
00295 azArg[i] ? azArg[i] : p->nullvalue);
00296 }
00297 break;
00298 }
00299 case MODE_Column: {
00300 if( p->cnt++==0 ){
00301 for(i=0; i<nArg; i++){
00302 int w, n;
00303 if( i<ArraySize(p->colWidth) ){
00304 w = p->colWidth[i];
00305 }else{
00306 w = 0;
00307 }
00308 if( w<=0 ){
00309 w = strlen(azCol[i] ? azCol[i] : "");
00310 if( w<10 ) w = 10;
00311 n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
00312 if( w<n ) w = n;
00313 }
00314 if( i<ArraySize(p->actualWidth) ){
00315 p->actualWidth[i] = w;
00316 }
00317 if( p->showHeader ){
00318 fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " ");
00319 }
00320 }
00321 if( p->showHeader ){
00322 for(i=0; i<nArg; i++){
00323 int w;
00324 if( i<ArraySize(p->actualWidth) ){
00325 w = p->actualWidth[i];
00326 }else{
00327 w = 10;
00328 }
00329 fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
00330 "----------------------------------------------------------",
00331 i==nArg-1 ? "\n": " ");
00332 }
00333 }
00334 }
00335 if( azArg==0 ) break;
00336 for(i=0; i<nArg; i++){
00337 int w;
00338 if( i<ArraySize(p->actualWidth) ){
00339 w = p->actualWidth[i];
00340 }else{
00341 w = 10;
00342 }
00343 fprintf(p->out,"%-*.*s%s",w,w,
00344 azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " ");
00345 }
00346 break;
00347 }
00348 case MODE_Semi:
00349 case MODE_List: {
00350 if( p->cnt++==0 && p->showHeader ){
00351 for(i=0; i<nArg; i++){
00352 fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
00353 }
00354 }
00355 if( azArg==0 ) break;
00356 for(i=0; i<nArg; i++){
00357 char *z = azArg[i];
00358 if( z==0 ) z = p->nullvalue;
00359 fprintf(p->out, "%s", z);
00360 if( i<nArg-1 ){
00361 fprintf(p->out, "%s", p->separator);
00362 }else if( p->mode==MODE_Semi ){
00363 fprintf(p->out, ";\n");
00364 }else{
00365 fprintf(p->out, "\n");
00366 }
00367 }
00368 break;
00369 }
00370 case MODE_Html: {
00371 if( p->cnt++==0 && p->showHeader ){
00372 fprintf(p->out,"<TR>");
00373 for(i=0; i<nArg; i++){
00374 fprintf(p->out,"<TH>%s</TH>",azCol[i]);
00375 }
00376 fprintf(p->out,"</TR>\n");
00377 }
00378 if( azArg==0 ) break;
00379 fprintf(p->out,"<TR>");
00380 for(i=0; i<nArg; i++){
00381 fprintf(p->out,"<TD>");
00382 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
00383 fprintf(p->out,"</TD>\n");
00384 }
00385 fprintf(p->out,"</TR>\n");
00386 break;
00387 }
00388 case MODE_Insert: {
00389 if( azArg==0 ) break;
00390 fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
00391 for(i=0; i<nArg; i++){
00392 char *zSep = i>0 ? ",": "";
00393 if( azArg[i]==0 ){
00394 fprintf(p->out,"%sNULL",zSep);
00395 }else if( sqliteIsNumber(azArg[i]) ){
00396 fprintf(p->out,"%s%s",zSep, azArg[i]);
00397 }else{
00398 if( zSep[0] ) fprintf(p->out,"%s",zSep);
00399 output_quoted_string(p->out, azArg[i]);
00400 }
00401 }
00402 fprintf(p->out,");\n");
00403 break;
00404 }
00405 }
00406 return 0;
00407 }
00408
00409
00410
00411
00412
00413
00414 static void set_table_name(struct callback_data *p, const char *zName){
00415 int i, n;
00416 int needQuote;
00417 char *z;
00418
00419 if( p->zDestTable ){
00420 free(p->zDestTable);
00421 p->zDestTable = 0;
00422 }
00423 if( zName==0 ) return;
00424 needQuote = !isalpha(*zName) && *zName!='_';
00425 for(i=n=0; zName[i]; i++, n++){
00426 if( !isalnum(zName[i]) && zName[i]!='_' ){
00427 needQuote = 1;
00428 if( zName[i]=='\'' ) n++;
00429 }
00430 }
00431 if( needQuote ) n += 2;
00432 z = p->zDestTable = malloc( n+1 );
00433 if( z==0 ){
00434 fprintf(stderr,"Out of memory!\n");
00435 exit(1);
00436 }
00437 n = 0;
00438 if( needQuote ) z[n++] = '\'';
00439 for(i=0; zName[i]; i++){
00440 z[n++] = zName[i];
00441 if( zName[i]=='\'' ) z[n++] = '\'';
00442 }
00443 if( needQuote ) z[n++] = '\'';
00444 z[n] = 0;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
00454 struct callback_data *p = (struct callback_data *)pArg;
00455 if( nArg!=3 ) return 1;
00456 fprintf(p->out, "%s;\n", azArg[2]);
00457 if( strcmp(azArg[1],"table")==0 ){
00458 struct callback_data d2;
00459 d2 = *p;
00460 d2.mode = MODE_Insert;
00461 d2.zDestTable = 0;
00462 set_table_name(&d2, azArg[0]);
00463 sqlite_exec_printf(p->db,
00464 "SELECT * FROM '%q'",
00465 callback, &d2, 0, azArg[0]
00466 );
00467 set_table_name(&d2, 0);
00468 }
00469 return 0;
00470 }
00471
00472
00473
00474
00475 static char zHelp[] =
00476 ".databases List names and files of attached databases\n"
00477 ".dump ?TABLE? ... Dump the database in a text format\n"
00478 ".echo ON|OFF Turn command echo on or off\n"
00479 ".exit Exit this program\n"
00480 ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
00481 ".header(s) ON|OFF Turn display of headers on or off\n"
00482 ".help Show this message\n"
00483 ".indices TABLE Show names of all indices on TABLE\n"
00484 ".mode MODE Set mode to one of \"line(s)\", \"column(s)\", \n"
00485 " \"insert\", \"list\", or \"html\"\n"
00486 ".mode insert TABLE Generate SQL insert statements for TABLE\n"
00487 ".nullvalue STRING Print STRING instead of nothing for NULL data\n"
00488 ".output FILENAME Send output to FILENAME\n"
00489 ".output stdout Send output to the screen\n"
00490 ".prompt MAIN CONTINUE Replace the standard prompts\n"
00491 ".quit Exit this program\n"
00492 ".read FILENAME Execute SQL in FILENAME\n"
00493 #ifdef SQLITE_HAS_CODEC
00494 ".rekey OLD NEW NEW Change the encryption key\n"
00495 #endif
00496 ".schema ?TABLE? Show the CREATE statements\n"
00497 ".separator STRING Change separator string for \"list\" mode\n"
00498 ".show Show the current values for various settings\n"
00499 ".tables ?PATTERN? List names of tables matching a pattern\n"
00500 ".timeout MS Try opening locked tables for MS milliseconds\n"
00501 ".width NUM NUM ... Set column widths for \"column\" mode\n"
00502 ;
00503
00504
00505 static void process_input(struct callback_data *p, FILE *in);
00506
00507
00508
00509
00510
00511 static void open_db(struct callback_data *p){
00512 if( p->db==0 ){
00513 char *zErrMsg = 0;
00514 #ifdef SQLITE_HAS_CODEC
00515 int n = p->zKey ? strlen(p->zKey) : 0;
00516 db = p->db = sqlite_open_encrypted(p->zDbFilename, p->zKey, n, 0, &zErrMsg);
00517 #else
00518 db = p->db = sqlite_open(p->zDbFilename, 0, &zErrMsg);
00519 #endif
00520 if( p->db==0 ){
00521 if( zErrMsg ){
00522 fprintf(stderr,"Unable to open database \"%s\": %s\n",
00523 p->zDbFilename, zErrMsg);
00524 }else{
00525 fprintf(stderr,"Unable to open database %s\n", p->zDbFilename);
00526 }
00527 exit(1);
00528 }
00529 }
00530 }
00531
00532
00533
00534
00535
00536
00537
00538 static int do_meta_command(char *zLine, struct callback_data *p){
00539 int i = 1;
00540 int nArg = 0;
00541 int n, c;
00542 int rc = 0;
00543 char *azArg[50];
00544
00545
00546
00547 while( zLine[i] && nArg<ArraySize(azArg) ){
00548 while( isspace(zLine[i]) ){ i++; }
00549 if( zLine[i]==0 ) break;
00550 if( zLine[i]=='\'' || zLine[i]=='"' ){
00551 int delim = zLine[i++];
00552 azArg[nArg++] = &zLine[i];
00553 while( zLine[i] && zLine[i]!=delim ){ i++; }
00554 if( zLine[i]==delim ){
00555 zLine[i++] = 0;
00556 }
00557 }else{
00558 azArg[nArg++] = &zLine[i];
00559 while( zLine[i] && !isspace(zLine[i]) ){ i++; }
00560 if( zLine[i] ) zLine[i++] = 0;
00561 }
00562 }
00563
00564
00565
00566 if( nArg==0 ) return rc;
00567 n = strlen(azArg[0]);
00568 c = azArg[0][0];
00569 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
00570 struct callback_data data;
00571 char *zErrMsg = 0;
00572 open_db(p);
00573 memcpy(&data, p, sizeof(data));
00574 data.showHeader = 1;
00575 data.mode = MODE_Column;
00576 data.colWidth[0] = 3;
00577 data.colWidth[1] = 15;
00578 data.colWidth[2] = 58;
00579 sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
00580 if( zErrMsg ){
00581 fprintf(stderr,"Error: %s\n", zErrMsg);
00582 sqlite_freemem(zErrMsg);
00583 }
00584 }else
00585
00586 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
00587 char *zErrMsg = 0;
00588 open_db(p);
00589 fprintf(p->out, "BEGIN TRANSACTION;\n");
00590 if( nArg==1 ){
00591 sqlite_exec(p->db,
00592 "SELECT name, type, sql FROM sqlite_master "
00593 "WHERE type!='meta' AND sql NOT NULL "
00594 "ORDER BY substr(type,2,1), rowid",
00595 dump_callback, p, &zErrMsg
00596 );
00597 }else{
00598 int i;
00599 for(i=1; i<nArg && zErrMsg==0; i++){
00600 sqlite_exec_printf(p->db,
00601 "SELECT name, type, sql FROM sqlite_master "
00602 "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
00603 "ORDER BY substr(type,2,1), rowid",
00604 dump_callback, p, &zErrMsg, azArg[i]
00605 );
00606 }
00607 }
00608 if( zErrMsg ){
00609 fprintf(stderr,"Error: %s\n", zErrMsg);
00610 sqlite_freemem(zErrMsg);
00611 }else{
00612 fprintf(p->out, "COMMIT;\n");
00613 }
00614 }else
00615
00616 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
00617 int j;
00618 char *z = azArg[1];
00619 int val = atoi(azArg[1]);
00620 for(j=0; z[j]; j++){
00621 if( isupper(z[j]) ) z[j] = tolower(z[j]);
00622 }
00623 if( strcmp(z,"on")==0 ){
00624 val = 1;
00625 }else if( strcmp(z,"yes")==0 ){
00626 val = 1;
00627 }
00628 p->echoOn = val;
00629 }else
00630
00631 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
00632 rc = 1;
00633 }else
00634
00635 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
00636 int j;
00637 char *z = nArg>=2 ? azArg[1] : "1";
00638 int val = atoi(z);
00639 for(j=0; z[j]; j++){
00640 if( isupper(z[j]) ) z[j] = tolower(z[j]);
00641 }
00642 if( strcmp(z,"on")==0 ){
00643 val = 1;
00644 }else if( strcmp(z,"yes")==0 ){
00645 val = 1;
00646 }
00647 if(val == 1) {
00648 if(!p->explainPrev.valid) {
00649 p->explainPrev.valid = 1;
00650 p->explainPrev.mode = p->mode;
00651 p->explainPrev.showHeader = p->showHeader;
00652 memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
00653 }
00654
00655
00656
00657
00658
00659
00660
00661 p->mode = MODE_Column;
00662 p->showHeader = 1;
00663 memset(p->colWidth,0,ArraySize(p->colWidth));
00664 p->colWidth[0] = 4;
00665 p->colWidth[1] = 12;
00666 p->colWidth[2] = 10;
00667 p->colWidth[3] = 10;
00668 p->colWidth[4] = 35;
00669 }else if (p->explainPrev.valid) {
00670 p->explainPrev.valid = 0;
00671 p->mode = p->explainPrev.mode;
00672 p->showHeader = p->explainPrev.showHeader;
00673 memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
00674 }
00675 }else
00676
00677 if( c=='h' && (strncmp(azArg[0], "header", n)==0
00678 ||
00679 strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
00680 int j;
00681 char *z = azArg[1];
00682 int val = atoi(azArg[1]);
00683 for(j=0; z[j]; j++){
00684 if( isupper(z[j]) ) z[j] = tolower(z[j]);
00685 }
00686 if( strcmp(z,"on")==0 ){
00687 val = 1;
00688 }else if( strcmp(z,"yes")==0 ){
00689 val = 1;
00690 }
00691 p->showHeader = val;
00692 }else
00693
00694 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
00695 fprintf(stderr,zHelp);
00696 }else
00697
00698 if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
00699 struct callback_data data;
00700 char *zErrMsg = 0;
00701 open_db(p);
00702 memcpy(&data, p, sizeof(data));
00703 data.showHeader = 0;
00704 data.mode = MODE_List;
00705 sqlite_exec_printf(p->db,
00706 "SELECT name FROM sqlite_master "
00707 "WHERE type='index' AND tbl_name LIKE '%q' "
00708 "UNION ALL "
00709 "SELECT name FROM sqlite_temp_master "
00710 "WHERE type='index' AND tbl_name LIKE '%q' "
00711 "ORDER BY 1",
00712 callback, &data, &zErrMsg, azArg[1], azArg[1]
00713 );
00714 if( zErrMsg ){
00715 fprintf(stderr,"Error: %s\n", zErrMsg);
00716 sqlite_freemem(zErrMsg);
00717 }
00718 }else
00719
00720 if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
00721 int n2 = strlen(azArg[1]);
00722 if( strncmp(azArg[1],"line",n2)==0
00723 ||
00724 strncmp(azArg[1],"lines",n2)==0 ){
00725 p->mode = MODE_Line;
00726 }else if( strncmp(azArg[1],"column",n2)==0
00727 ||
00728 strncmp(azArg[1],"columns",n2)==0 ){
00729 p->mode = MODE_Column;
00730 }else if( strncmp(azArg[1],"list",n2)==0 ){
00731 p->mode = MODE_List;
00732 }else if( strncmp(azArg[1],"html",n2)==0 ){
00733 p->mode = MODE_Html;
00734 }else if( strncmp(azArg[1],"insert",n2)==0 ){
00735 p->mode = MODE_Insert;
00736 if( nArg>=3 ){
00737 set_table_name(p, azArg[2]);
00738 }else{
00739 set_table_name(p, "table");
00740 }
00741 }else {
00742 fprintf(stderr,"mode should be on of: column html insert line list\n");
00743 }
00744 }else
00745
00746 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
00747 sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
00748 }else
00749
00750 if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
00751 if( p->out!=stdout ){
00752 fclose(p->out);
00753 }
00754 if( strcmp(azArg[1],"stdout")==0 ){
00755 p->out = stdout;
00756 strcpy(p->outfile,"stdout");
00757 }else{
00758 p->out = fopen(azArg[1], "wb");
00759 if( p->out==0 ){
00760 fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
00761 p->out = stdout;
00762 } else {
00763 strcpy(p->outfile,azArg[1]);
00764 }
00765 }
00766 }else
00767
00768 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
00769 if( nArg >= 2) {
00770 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
00771 }
00772 if( nArg >= 3) {
00773 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
00774 }
00775 }else
00776
00777 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
00778 rc = 1;
00779 }else
00780
00781 if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
00782 FILE *alt = fopen(azArg[1], "rb");
00783 if( alt==0 ){
00784 fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
00785 }else{
00786 process_input(p, alt);
00787 fclose(alt);
00788 }
00789 }else
00790
00791 #ifdef SQLITE_HAS_CODEC
00792 if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){
00793 char *zOld = p->zKey;
00794 if( zOld==0 ) zOld = "";
00795 if( strcmp(azArg[1],zOld) ){
00796 fprintf(stderr,"old key is incorrect\n");
00797 }else if( strcmp(azArg[2], azArg[3]) ){
00798 fprintf(stderr,"2nd copy of new key does not match the 1st\n");
00799 }else{
00800 sqlite_freemem(p->zKey);
00801 p->zKey = sqlite_mprintf("%s", azArg[2]);
00802 sqlite_rekey(p->db, p->zKey, strlen(p->zKey));
00803 }
00804 }else
00805 #endif
00806
00807 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
00808 struct callback_data data;
00809 char *zErrMsg = 0;
00810 open_db(p);
00811 memcpy(&data, p, sizeof(data));
00812 data.showHeader = 0;
00813 data.mode = MODE_Semi;
00814 if( nArg>1 ){
00815 extern int sqliteStrICmp(const char*,const char*);
00816 if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){
00817 char *new_argv[2], *new_colv[2];
00818 new_argv[0] = "CREATE TABLE sqlite_master (\n"
00819 " type text,\n"
00820 " name text,\n"
00821 " tbl_name text,\n"
00822 " rootpage integer,\n"
00823 " sql text\n"
00824 ")";
00825 new_argv[1] = 0;
00826 new_colv[0] = "sql";
00827 new_colv[1] = 0;
00828 callback(&data, 1, new_argv, new_colv);
00829 }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){
00830 char *new_argv[2], *new_colv[2];
00831 new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
00832 " type text,\n"
00833 " name text,\n"
00834 " tbl_name text,\n"
00835 " rootpage integer,\n"
00836 " sql text\n"
00837 ")";
00838 new_argv[1] = 0;
00839 new_colv[0] = "sql";
00840 new_colv[1] = 0;
00841 callback(&data, 1, new_argv, new_colv);
00842 }else{
00843 sqlite_exec_printf(p->db,
00844 "SELECT sql FROM "
00845 " (SELECT * FROM sqlite_master UNION ALL"
00846 " SELECT * FROM sqlite_temp_master) "
00847 "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL "
00848 "ORDER BY substr(type,2,1), name",
00849 callback, &data, &zErrMsg, azArg[1]);
00850 }
00851 }else{
00852 sqlite_exec(p->db,
00853 "SELECT sql FROM "
00854 " (SELECT * FROM sqlite_master UNION ALL"
00855 " SELECT * FROM sqlite_temp_master) "
00856 "WHERE type!='meta' AND sql NOTNULL "
00857 "ORDER BY substr(type,2,1), name",
00858 callback, &data, &zErrMsg
00859 );
00860 }
00861 if( zErrMsg ){
00862 fprintf(stderr,"Error: %s\n", zErrMsg);
00863 sqlite_freemem(zErrMsg);
00864 }
00865 }else
00866
00867 if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
00868 sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
00869 }else
00870
00871 if( c=='s' && strncmp(azArg[0], "show", n)==0){
00872 int i;
00873 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
00874 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
00875 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
00876 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
00877 fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue);
00878 fprintf(p->out,"%9.9s: %s\n","output",
00879 strlen(p->outfile) ? p->outfile : "stdout");
00880 fprintf(p->out,"%9.9s: %s\n","separator", p->separator);
00881 fprintf(p->out,"%9.9s: ","width");
00882 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
00883 fprintf(p->out,"%d ",p->colWidth[i]);
00884 }
00885 fprintf(p->out,"\n\n");
00886 }else
00887
00888 if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
00889 char **azResult;
00890 int nRow, rc;
00891 char *zErrMsg;
00892 open_db(p);
00893 if( nArg==1 ){
00894 rc = sqlite_get_table(p->db,
00895 "SELECT name FROM sqlite_master "
00896 "WHERE type IN ('table','view') "
00897 "UNION ALL "
00898 "SELECT name FROM sqlite_temp_master "
00899 "WHERE type IN ('table','view') "
00900 "ORDER BY 1",
00901 &azResult, &nRow, 0, &zErrMsg
00902 );
00903 }else{
00904 rc = sqlite_get_table_printf(p->db,
00905 "SELECT name FROM sqlite_master "
00906 "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
00907 "UNION ALL "
00908 "SELECT name FROM sqlite_temp_master "
00909 "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
00910 "ORDER BY 1",
00911 &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1]
00912 );
00913 }
00914 if( zErrMsg ){
00915 fprintf(stderr,"Error: %s\n", zErrMsg);
00916 sqlite_freemem(zErrMsg);
00917 }
00918 if( rc==SQLITE_OK ){
00919 int len, maxlen = 0;
00920 int i, j;
00921 int nPrintCol, nPrintRow;
00922 for(i=1; i<=nRow; i++){
00923 if( azResult[i]==0 ) continue;
00924 len = strlen(azResult[i]);
00925 if( len>maxlen ) maxlen = len;
00926 }
00927 nPrintCol = 80/(maxlen+2);
00928 if( nPrintCol<1 ) nPrintCol = 1;
00929 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
00930 for(i=0; i<nPrintRow; i++){
00931 for(j=i+1; j<=nRow; j+=nPrintRow){
00932 char *zSp = j<=nPrintRow ? "" : " ";
00933 printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
00934 }
00935 printf("\n");
00936 }
00937 }
00938 sqlite_free_table(azResult);
00939 }else
00940
00941 if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
00942 open_db(p);
00943 sqlite_busy_timeout(p->db, atoi(azArg[1]));
00944 }else
00945
00946 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
00947 int j;
00948 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
00949 p->colWidth[j-1] = atoi(azArg[j]);
00950 }
00951 }else
00952
00953 {
00954 fprintf(stderr, "unknown command or invalid arguments: "
00955 " \"%s\". Enter \".help\" for help\n", azArg[0]);
00956 }
00957
00958 return rc;
00959 }
00960
00961
00962
00963
00964
00965 static int _ends_with_semicolon(const char *z, int N){
00966 while( N>0 && isspace(z[N-1]) ){ N--; }
00967 return N>0 && z[N-1]==';';
00968 }
00969
00970
00971
00972
00973 static int _all_whitespace(const char *z){
00974 for(; *z; z++){
00975 if( isspace(*z) ) continue;
00976 if( *z=='/' && z[1]=='*' ){
00977 z += 2;
00978 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
00979 if( *z==0 ) return 0;
00980 z++;
00981 continue;
00982 }
00983 if( *z=='-' && z[1]=='-' ){
00984 z += 2;
00985 while( *z && *z!='\n' ){ z++; }
00986 if( *z==0 ) return 1;
00987 continue;
00988 }
00989 return 0;
00990 }
00991 return 1;
00992 }
00993
00994
00995
00996
00997
00998
00999 static int _is_command_terminator(const char *zLine){
01000 extern int sqliteStrNICmp(const char*,const char*,int);
01001 while( isspace(*zLine) ){ zLine++; };
01002 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1;
01003 if( sqliteStrNICmp(zLine,"go",2)==0 && _all_whitespace(&zLine[2]) ){
01004 return 1;
01005 }
01006 return 0;
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016 static void process_input(struct callback_data *p, FILE *in){
01017 char *zLine;
01018 char *zSql = 0;
01019 int nSql = 0;
01020 char *zErrMsg;
01021 int rc;
01022 while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
01023 if( seenInterrupt ){
01024 if( in!=0 ) break;
01025 seenInterrupt = 0;
01026 }
01027 if( p->echoOn ) printf("%s\n", zLine);
01028 if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
01029 if( zLine && zLine[0]=='.' && nSql==0 ){
01030 int rc = do_meta_command(zLine, p);
01031 free(zLine);
01032 if( rc ) break;
01033 continue;
01034 }
01035 if( _is_command_terminator(zLine) ){
01036 strcpy(zLine,";");
01037 }
01038 if( zSql==0 ){
01039 int i;
01040 for(i=0; zLine[i] && isspace(zLine[i]); i++){}
01041 if( zLine[i]!=0 ){
01042 nSql = strlen(zLine);
01043 zSql = malloc( nSql+1 );
01044 strcpy(zSql, zLine);
01045 }
01046 }else{
01047 int len = strlen(zLine);
01048 zSql = realloc( zSql, nSql + len + 2 );
01049 if( zSql==0 ){
01050 fprintf(stderr,"%s: out of memory!\n", Argv0);
01051 exit(1);
01052 }
01053 strcpy(&zSql[nSql++], "\n");
01054 strcpy(&zSql[nSql], zLine);
01055 nSql += len;
01056 }
01057 free(zLine);
01058 if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite_complete(zSql) ){
01059 p->cnt = 0;
01060 open_db(p);
01061 rc = sqlite_exec(p->db, zSql, callback, p, &zErrMsg);
01062 if( rc || zErrMsg ){
01063 if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
01064 if( zErrMsg!=0 ){
01065 printf("SQL error: %s\n", zErrMsg);
01066 sqlite_freemem(zErrMsg);
01067 zErrMsg = 0;
01068 }else{
01069 printf("SQL error: %s\n", sqlite_error_string(rc));
01070 }
01071 }
01072 free(zSql);
01073 zSql = 0;
01074 nSql = 0;
01075 }
01076 }
01077 if( zSql ){
01078 if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
01079 free(zSql);
01080 }
01081 }
01082
01083
01084
01085
01086
01087
01088
01089 static char *find_home_dir(void){
01090 char *home_dir = NULL;
01091
01092 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
01093 struct passwd *pwent;
01094 uid_t uid = getuid();
01095 if( (pwent=getpwuid(uid)) != NULL) {
01096 home_dir = pwent->pw_dir;
01097 }
01098 #endif
01099
01100 #ifdef __MACOS__
01101 char home_path[_MAX_PATH+1];
01102 home_dir = getcwd(home_path, _MAX_PATH);
01103 #endif
01104
01105 if (!home_dir) {
01106 home_dir = getenv("HOME");
01107 if (!home_dir) {
01108 home_dir = getenv("HOMEPATH");
01109 }
01110 }
01111
01112 #if defined(_WIN32) || defined(WIN32)
01113 if (!home_dir) {
01114 home_dir = "c:";
01115 }
01116 #endif
01117
01118 if( home_dir ){
01119 char *z = malloc( strlen(home_dir)+1 );
01120 if( z ) strcpy(z, home_dir);
01121 home_dir = z;
01122 }
01123
01124 return home_dir;
01125 }
01126
01127
01128
01129
01130
01131 static void process_sqliterc(
01132 struct callback_data *p,
01133 const char *sqliterc_override
01134 ){
01135 char *home_dir = NULL;
01136 const char *sqliterc = sqliterc_override;
01137 char *zBuf;
01138 FILE *in = NULL;
01139
01140 if (sqliterc == NULL) {
01141 home_dir = find_home_dir();
01142 if( home_dir==0 ){
01143 fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
01144 return;
01145 }
01146 zBuf = malloc(strlen(home_dir) + 15);
01147 if( zBuf==0 ){
01148 fprintf(stderr,"%s: out of memory!\n", Argv0);
01149 exit(1);
01150 }
01151 sprintf(zBuf,"%s/.sqliterc",home_dir);
01152 free(home_dir);
01153 sqliterc = (const char*)zBuf;
01154 }
01155 in = fopen(sqliterc,"rb");
01156 if( in ){
01157 if( isatty(fileno(stdout)) ){
01158 printf("Loading resources from %s\n",sqliterc);
01159 }
01160 process_input(p,in);
01161 fclose(in);
01162 }
01163 return;
01164 }
01165
01166
01167
01168
01169 static const char zOptions[] =
01170 " -init filename read/process named file\n"
01171 " -echo print commands before execution\n"
01172 " -[no]header turn headers on or off\n"
01173 " -column set output mode to 'column'\n"
01174 " -html set output mode to HTML\n"
01175 #ifdef SQLITE_HAS_CODEC
01176 " -key KEY encryption key\n"
01177 #endif
01178 " -line set output mode to 'line'\n"
01179 " -list set output mode to 'list'\n"
01180 " -separator 'x' set output field separator (|)\n"
01181 " -nullvalue 'text' set text string for NULL values\n"
01182 " -version show SQLite version\n"
01183 " -help show this text, also show dot-commands\n"
01184 ;
01185 static void usage(int showDetail){
01186 fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0);
01187 if( showDetail ){
01188 fprintf(stderr, "Options are:\n%s", zOptions);
01189 }else{
01190 fprintf(stderr, "Use the -help option for additional information\n");
01191 }
01192 exit(1);
01193 }
01194
01195
01196
01197
01198 void main_init(struct callback_data *data) {
01199 memset(data, 0, sizeof(*data));
01200 data->mode = MODE_List;
01201 strcpy(data->separator,"|");
01202 data->showHeader = 0;
01203 strcpy(mainPrompt,"sqlite> ");
01204 strcpy(continuePrompt," ...> ");
01205 }
01206
01207 int main(int argc, char **argv){
01208 char *zErrMsg = 0;
01209 struct callback_data data;
01210 const char *zInitFile = 0;
01211 char *zFirstCmd = 0;
01212 int i;
01213 extern int sqliteOsFileExists(const char*);
01214
01215 #ifdef __MACOS__
01216 argc = ccommand(&argv);
01217 #endif
01218
01219 Argv0 = argv[0];
01220 main_init(&data);
01221
01222
01223
01224
01225 #ifdef SIGINT
01226 signal(SIGINT, interrupt_handler);
01227 #endif
01228
01229
01230
01231
01232
01233 for(i=1; i<argc-1; i++){
01234 if( argv[i][0]!='-' ) break;
01235 if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
01236 i++;
01237 }else if( strcmp(argv[i],"-init")==0 ){
01238 i++;
01239 zInitFile = argv[i];
01240 }else if( strcmp(argv[i],"-key")==0 ){
01241 i++;
01242 data.zKey = sqlite_mprintf("%s",argv[i]);
01243 }
01244 }
01245 if( i<argc ){
01246 data.zDbFilename = argv[i++];
01247 }else{
01248 data.zDbFilename = ":memory:";
01249 }
01250 if( i<argc ){
01251 zFirstCmd = argv[i++];
01252 }
01253 data.out = stdout;
01254
01255
01256
01257
01258
01259
01260 if( sqliteOsFileExists(data.zDbFilename) ){
01261 open_db(&data);
01262 }
01263
01264
01265
01266
01267
01268 process_sqliterc(&data,zInitFile);
01269
01270
01271
01272
01273
01274
01275 for(i=1; i<argc && argv[i][0]=='-'; i++){
01276 char *z = argv[i];
01277 if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){
01278 i++;
01279 }else if( strcmp(z,"-html")==0 ){
01280 data.mode = MODE_Html;
01281 }else if( strcmp(z,"-list")==0 ){
01282 data.mode = MODE_List;
01283 }else if( strcmp(z,"-line")==0 ){
01284 data.mode = MODE_Line;
01285 }else if( strcmp(z,"-column")==0 ){
01286 data.mode = MODE_Column;
01287 }else if( strcmp(z,"-separator")==0 ){
01288 i++;
01289 sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
01290 }else if( strcmp(z,"-nullvalue")==0 ){
01291 i++;
01292 sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
01293 }else if( strcmp(z,"-header")==0 ){
01294 data.showHeader = 1;
01295 }else if( strcmp(z,"-noheader")==0 ){
01296 data.showHeader = 0;
01297 }else if( strcmp(z,"-echo")==0 ){
01298 data.echoOn = 1;
01299 }else if( strcmp(z,"-version")==0 ){
01300 printf("%s\n", sqlite_version);
01301 return 1;
01302 }else if( strcmp(z,"-help")==0 ){
01303 usage(1);
01304 }else{
01305 fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
01306 fprintf(stderr,"Use -help for a list of options.\n");
01307 return 1;
01308 }
01309 }
01310
01311 if( zFirstCmd ){
01312
01313
01314 if( zFirstCmd[0]=='.' ){
01315 do_meta_command(zFirstCmd, &data);
01316 exit(0);
01317 }else{
01318 int rc;
01319 open_db(&data);
01320 rc = sqlite_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
01321 if( rc!=0 && zErrMsg!=0 ){
01322 fprintf(stderr,"SQL error: %s\n", zErrMsg);
01323 exit(1);
01324 }
01325 }
01326 }else{
01327
01328
01329 if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
01330 char *zHome;
01331 char *zHistory = 0;
01332 printf(
01333 "SQLite version %s\n"
01334 "Enter \".help\" for instructions\n",
01335 sqlite_version
01336 );
01337 zHome = find_home_dir();
01338 if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
01339 sprintf(zHistory,"%s/.sqlite_history", zHome);
01340 }
01341 if( zHistory ) read_history(zHistory);
01342 process_input(&data, 0);
01343 if( zHistory ){
01344 stifle_history(100);
01345 write_history(zHistory);
01346 }
01347 }else{
01348 process_input(&data, stdin);
01349 }
01350 }
01351 set_table_name(&data, 0);
01352 if( db ) sqlite_close(db);
01353 return 0;
01354 }