aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c17
-rw-r--r--src/shell.c.in146
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/trigger.c11
4 files changed, 107 insertions, 68 deletions
diff --git a/src/build.c b/src/build.c
index 24f5d3f96..3d0679235 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1408,19 +1408,12 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
#endif
/*
-** Name of the special TEMP trigger used to implement RETURNING. The
-** name begins with "sqlite_" so that it is guaranteed not to collide
-** with any application-generated triggers.
-*/
-#define RETURNING_TRIGGER_NAME "sqlite_returning"
-
-/*
** Clean up the data structures associated with the RETURNING clause.
*/
static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
Hash *pHash;
pHash = &(db->aDb[1].pSchema->trigHash);
- sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+ sqlite3HashInsert(pHash, pRet->zName, 0);
sqlite3ExprListDelete(db, pRet->pReturnEL);
sqlite3DbFree(db, pRet);
}
@@ -1463,7 +1456,9 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
(void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
testcase( pParse->earlyCleanup );
if( db->mallocFailed ) return;
- pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+ sqlite3_snprintf(sizeof(pRet->zName), pRet->zName,
+ "sqlite_returning_%p", pParse);
+ pRet->retTrig.zName = pRet->zName;
pRet->retTrig.op = TK_RETURNING;
pRet->retTrig.tr_tm = TRIGGER_AFTER;
pRet->retTrig.bReturning = 1;
@@ -1474,9 +1469,9 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pRet->retTStep.pTrig = &pRet->retTrig;
pRet->retTStep.pExprList = pList;
pHash = &(db->aDb[1].pSchema->trigHash);
- assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0
+ assert( sqlite3HashFind(pHash, pRet->zName)==0
|| pParse->nErr || pParse->ifNotExists );
- if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig)
==&pRet->retTrig ){
sqlite3OomFault(db);
}
diff --git a/src/shell.c.in b/src/shell.c.in
index b78759c00..395cbd035 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -449,12 +449,20 @@ static int bail_on_error = 0;
*/
static int stdin_is_interactive = 1;
+/*
+** If build is for Windows, without 3rd-party line editing, Console
+** input and output may be done in a UTF-8 compatible way. This is
+** determined by invocation option and OS installed capability.
+*/
#if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \
&& !defined(SHELL_OMIT_WIN_UTF8)
# define SHELL_WIN_UTF8_OPT 1
- static int console_utf8 = sizeof(char*)/4 - 1;
+ static int console_utf8_in = 0;
+ static int console_utf8_out = 0;
+ static int mbcs_opted = 0;
#else
-# define console_utf8 0
+# define console_utf8_in 0
+# define console_utf8_out 0
# define SHELL_WIN_UTF8_OPT 0
#endif
@@ -597,7 +605,7 @@ static struct ConsoleState {
int infsMode; /* Input file stream mode upon shell start */
UINT inCodePage; /* Input code page upon shell start */
UINT outCodePage; /* Output code page upon shell start */
- HANDLE hConsoleIn; /* Console input handle */
+ HANDLE hConsole; /* Console input or output handle */
DWORD consoleMode; /* Console mode upon shell start */
} conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };
@@ -607,49 +615,61 @@ static struct ConsoleState {
/*
** Prepare console, (if known to be a WIN32 console), for UTF-8
-** input (from either typing or suitable paste operations) and for
+** input (from either typing or suitable paste operations) and/or for
** UTF-8 rendering. This may "fail" with a message to stderr, where
** the preparation is not done and common "code page" issues occur.
*/
-static void console_prepare(void){
+static void console_prepare_utf8(void){
HANDLE hCI = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE hCO = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hCC = INVALID_HANDLE_VALUE;
DWORD consoleMode = 0;
- if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR
- && GetConsoleMode( hCI, &consoleMode) ){
- if( !IsValidCodePage(CP_UTF8) ){
- fprintf(stderr, "Cannot use UTF-8 code page.\n");
- console_utf8 = 0;
- return;
- }
- conState.hConsoleIn = hCI;
- conState.consoleMode = consoleMode;
- conState.inCodePage = GetConsoleCP();
- conState.outCodePage = GetConsoleOutputCP();
+ u8 conI = 0, conO = 0;
+
+ console_utf8_in = console_utf8_out = 0;
+ if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR ) conI = 1;
+ if( isatty(1) && GetFileType(hCO)==FILE_TYPE_CHAR ) conO = 1;
+ if( (!conI && !conO) || mbcs_opted ) return;
+ if( conI ) hCC = hCI;
+ else hCC = hCO;
+ if( !IsValidCodePage(CP_UTF8) || !GetConsoleMode( hCC, &consoleMode) ){
+ fprintf(stderr, "Cannot use UTF-8 code page.\n");
+ return;
+ }
+ conState.hConsole = hCC;
+ conState.consoleMode = consoleMode;
+ conState.inCodePage = GetConsoleCP();
+ conState.outCodePage = GetConsoleOutputCP();
+ if( conI ){
+ console_utf8_in = 1;
SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
consoleMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
- SetConsoleMode(conState.hConsoleIn, consoleMode);
+ SetConsoleMode(conState.hConsole, consoleMode);
conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT);
- console_utf8 = 1;
- }else{
- console_utf8 = 0;
+ }
+ if( conO ){
+ console_utf8_out = 1;
+ SetConsoleOutputCP(CP_UTF8);
}
}
/*
-** Undo the effects of console_prepare(), if any.
+** Undo the effects of console_prepare_utf8(), if any.
*/
static void SQLITE_CDECL console_restore(void){
- if( console_utf8 && conState.inCodePage!=0
- && conState.hConsoleIn!=INVALID_HANDLE_VALUE ){
- _setmode(_fileno(stdin), conState.infsMode);
- SetConsoleCP(conState.inCodePage);
- SetConsoleOutputCP(conState.outCodePage);
- SetConsoleMode(conState.hConsoleIn, conState.consoleMode);
+ if( (console_utf8_in||console_utf8_out)
+ && conState.hConsole!=INVALID_HANDLE_VALUE ){
+ if( console_utf8_in ){
+ SetConsoleCP(conState.inCodePage);
+ _setmode(_fileno(stdin), conState.infsMode);
+ }
+ if( console_utf8_out ) SetConsoleOutputCP(conState.outCodePage);
+ SetConsoleMode(conState.hConsole, conState.consoleMode);
/* Avoid multiple calls. */
- conState.hConsoleIn = INVALID_HANDLE_VALUE;
+ conState.hConsole = INVALID_HANDLE_VALUE;
conState.consoleMode = 0;
- console_utf8 = 0;
+ console_utf8_in = 0;
+ console_utf8_out = 0;
}
}
@@ -657,11 +677,11 @@ static void SQLITE_CDECL console_restore(void){
** Collect input like fgets(...) with special provisions for input
** from the Windows console to get around its strange coding issues.
** Defers to plain fgets() when input is not interactive or when the
-** startup option, -utf8, has not been provided or taken effect.
+** UTF-8 input is unavailable or opted out.
*/
static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
if( fin==0 ) fin = stdin;
- if( fin==stdin && stdin_is_interactive && console_utf8 ){
+ if( fin==stdin && stdin_is_interactive && console_utf8_in ){
# define SQLITE_IALIM 150
wchar_t wbuf[SQLITE_IALIM];
int lend = 0;
@@ -674,7 +694,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
? SQLITE_IALIM : (ncmax-1 - noc)/4;
# undef SQLITE_IALIM
DWORD nbr = 0;
- BOOL bRC = ReadConsoleW(conState.hConsoleIn, wbuf, na, &nbr, 0);
+ BOOL bRC = ReadConsoleW(conState.hConsole, wbuf, na, &nbr, 0);
if( !bRC || (noc==0 && nbr==0) ) return 0;
if( nbr > 0 ){
int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
@@ -720,8 +740,8 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
/*
** Render output like fprintf(). Except, if the output is going to the
-** console and if this is running on a Windows machine, and if the -utf8
-** option is unavailable or (available and inactive), translate the
+** console and if this is running on a Windows machine, and if UTF-8
+** output unavailable (or available but opted out), translate the
** output from UTF-8 into MBCS for output through 8-bit stdout stream.
** (With -utf8 active, no translation is needed and must not be done.)
*/
@@ -729,7 +749,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
void utf8_printf(FILE *out, const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
- if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8 ){
+ if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8_out ){
char *z1 = sqlite3_vmprintf(zFormat, ap);
char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
sqlite3_free(z1);
@@ -942,8 +962,8 @@ static char *local_getline(char *zLine, FILE *in){
#if defined(_WIN32) || defined(WIN32)
/* For interactive input on Windows systems, without -utf8,
** translate the multi-byte characterset characters into UTF-8.
- ** This is the translation that predates the -utf8 option. */
- if( stdin_is_interactive && in==stdin && !console_utf8 ){
+ ** This is the translation that predates console UTF-8 input. */
+ if( stdin_is_interactive && in==stdin && !console_utf8_in ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
i64 nTrans = strlen(zTrans)+1;
@@ -12227,12 +12247,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
(void)cmdline_option_value(argc, argv, ++i);
}else if( cli_strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
+ }else if( cli_strcmp(z,"-interactive")==0 ){
+ /* Need to check for interactive override here to so that it can
+ ** affect console setup (for Windows only) and testing thereof.
+ */
+ stdin_is_interactive = 1;
}else if( cli_strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
** informational messages (like from process_sqliterc) before
** we do the actual processing of arguments later in a second pass.
*/
stdin_is_interactive = 0;
+ }else if( cli_strcmp(z,"-utf8")==0 ){
+#if SHELL_WIN_UTF8_OPT
+ mbcs_opted = 0;
+#endif /* SHELL_WIN_UTF8_OPT */
+ }else if( cli_strcmp(z,"-no-utf8")==0 ){
+#if SHELL_WIN_UTF8_OPT
+ mbcs_opted = 1;
+#endif /* SHELL_WIN_UTF8_OPT */
}else if( cli_strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
const char *zSize;
@@ -12372,6 +12405,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}
}
+#if SHELL_WIN_UTF8_OPT
+ /* Get indicated Windows console setup done before running invocation commands. */
+ if( stdin_is_interactive || stdout_is_console ){
+ console_prepare_utf8();
+ }
+ if( !stdin_is_interactive ){
+ setBinaryMode(stdin, 0);
+ }
+#endif
+
if( data.pAuxDb->zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
data.pAuxDb->zDbFilename = ":memory:";
@@ -12498,17 +12541,13 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
8*(int)sizeof(char*));
return 0;
}else if( cli_strcmp(z,"-interactive")==0 ){
- stdin_is_interactive = 1;
+ /* already handled */
}else if( cli_strcmp(z,"-batch")==0 ){
- stdin_is_interactive = 0;
+ /* already handled */
}else if( cli_strcmp(z,"-utf8")==0 ){
-#if SHELL_WIN_UTF8_OPT
- console_utf8 = 1;
-#endif /* SHELL_WIN_UTF8_OPT */
+ /* already handled */
}else if( cli_strcmp(z,"-no-utf8")==0 ){
-#if SHELL_WIN_UTF8_OPT
- console_utf8 = 0;
-#endif /* SHELL_WIN_UTF8_OPT */
+ /* already handled */
}else if( cli_strcmp(z,"-heap")==0 ){
i++;
}else if( cli_strcmp(z,"-pagecache")==0 ){
@@ -12590,14 +12629,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}
data.cMode = data.mode;
}
-#if SHELL_WIN_UTF8_OPT
- if( console_utf8 && stdin_is_interactive ){
- console_prepare();
- }else{
- setBinaryMode(stdin, 0);
- console_utf8 = 0;
- }
-#endif
if( !readStdin ){
/* Run all arguments that do not begin with '-' as if they were separate
@@ -12636,7 +12667,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
const char *zCharset = "";
int nHistory;
#if SHELL_WIN_UTF8_OPT
- if( console_utf8 ) zCharset = " (utf8)";
+ switch( console_utf8_in+2*console_utf8_out ){
+ default: case 0: break;
+ case 1: zCharset = " (utf8 in)"; break;
+ case 2: zCharset = " (utf8 out)"; break;
+ case 3: zCharset = " (utf8 I/O)"; break;
+ }
#endif
printf(
"SQLite version %s %.19s%s\n" /*extra-version-info*/
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b6cc81fba..dbf01dd13 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -4077,6 +4077,7 @@ struct Returning {
int iRetCur; /* Transient table holding RETURNING results */
int nRetCol; /* Number of in pReturnEL after expansion */
int iRetReg; /* Register array for holding a row of RETURNING */
+ char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
};
/*
diff --git a/src/trigger.c b/src/trigger.c
index c4f09a486..97ca249be 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -970,10 +970,17 @@ static void codeReturningTrigger(
SrcList sFrom;
assert( v!=0 );
- if( !pParse->bReturning ) return;
+ if( !pParse->bReturning ){
+ /* This RETURNING trigger must be for a different statement as
+ ** this statement lacks a RETURNING clause. */
+ return;
+ }
assert( db->pParse==pParse );
pReturning = pParse->u1.pReturning;
- assert( pTrigger == &(pReturning->retTrig) );
+ if( pTrigger != &(pReturning->retTrig) ){
+ /* This RETURNING trigger is for a different statement */
+ return;
+ }
memset(&sSelect, 0, sizeof(sSelect));
memset(&sFrom, 0, sizeof(sFrom));
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);