📄 shell.c
字号:
** the table type ("index" or "table") and SQL to create the table.** This routine should print text sufficient to recreate the table.*/static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ struct callback_data *p = (struct callback_data *)pArg; if( nArg!=3 ) return 1; fprintf(p->out, "%s;\n", azArg[2]); if( strcmp(azArg[1],"table")==0 ){ struct callback_data d2; d2 = *p; d2.mode = MODE_Insert; d2.zDestTable = 0; set_table_name(&d2, azArg[0]); sqlite_exec_printf(p->db, "SELECT * FROM '%q'", callback, &d2, 0, azArg[0] ); set_table_name(&d2, 0); } return 0;}/*** Text of a help message*/static char zHelp[] = ".databases List names and files of attached databases\n" ".dump ?TABLE? ... Dump the database in a text format\n" ".echo ON|OFF Turn command echo on or off\n" ".exit Exit this program\n" ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n" ".header(s) ON|OFF Turn display of headers on or off\n" ".help Show this message\n" ".indices TABLE Show names of all indices on TABLE\n" ".mode MODE Set mode to one of \"line(s)\", \"column(s)\", \n" " \"insert\", \"list\", or \"html\"\n" ".mode insert TABLE Generate SQL insert statements for TABLE\n" ".nullvalue STRING Print STRING instead of nothing for NULL data\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".schema ?TABLE? Show the CREATE statements\n" ".separator STRING Change separator string for \"list\" mode\n" ".show Show the current values for various settings\n" ".tables ?PATTERN? List names of tables matching a pattern\n" ".timeout MS Try opening locked tables for MS milliseconds\n" ".width NUM NUM ... Set column widths for \"column\" mode\n";/* Forward reference */static void process_input(struct callback_data *p, FILE *in);/*** Make sure the database is open. If it is not, then open it. If** the database fails to open, print an error message and exit.*/static void open_db(struct callback_data *p){ if( p->db==0 ){ char *zErrMsg = 0; p->db = db = sqlite_open(p->zDbFilename, 0666, &zErrMsg); if( db==0 ){ p->db = db = sqlite_open(p->zDbFilename, 0444, &zErrMsg); if( db==0 ){ if( zErrMsg ){ fprintf(stderr,"Unable to open database \"%s\": %s\n", p->zDbFilename, zErrMsg); }else{ fprintf(stderr,"Unable to open database %s\n", p->zDbFilename); } exit(1); }else{ fprintf(stderr,"Database \"%s\" opened READ ONLY!\n", p->zDbFilename); } } }}/*** If an input line begins with "." then invoke this routine to** process that line.**** Return 1 to exit and 0 to continue.*/static int do_meta_command(char *zLine, struct callback_data *p){ int i = 1; int nArg = 0; int n, c; int rc = 0; char *azArg[50]; /* Parse the input line into tokens. */ while( zLine[i] && nArg<ArraySize(azArg) ){ while( isspace(zLine[i]) ){ i++; } if( zLine[i]=='\'' || zLine[i]=='"' ){ int delim = zLine[i++]; azArg[nArg++] = &zLine[i]; while( zLine[i] && zLine[i]!=delim ){ i++; } if( zLine[i]==delim ){ zLine[i++] = 0; } }else{ azArg[nArg++] = &zLine[i]; while( zLine[i] && !isspace(zLine[i]) ){ i++; } if( zLine[i] ) zLine[i++] = 0; } } /* Process the input line. */ if( nArg==0 ) return rc; n = strlen(azArg[0]); c = azArg[0][0]; if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Column; sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); } }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ char *zErrMsg = 0; open_db(p); fprintf(p->out, "BEGIN TRANSACTION;\n"); if( nArg==1 ){ sqlite_exec(p->db, "SELECT name, type, sql FROM sqlite_master " "WHERE type!='meta' AND sql NOT NULL " "ORDER BY substr(type,2,1), name", dump_callback, p, &zErrMsg ); }else{ int i; for(i=1; i<nArg && zErrMsg==0; i++){ sqlite_exec_printf(p->db, "SELECT name, type, sql FROM sqlite_master " "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL " "ORDER BY substr(type,2,1), name", dump_callback, p, &zErrMsg, azArg[i] ); } } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); }else{ fprintf(p->out, "COMMIT;\n"); } }else if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){ int j; char *z = azArg[1]; int val = atoi(azArg[1]); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } p->echoOn = val; }else if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ rc = 1; }else if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ int j; char *z = nArg>=2 ? azArg[1] : "1"; int val = atoi(z); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } if(val == 1) { if(!p->explainPrev.valid) { p->explainPrev.valid = 1; p->explainPrev.mode = p->mode; p->explainPrev.showHeader = p->showHeader; memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); } /* We could put this code under the !p->explainValid ** condition so that it does not execute if we are already in ** explain mode. However, always executing it allows us an easy ** was to reset to explain mode in case the user previously ** did an .explain followed by a .width, .mode or .header ** command. */ p->mode = MODE_Column; p->showHeader = 1; memset(p->colWidth,0,ArraySize(p->colWidth)); p->colWidth[0] = 4; p->colWidth[1] = 12; p->colWidth[2] = 10; p->colWidth[3] = 10; p->colWidth[4] = 35; }else if (p->explainPrev.valid) { p->explainPrev.valid = 0; p->mode = p->explainPrev.mode; p->showHeader = p->explainPrev.showHeader; memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); } }else if( c=='h' && (strncmp(azArg[0], "header", n)==0 || strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){ int j; char *z = azArg[1]; int val = atoi(azArg[1]); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } p->showHeader = val; }else if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ fprintf(stderr,zHelp); }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; sqlite_exec_printf(p->db, "SELECT name FROM sqlite_master " "WHERE type='index' AND tbl_name LIKE '%q' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type='index' AND tbl_name LIKE '%q' " "ORDER BY 1", callback, &data, &zErrMsg, azArg[1], azArg[1] ); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ int n2 = strlen(azArg[1]); if( strncmp(azArg[1],"line",n2)==0 || strncmp(azArg[1],"lines",n2)==0 ){ p->mode = MODE_Line; }else if( strncmp(azArg[1],"column",n2)==0 || strncmp(azArg[1],"columns",n2)==0 ){ p->mode = MODE_Column; }else if( strncmp(azArg[1],"list",n2)==0 ){ p->mode = MODE_List; }else if( strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( strncmp(azArg[1],"insert",n2)==0 ){ p->mode = MODE_Insert; if( nArg>=3 ){ set_table_name(p, azArg[2]); }else{ set_table_name(p, "table"); } }else { fprintf(stderr,"mode should be on of: column html insert line list\n"); } }else if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->out!=stdout ){ fclose(p->out); } if( strcmp(azArg[1],"stdout")==0 ){ p->out = stdout; strcpy(p->outfile,"stdout"); }else{ p->out = fopen(azArg[1], "w"); if( p->out==0 ){ fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); p->out = stdout; } else { strcpy(p->outfile,azArg[1]); } } }else if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ if( nArg >= 2) { strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); } if( nArg >= 3) { strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); } }else if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ if( p->db ) sqlite_close(p->db); exit(0); }else if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ FILE *alt = fopen(azArg[1], "r"); if( alt==0 ){ fprintf(stderr,"can't open \"%s\"\n", azArg[1]); }else{ process_input(p, alt); fclose(alt); } }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; if( nArg>1 ){ extern int sqliteStrICmp(const char*,const char*); if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){ char *new_argv[2], *new_colv[2]; new_argv[0] = "CREATE TABLE sqlite_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){ char *new_argv[2], *new_colv[2]; new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); }else{ sqlite_exec_printf(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg, azArg[1]); } }else{ sqlite_exec(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " "WHERE type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); } }else if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]); }else if( c=='s' && strncmp(azArg[0], "show", n)==0){ int i; fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue); fprintf(p->out,"%9.9s: %s\n","output", strlen(p->outfile) ? p->outfile : "stdout"); fprintf(p->out,"%9.9s: %s\n","separator", p->separator); fprintf(p->out,"%9.9s: ","width"); for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { fprintf(p->out,"%d ",p->colWidth[i]); } fprintf(p->out,"\n\n"); }else if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ char **azResult; int nRow, rc; char *zErrMsg; open_db(p); if( nArg==1 ){ rc = sqlite_get_table(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg ); }else{ rc = sqlite_get_table_printf(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1] ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); } if( rc==SQLITE_OK ){ int len, maxlen = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -