in fdbserver/sqlite/shell.c [1471:2361]
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((unsigned char)zLine[i])) {
i++;
}
if (zLine[i] == 0)
break;
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;
}
if (delim == '"')
resolve_backslashes(azArg[nArg - 1]);
} else {
azArg[nArg++] = &zLine[i];
while (zLine[i] && !isspace((unsigned char)zLine[i])) {
i++;
}
if (zLine[i])
zLine[i++] = 0;
resolve_backslashes(azArg[nArg - 1]);
}
}
/* Process the input line.
*/
if (nArg == 0)
return 0; /* no tokens, no error */
n = strlen30(azArg[0]);
c = azArg[0][0];
if (c == 'b' && n >= 3 && strncmp(azArg[0], "backup", n) == 0 && nArg > 1 && nArg < 4) {
const char* zDestFile;
const char* zDb;
sqlite3* pDest;
sqlite3_backup* pBackup;
if (nArg == 2) {
zDestFile = azArg[1];
zDb = "main";
} else {
zDestFile = azArg[2];
zDb = azArg[1];
}
rc = sqlite3_open(zDestFile, &pDest);
if (rc != SQLITE_OK) {
fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
sqlite3_close(pDest);
return 1;
}
open_db(p);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if (pBackup == 0) {
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
sqlite3_close(pDest);
return 1;
}
while ((rc = sqlite3_backup_step(pBackup, 100)) == SQLITE_OK) {
}
sqlite3_backup_finish(pBackup);
if (rc == SQLITE_DONE) {
rc = 0;
} else {
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
rc = 1;
}
sqlite3_close(pDest);
} else
if (c == 'b' && n >= 3 && strncmp(azArg[0], "bail", n) == 0 && nArg > 1 && nArg < 3) {
bail_on_error = booleanValue(azArg[1]);
} else
if (c == 'd' && n > 1 && strncmp(azArg[0], "databases", n) == 0 && nArg == 1) {
struct callback_data data;
char* zErrMsg = 0;
open_db(p);
memcpy(&data, p, sizeof(data));
data.showHeader = 1;
data.mode = MODE_Column;
data.colWidth[0] = 3;
data.colWidth[1] = 15;
data.colWidth[2] = 58;
data.cnt = 0;
sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
if (zErrMsg) {
fprintf(stderr, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
} else
if (c == 'd' && strncmp(azArg[0], "dump", n) == 0 && nArg < 3) {
char* zErrMsg = 0;
open_db(p);
/* When playing back a "dump", the content might appear in an order
** which causes immediate foreign key constraints to be violated.
** So disable foreign-key constraint enforcement to prevent problems. */
fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
fprintf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0);
if (nArg == 1) {
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
0);
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE name=='sqlite_sequence'",
0);
run_table_dump_query(p->out,
p->db,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')",
0);
} else {
int i;
for (i = 1; i < nArg; i++) {
zShellStatic = azArg[i];
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
" AND sql NOT NULL",
0);
run_table_dump_query(p->out,
p->db,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL"
" AND type IN ('index','trigger','view')"
" AND tbl_name LIKE shellstatic()",
0);
zShellStatic = 0;
}
}
if (p->writableSchema) {
fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
p->writableSchema = 0;
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0);
if (zErrMsg) {
fprintf(stderr, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(p->out, "COMMIT;\n");
}
} else
if (c == 'e' && strncmp(azArg[0], "echo", n) == 0 && nArg > 1 && nArg < 3) {
p->echoOn = booleanValue(azArg[1]);
} else
if (c == 'e' && strncmp(azArg[0], "exit", n) == 0 && nArg == 1) {
rc = 2;
} else
if (c == 'e' && strncmp(azArg[0], "explain", n) == 0 && nArg < 3) {
int val = nArg >= 2 ? booleanValue(azArg[1]) : 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_Explain;
p->showHeader = 1;
memset(p->colWidth, 0, ArraySize(p->colWidth));
p->colWidth[0] = 4; /* addr */
p->colWidth[1] = 13; /* opcode */
p->colWidth[2] = 4; /* P1 */
p->colWidth[3] = 4; /* P2 */
p->colWidth[4] = 4; /* P3 */
p->colWidth[5] = 13; /* P4 */
p->colWidth[6] = 2; /* P5 */
p->colWidth[7] = 13; /* Comment */
} 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 &&
nArg < 3) {
p->showHeader = booleanValue(azArg[1]);
} else
if (c == 'h' && strncmp(azArg[0], "help", n) == 0) {
fprintf(stderr, "%s", zHelp);
if (HAS_TIMER) {
fprintf(stderr, "%s", zTimerHelp);
}
} else
if (c == 'i' && strncmp(azArg[0], "import", n) == 0 && nArg == 3) {
char* zTable = azArg[2]; /* Insert data into this table */
char* zFile = azArg[1]; /* The file from which to extract data */
sqlite3_stmt* pStmt = NULL; /* A statement */
int nCol; /* Number of columns in the table */
int nByte; /* Number of bytes in an SQL string */
int i, j; /* Loop counters */
int nSep; /* Number of bytes in p->separator[] */
char* zSql; /* An SQL statement */
char* zLine; /* A single line of input from the file */
char** azCol; /* zLine[] broken up into columns */
char* zCommit; /* How to commit changes */
FILE* in; /* The input file */
int lineno = 0; /* Line number of input file */
open_db(p);
nSep = strlen30(p->separator);
if (nSep == 0) {
fprintf(stderr, "Error: non-null separator required for import\n");
return 1;
}
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if (zSql == 0) {
fprintf(stderr, "Error: out of memory\n");
return 1;
}
nByte = strlen30(zSql);
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if (rc) {
if (pStmt)
sqlite3_finalize(pStmt);
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
return 1;
}
nCol = sqlite3_column_count(pStmt);
sqlite3_finalize(pStmt);
pStmt = 0;
if (nCol == 0)
return 0; /* no columns, no error */
zSql = malloc(nByte + 20 + nCol * 2);
if (zSql == 0) {
fprintf(stderr, "Error: out of memory\n");
return 1;
}
sqlite3_snprintf(nByte + 20, zSql, "INSERT INTO '%q' VALUES(?", zTable);
j = strlen30(zSql);
for (i = 1; i < nCol; i++) {
zSql[j++] = ',';
zSql[j++] = '?';
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
free(zSql);
if (rc) {
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
if (pStmt)
sqlite3_finalize(pStmt);
return 1;
}
in = fopen(zFile, "rb");
if (in == 0) {
fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
sqlite3_finalize(pStmt);
return 1;
}
azCol = malloc(sizeof(azCol[0]) * (nCol + 1));
if (azCol == 0) {
fprintf(stderr, "Error: out of memory\n");
fclose(in);
sqlite3_finalize(pStmt);
return 1;
}
sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
zCommit = "COMMIT";
while ((zLine = local_getline(0, in)) != 0) {
char* z;
i = 0;
lineno++;
azCol[0] = zLine;
for (i = 0, z = zLine; *z && *z != '\n' && *z != '\r'; z++) {
if (*z == p->separator[0] && strncmp(z, p->separator, nSep) == 0) {
*z = 0;
i++;
if (i < nCol) {
azCol[i] = &z[nSep];
z += nSep - 1;
}
}
} /* end for */
*z = 0;
if (i + 1 != nCol) {
fprintf(stderr,
"Error: %s line %d: expected %d columns of data but found %d\n",
zFile,
lineno,
nCol,
i + 1);
zCommit = "ROLLBACK";
free(zLine);
rc = 1;
break; /* from while */
}
for (i = 0; i < nCol; i++) {
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; /* from while */
}
} /* end while */
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 < 3) {
struct callback_data data;
char* zErrMsg = 0;
open_db(p);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.mode = MODE_List;
if (nArg == 1) {
rc = sqlite3_exec(p->db,
"SELECT name FROM sqlite_master "
"WHERE type='index' AND name NOT LIKE 'sqlite_%' "
"UNION ALL "
"SELECT name FROM sqlite_temp_master "
"WHERE type='index' "
"ORDER BY 1",
callback,
&data,
&zErrMsg);
} else {
zShellStatic = azArg[1];
rc = 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);
rc = 1;
} else if (rc != SQLITE_OK) {
fprintf(stderr, "Error: querying sqlite_master and sqlite_temp_master\n");
rc = 1;
}
} 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, "Error: cannot open \"%s\"\n", azArg[1]);
sqlite3IoTrace = 0;
rc = 1;
} 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;
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, "Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}
} else
#endif
if (c == 'l' && strncmp(azArg[0], "log", n) == 0 && nArg >= 1) {
const char* zFile = azArg[1];
if (p->pLog && p->pLog != stdout && p->pLog != stderr) {
fclose(p->pLog);
p->pLog = 0;
}
if (strcmp(zFile, "stdout") == 0) {
p->pLog = stdout;
} else if (strcmp(zFile, "stderr") == 0) {
p->pLog = stderr;
} else if (strcmp(zFile, "off") == 0) {
p->pLog = 0;
} else {
p->pLog = fopen(zFile, "w");
if (p->pLog == 0) {
fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
}
}
} else
if (c == 'm' && strncmp(azArg[0], "mode", n) == 0 && nArg == 2) {
int n2 = strlen30(azArg[1]);
if ((n2 == 4 && strncmp(azArg[1], "line", n2) == 0) || (n2 == 5 && strncmp(azArg[1], "lines", n2) == 0)) {
p->mode = MODE_Line;
} else if ((n2 == 6 && strncmp(azArg[1], "column", n2) == 0) ||
(n2 == 7 && strncmp(azArg[1], "columns", n2) == 0)) {
p->mode = MODE_Column;
} else if (n2 == 4 && strncmp(azArg[1], "list", n2) == 0) {
p->mode = MODE_List;
} else if (n2 == 4 && strncmp(azArg[1], "html", n2) == 0) {
p->mode = MODE_Html;
} else if (n2 == 3 && strncmp(azArg[1], "tcl", n2) == 0) {
p->mode = MODE_Tcl;
} else if (n2 == 3 && strncmp(azArg[1], "csv", n2) == 0) {
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
} else if (n2 == 4 && strncmp(azArg[1], "tabs", n2) == 0) {
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
} else if (n2 == 6 && strncmp(azArg[1], "insert", n2) == 0) {
p->mode = MODE_Insert;
set_table_name(p, "table");
} else {
fprintf(stderr,
"Error: mode should be one of: "
"column csv html insert line list tabs tcl\n");
rc = 1;
}
} else
if (c == 'm' && strncmp(azArg[0], "mode", n) == 0 && nArg == 3) {
int n2 = strlen30(azArg[1]);
if (n2 == 6 && strncmp(azArg[1], "insert", n2) == 0) {
p->mode = MODE_Insert;
set_table_name(p, azArg[2]);
} else {
fprintf(stderr,
"Error: invalid arguments: "
" \"%s\". Enter \".help\" for help\n",
azArg[2]);
rc = 1;
}
} 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, "Error: cannot write to \"%s\"\n", azArg[1]);
p->out = stdout;
rc = 1;
} 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 && nArg == 1) {
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, "Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
} else {
rc = process_input(p, alt);
fclose(alt);
}
} else
if (c == 'r' && n >= 3 && strncmp(azArg[0], "restore", n) == 0 && nArg > 1 && nArg < 4) {
const char* zSrcFile;
const char* zDb;
sqlite3* pSrc;
sqlite3_backup* pBackup;
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 = 0;
} else if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
fprintf(stderr, "Error: source database is busy\n");
rc = 1;
} else {
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}
sqlite3_close(pSrc);
} else
if (c == 's' && strncmp(azArg[0], "schema", n) == 0 && nArg < 3) {
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);
rc = SQLITE_OK;
} 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);
rc = SQLITE_OK;
} else {
zShellStatic = azArg[1];
rc = 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 {
rc = 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);
rc = 1;
} else if (rc != SQLITE_OK) {
fprintf(stderr, "Error: querying schema information\n");
rc = 1;
} else {
rc = 0;
}
} 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 && nArg == 1) {
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: %s\n", "stats", p->statsOn ? "on" : "off");
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 == 's' && strncmp(azArg[0], "stats", n) == 0 && nArg > 1 && nArg < 3) {
p->statsOn = booleanValue(azArg[1]);
} else
if (c == 't' && n > 1 && strncmp(azArg[0], "tables", n) == 0 && nArg < 3) {
char** azResult;
int nRow;
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);
rc = 1;
} else if (rc != SQLITE_OK) {
fprintf(stderr, "Error: querying sqlite_master and sqlite_temp_master\n");
rc = 1;
} else {
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");
}
}
sqlite3_free_table(azResult);
} else
if (c == 't' && n >= 8 && strncmp(azArg[0], "testctrl", n) == 0 && nArg >= 2) {
int testctrl = -1;
int rc = 0;
open_db(p);
/* convert testctrl text option to value. allow only the first
** three characters of the option to be used or the numerical
** value. */
if (strncmp(azArg[1], "prng_save", 6) == 0)
testctrl = SQLITE_TESTCTRL_PRNG_SAVE;
else if (strncmp(azArg[1], "prng_restore", 10) == 0)
testctrl = SQLITE_TESTCTRL_PRNG_RESTORE;
else if (strncmp(azArg[1], "prng_reset", 10) == 0)
testctrl = SQLITE_TESTCTRL_PRNG_RESET;
else if (strncmp(azArg[1], "bitvec_test", 6) == 3)
testctrl = SQLITE_TESTCTRL_BITVEC_TEST;
else if (strncmp(azArg[1], "fault_install", 6) == 3)
testctrl = SQLITE_TESTCTRL_FAULT_INSTALL;
else if (strncmp(azArg[1], "benign_malloc_hooks", 3) == 0)
testctrl = SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS;
else if (strncmp(azArg[1], "pending_byte", 3) == 0)
testctrl = SQLITE_TESTCTRL_PENDING_BYTE;
else if (strncmp(azArg[1], "assert", 3) == 0)
testctrl = SQLITE_TESTCTRL_ASSERT;
else if (strncmp(azArg[1], "always", 3) == 0)
testctrl = SQLITE_TESTCTRL_ALWAYS;
else if (strncmp(azArg[1], "reserve", 3) == 0)
testctrl = SQLITE_TESTCTRL_RESERVE;
else if (strncmp(azArg[1], "optimizations", 3) == 0)
testctrl = SQLITE_TESTCTRL_OPTIMIZATIONS;
else if (strncmp(azArg[1], "iskeyword", 3) == 0)
testctrl = SQLITE_TESTCTRL_ISKEYWORD;
else if (strncmp(azArg[1], "pghdrsz", 3) == 0)
testctrl = SQLITE_TESTCTRL_PGHDRSZ;
else if (strncmp(azArg[1], "scratchmalloc", 3) == 0)
testctrl = SQLITE_TESTCTRL_SCRATCHMALLOC;
else
testctrl = atoi(azArg[1]);
if ((testctrl < SQLITE_TESTCTRL_FIRST) || (testctrl > SQLITE_TESTCTRL_LAST)) {
fprintf(stderr, "Error: invalid testctrl option: %s\n", azArg[1]);
} else {
switch (testctrl) {
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
case SQLITE_TESTCTRL_RESERVE:
if (nArg == 3) {
int opt = (int)strtol(azArg[2], 0, 0);
rc = sqlite3_test_control(testctrl, p->db, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr, "Error: testctrl %s takes a single int option\n", azArg[1]);
}
break;
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_PGHDRSZ:
if (nArg == 2) {
rc = sqlite3_test_control(testctrl);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr, "Error: testctrl %s takes no options\n", azArg[1]);
}
break;
/* sqlite3_test_control(int, uint) */
case SQLITE_TESTCTRL_PENDING_BYTE:
if (nArg == 3) {
unsigned int opt = (unsigned int)atoi(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr, "Error: testctrl %s takes a single unsigned int option\n", azArg[1]);
}
break;
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
if (nArg == 3) {
int opt = atoi(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr, "Error: testctrl %s takes a single int option\n", azArg[1]);
}
break;
/* sqlite3_test_control(int, char *) */
#ifdef SQLITE_N_KEYWORD
case SQLITE_TESTCTRL_ISKEYWORD:
if (nArg == 3) {
const char* opt = azArg[2];
rc = sqlite3_test_control(testctrl, opt);
printf("%d (0x%08x)\n", rc, rc);
} else {
fprintf(stderr, "Error: testctrl %s takes a single char * option\n", azArg[1]);
}
break;
#endif
case SQLITE_TESTCTRL_BITVEC_TEST:
case SQLITE_TESTCTRL_FAULT_INSTALL:
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
case SQLITE_TESTCTRL_SCRATCHMALLOC:
default:
fprintf(stderr, "Error: CLI support for testctrl %s not implemented\n", azArg[1]);
break;
}
}
} 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 && c == 't' && n >= 5 && strncmp(azArg[0], "timer", n) == 0 && nArg == 2) {
enableTimer = booleanValue(azArg[1]);
} else
if (c == 'w' && strncmp(azArg[0], "width", n) == 0 && nArg > 1) {
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,
"Error: unknown command or invalid arguments: "
" \"%s\". Enter \".help\" for help\n",
azArg[0]);
rc = 1;
}
return rc;
}