📄 shell.c
字号:
sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); } sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); free(zLine); if( rc!=SQLITE_OK ){ fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); zCommit = "ROLLBACK"; rc = 1; break; } } free(azCol); fclose(in); sqlite3_finalize(pStmt); sqlite3_exec(p->db, zCommit, 0, 0, 0); }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; zShellStatic = azArg[1]; sqlite3_exec(p->db, "SELECT name FROM sqlite_master " "WHERE type='index' AND tbl_name LIKE shellstatic() " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type='index' AND tbl_name LIKE shellstatic() " "ORDER BY 1", callback, &data, &zErrMsg ); zShellStatic = 0; if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } }else#ifdef SQLITE_ENABLE_IOTRACE if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ extern void (*sqlite3IoTrace)(const char*, ...); if( iotrace && iotrace!=stdout ) fclose(iotrace); iotrace = 0; if( nArg<2 ){ sqlite3IoTrace = 0; }else if( strcmp(azArg[1], "-")==0 ){ sqlite3IoTrace = iotracePrintf; iotrace = stdout; }else{ iotrace = fopen(azArg[1], "w"); if( iotrace==0 ){ fprintf(stderr, "cannot open \"%s\"\n", azArg[1]); sqlite3IoTrace = 0; }else{ sqlite3IoTrace = iotracePrintf; } } }else#endif#ifndef SQLITE_OMIT_LOAD_EXTENSION if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ const char *zFile, *zProc; char *zErrMsg = 0; int rc; zFile = azArg[1]; zProc = nArg>=3 ? azArg[2] : 0; open_db(p); rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); if( rc!=SQLITE_OK ){ fprintf(stderr, "%s\n", zErrMsg); sqlite3_free(zErrMsg); rc = 1; } }else#endif if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ int n2 = strlen30(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],"tcl",n2)==0 ){ p->mode = MODE_Tcl; }else if( strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->separator), p->separator, ","); }else if( strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); }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 one of: " "column csv html insert line list tabs tcl\n"); } }else if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { sqlite3_snprintf(sizeof(p->nullvalue), 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; sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); }else{ p->out = fopen(azArg[1], "wb"); if( p->out==0 ){ fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); p->out = stdout; } else { sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", 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 ){ rc = 2; }else if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ FILE *alt = fopen(azArg[1], "rb"); if( alt==0 ){ fprintf(stderr,"can't open \"%s\"\n", azArg[1]); }else{ process_input(p, alt); fclose(alt); } }else if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 ){ const char *zSrcFile; const char *zDb; sqlite3 *pSrc; sqlite3_backup *pBackup; int rc; int nTimeout = 0; if( nArg==2 ){ zSrcFile = azArg[1]; zDb = "main"; }else{ zSrcFile = azArg[2]; zDb = azArg[1]; } rc = sqlite3_open(zSrcFile, &pSrc); if( rc!=SQLITE_OK ){ fprintf(stderr, "Error: cannot open %s\n", zSrcFile); sqlite3_close(pSrc); return 1; } open_db(p); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); sqlite3_close(pSrc); return 1; } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK || rc==SQLITE_BUSY ){ if( rc==SQLITE_BUSY ){ if( nTimeout++ >= 3 ) break; sqlite3_sleep(100); } } sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = SQLITE_OK; }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ fprintf(stderr, "source database is busy\n"); }else{ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); } sqlite3_close(pSrc); }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 ){ int i; for(i=0; azArg[1][i]; i++) azArg[1][i] = (char)tolower(azArg[1][i]); if( strcmp(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( strcmp(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{ zShellStatic = azArg[1]; sqlite3_exec(p->db, "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg); zShellStatic = 0; } }else{ sqlite3_exec(p->db, "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } }else if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sqlite3_snprintf(sizeof(p->separator), p->separator, "%.*s", (int)sizeof(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: ", "nullvalue"); output_c_string(p->out, p->nullvalue); fprintf(p->out, "\n"); fprintf(p->out,"%9.9s: %s\n","output", strlen30(p->outfile) ? p->outfile : "stdout"); fprintf(p->out,"%9.9s: ", "separator"); output_c_string(p->out, p->separator); fprintf(p->out, "\n"); 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"); }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 = sqlite3_get_table(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg ); }else{ zShellStatic = azArg[1]; rc = sqlite3_get_table(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg ); zShellStatic = 0; } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } if( rc==SQLITE_OK ){ int len, maxlen = 0; int i, j; int nPrintCol, nPrintRow; for(i=1; i<=nRow; i++){ if( azResult[i]==0 ) continue; len = strlen30(azResult[i]); if( len>maxlen ) maxlen = len; } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; i<nPrintRow; i++){ for(j=i+1; j<=nRow; j+=nPrintRow){ char *zSp = j<=nPrintRow ? "" : " "; printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); } printf("\n"); } }else{ rc = 1; } sqlite3_free_table(azResult); }else if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ open_db(p); sqlite3_busy_timeout(p->db, atoi(azArg[1])); }else #if HAS_TIMER if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){ enableTimer = booleanValue(azArg[1]); }else#endif if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ int j; assert( nArg<=ArraySize(azArg) ); for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } }else { fprintf(stderr, "unknown command or invalid arguments: " " \"%s\". Enter \".help\" for help\n", azArg[0]); } return rc;}/*** Return TRUE if a semicolon occurs anywhere in the first N characters** of string z[].*/static int _contains_semicolon(const char *z, int N){ int i; for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } return 0;}/*** Test to see if a line consists entirely of whitespace.*/static int _all_whitespace(const char *z){ for(; *z; z++){ if( isspace(*(unsigned char*)z) ) continue; if( *z=='/' && z[1]=='*' ){ z += 2; while( *z && (*z!='*' || z[1]!='/') ){ z++; } if( *z==0 ) return 0; z++; continue; } if( *z=='-' && z[1]=='-' ){ z += 2; while( *z && *z!='\n' ){ z++; } if( *z==0 ) return 1; continue; } return 0; } return 1;}/*** Return TRUE if the line typed in is an SQL command terminator other** than a semi-colon. The SQL Server style "go" command is understood** as is the Oracle "/".*/static int _is_command_terminator(const char *zLine){ while( isspace(*(unsigned char*)zLine) ){ zLine++; }; if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){ return 1; /* Oracle */ } if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o' && _all_whitespace(&zLine[2]) ){ return 1; /* SQL Server */ } return 0;}/*** Return true if zSql is a complete SQL statement. Return false if it** ends in the middle of a string literal or C-style comment.*/static int _is_complete(char *zSql, int nSql){ int rc; if( zSql==0 ) return 1; zSql[nSql] = ';'; zSql[nSql+1] = 0; rc = sqlite3_complete(zSql); zSql[nSql] = 0; return rc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -