mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
Begin adding commands to the command-line interface for interacting with
the sessions extension. This is the first check-in of a work-in-progress. FossilOrigin-Name: c2fcf0b9f4bdc48dfc6530bda4f531b94a833207
This commit is contained in:
151
src/shell.c
151
src/shell.c
@@ -432,6 +432,19 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
|
||||
return zResult;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
/*
|
||||
** State information for a single open session
|
||||
*/
|
||||
typedef struct OpenSession OpenSession;
|
||||
struct OpenSession {
|
||||
char *zName; /* Symbolic name for this session */
|
||||
int nFilter; /* Number of xFilter rejection GLOB patterns */
|
||||
char **azFilter; /* Array of xFilter rejection GLOB patterns */
|
||||
sqlite3_session *p; /* The open session */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Shell output mode information from before ".explain on",
|
||||
** saved so that it can be restored by ".explain off"
|
||||
@@ -479,6 +492,10 @@ struct ShellState {
|
||||
int *aiIndent; /* Array of indents used in MODE_Explain */
|
||||
int nIndent; /* Size of array aiIndent[] */
|
||||
int iIndent; /* Index of current op in aiIndent[] */
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
int nSession; /* Number of active sessions */
|
||||
OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1636,6 +1653,9 @@ static char zHelp[] =
|
||||
" LIKE pattern TABLE.\n"
|
||||
".separator STRING ?NL? Change separator used by output mode and .import\n"
|
||||
" NL is the end-of-line mark for CSV\n"
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
".session CMD ... Create or control sessions\n"
|
||||
#endif
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
".show Show the current values for various settings\n"
|
||||
".stats on|off Turn stats on or off\n"
|
||||
@@ -1651,6 +1671,30 @@ static char zHelp[] =
|
||||
" Negative values right-justify\n"
|
||||
;
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
/*
|
||||
** Print help information for the ".sessions" command
|
||||
*/
|
||||
void session_help(ShellState *p){
|
||||
fprintf(p->out,
|
||||
".session ?NAME? SUBCOMMAND ?ARGS...?\n"
|
||||
"If ?NAME? is omitted, the first defined session is used.\n"
|
||||
"Subcommands:\n"
|
||||
" attach TABLE Attach TABLE\n"
|
||||
" changeset FILE Write a changeset into FILE\n"
|
||||
" close Close one session\n"
|
||||
" enable ?BOOLEAN? Set or query the enable bit\n"
|
||||
" filter GLOB... Reject tables matching GLOBs\n"
|
||||
" indirect ?BOOLEAN? Mark or query the indirect status\n"
|
||||
" isempty Query whether the session is empty\n"
|
||||
" list List currently open session names\n"
|
||||
" open DB NAME Open a new session on DB\n"
|
||||
" patchset FILE Write a patchset into FILE\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Forward reference */
|
||||
static int process_input(ShellState *p, FILE *in);
|
||||
/*
|
||||
@@ -1714,6 +1758,36 @@ static void writefileFunc(
|
||||
sqlite3_result_int64(context, rc);
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
/*
|
||||
** Close a single OpenSession object and release all of its associated
|
||||
** resources.
|
||||
*/
|
||||
static void session_close(OpenSession *pSession){
|
||||
int i;
|
||||
sqlite3session_delete(pSession->p);
|
||||
sqlite3_free(pSession->zName);
|
||||
for(i=0; i<pSession->nFilter; i++){
|
||||
sqlite3_free(pSession->azFilter[i]);
|
||||
}
|
||||
sqlite3_free(pSession->azFilter);
|
||||
memset(pSession, 0, sizeof(OpenSession));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Close all OpenSession objects and release all assocaited resources.
|
||||
*/
|
||||
static void session_close_all(ShellState *p){
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
int i;
|
||||
for(i=0; i<p->nSession; i++){
|
||||
session_close(&p->aSession[i]);
|
||||
}
|
||||
p->nSession = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** 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.
|
||||
@@ -2865,6 +2939,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
open_db(p, 1);
|
||||
if( p->db!=0 ){
|
||||
session_close_all(p);
|
||||
sqlite3_close(savedDb);
|
||||
sqlite3_free(p->zFreeOnClose);
|
||||
p->zFreeOnClose = zNewFilename;
|
||||
@@ -3086,6 +3161,81 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
|
||||
OpenSession *pSession = &p->aSession[0];
|
||||
char **azCmd = &azArg[1];
|
||||
int iSes = 0;
|
||||
int nCmd = nArg - 1;
|
||||
int i;
|
||||
if( nArg<=1 ) goto session_syntax_error;
|
||||
if( nArg>=3 ){
|
||||
for(iSes=0; iSes<p->nSession; iSes++){
|
||||
if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
|
||||
}
|
||||
if( iSes<p->nSession ){
|
||||
pSession = &p->aSession[iSes];
|
||||
azCmd++;
|
||||
nCmd--;
|
||||
}else{
|
||||
pSession = &p->aSession[0];
|
||||
iSes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* .session close
|
||||
** Close the identified session
|
||||
*/
|
||||
if( strcmp(azCmd[0], "close")==0 ){
|
||||
if( p->nSession ){
|
||||
session_close(pSession);
|
||||
p->aSession[iSes] = p->aSession[--p->nSession];
|
||||
}
|
||||
}else
|
||||
|
||||
/* .session list
|
||||
** List all currently open sessions
|
||||
*/
|
||||
if( strcmp(azCmd[0],"list")==0 ){
|
||||
for(i=0; i<p->nSession; i++){
|
||||
fprintf(p->out, "%d %s\n", i, p->aSession[i].zName);
|
||||
}
|
||||
}else
|
||||
|
||||
/* .session open DB NAME
|
||||
** Open a new session called NAME on the attached database DB.
|
||||
** DB is normally "main".
|
||||
*/
|
||||
if( strcmp(azCmd[0],"open")==0 ){
|
||||
char *zName;
|
||||
if( nCmd!=3 ) goto session_syntax_error;
|
||||
zName = azCmd[2];
|
||||
if( zName[0]==0 ) goto session_syntax_error;
|
||||
for(i=0; i<p->nSession; i++){
|
||||
if( strcmp(p->aSession[i].zName,zName)==0 ){
|
||||
fprintf(stderr, "Session \"%s\" already exists\n", zName);
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}
|
||||
if( p->nSession>=ArraySize(p->aSession) ){
|
||||
fprintf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
|
||||
goto meta_command_exit;
|
||||
}
|
||||
pSession = &p->aSession[p->nSession];
|
||||
rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Cannot open session: error code=%d\n", rc);
|
||||
goto meta_command_exit;
|
||||
}
|
||||
p->nSession++;
|
||||
pSession->zName = sqlite3_mprintf("%s", zName);
|
||||
}else
|
||||
/* If no command name matches, show a syntax error */
|
||||
session_syntax_error:
|
||||
session_help(p);
|
||||
}else
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Undocumented commands for internal testing. Subject to change
|
||||
** without notice. */
|
||||
@@ -4134,6 +4284,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
set_table_name(&data, 0);
|
||||
if( data.db ){
|
||||
session_close_all(&data);
|
||||
sqlite3_close(data.db);
|
||||
}
|
||||
sqlite3_free(data.zFreeOnClose);
|
||||
|
||||
Reference in New Issue
Block a user