diff options
author | Alex Naidis <alex.naidis@linux.com> | 2017-05-24 19:25:14 +0200 |
---|---|---|
committer | Alex Naidis <alex.naidis@linux.com> | 2017-05-28 18:52:31 +0200 |
commit | b94ea7b498a753b88afce0b6c54ce0f08095f03e (patch) | |
tree | d806c1b6c3e6c607e77463fb91996aaad1ce49c3 /dist/orig/shell.c | |
parent | 8ca8b9cc892211491a2f04688404316e240d64d7 (diff) |
sqlite: Upgrade to SQLite 3.19.2
Downloaded from https://sqlite.org/2017/sqlite-amalgamation-3190200.zip
$ sha256sum sqlite-amalgamation-3190200.zip
c85282af6ef30538dfc74d1814c87547df8588d970b9360cadd66d096bcfd20a sqlite-amalgamation-3190200.zip
dist/orig contains the stock sqlite3 code, as packaged in the ZIP file above.
dist contains a copy of dist/orig, but with the Android.patch file applied.
Please see Android.patch for a list of differences between stock and
Android.
The Android specific patch applied cleanly and was regenerated.
3.19.0 is a regular maintenance release which contains performance
improvements to the query planner and some non-critical bug fixes.
3.19.1 is a high-priority bugfix release which fixes a critical regression.
3.19.2 is another high-priority bugfix release which fixes the regression
described in bug 62025391.
More details about the release are available here: https://sqlite.org/releaselog/3_19_2.html
Change-Id: Ifb8b0fd23e6306b576c2c947dcab45d811e4becb
Signed-off-by: Alex Naidis <alex.naidis@linux.com>
Diffstat (limited to 'dist/orig/shell.c')
-rw-r--r-- | dist/orig/shell.c | 255 |
1 files changed, 192 insertions, 63 deletions
diff --git a/dist/orig/shell.c b/dist/orig/shell.c index 1236b12..d36f1fd 100644 --- a/dist/orig/shell.c +++ b/dist/orig/shell.c @@ -427,6 +427,36 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ } #endif +/* +** Output string zUtf to stream pOut as w characters. If w is negative, +** then right-justify the text. W is the width in UTF-8 characters, not +** in bytes. This is different from the %*.*s specification in printf +** since with %*.*s the width is measured in bytes, not characters. +*/ +static void utf8_width_print(FILE *pOut, int w, const char *zUtf){ + int i; + int n; + int aw = w<0 ? -w : w; + char zBuf[1000]; + if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3; + for(i=n=0; zUtf[i]; i++){ + if( (zUtf[i]&0xc0)!=0x80 ){ + n++; + if( n==aw ){ + do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); + break; + } + } + } + if( n>=aw ){ + utf8_printf(pOut, "%.*s", i, zUtf); + }else if( w<0 ){ + utf8_printf(pOut, "%*s%s", aw-n, "", zUtf); + }else{ + utf8_printf(pOut, "%s%*s", zUtf, aw-n, ""); + } +} + /* ** Determines if a string is a number of not. @@ -714,6 +744,10 @@ struct SHA3Context { unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ }; +/* Allow the following routine to use the B0 variable, which is also +** a macro in the termios.h header file */ +#undef B0 + /* ** A single step of the Keccak mixing function for a 1600-bit state */ @@ -1489,53 +1523,124 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ } /* +** Find a string that is not found anywhere in z[]. Return a pointer +** to that string. +** +** Try to use zA and zB first. If both of those are already found in z[] +** then make up some string and store it in the buffer zBuf. +*/ +static const char *unused_string( + const char *z, /* Result must not appear anywhere in z */ + const char *zA, const char *zB, /* Try these first */ + char *zBuf /* Space to store a generated string */ +){ + unsigned i = 0; + if( strstr(z, zA)==0 ) return zA; + if( strstr(z, zB)==0 ) return zB; + do{ + sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++); + }while( strstr(z,zBuf)!=0 ); + return zBuf; +} + +/* ** Output the given string as a quoted string using SQL quoting conventions. ** -** The "\n" and "\r" characters are converted to char(10) and char(13) -** to prevent them from being transformed by end-of-line translators. +** See also: output_quoted_escaped_string() */ static void output_quoted_string(FILE *out, const char *z){ int i; char c; setBinaryMode(out, 1); - for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} + for(i=0; (c = z[i])!=0 && c!='\''; i++){} if( c==0 ){ utf8_printf(out,"'%s'",z); }else{ - int inQuote = 0; - int bStarted = 0; + raw_printf(out, "'"); while( *z ){ - for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){} + for(i=0; (c = z[i])!=0 && c!='\''; i++){} if( c=='\'' ) i++; if( i ){ - if( !inQuote ){ - if( bStarted ) raw_printf(out, "||"); - raw_printf(out, "'"); - inQuote = 1; - } utf8_printf(out, "%.*s", i, z); z += i; - bStarted = 1; } if( c=='\'' ){ raw_printf(out, "'"); continue; } - if( inQuote ){ + if( c==0 ){ + break; + } + z++; + } + raw_printf(out, "'"); + } + setTextMode(out, 1); +} + +/* +** Output the given string as a quoted string using SQL quoting conventions. +** Additionallly , escape the "\n" and "\r" characters so that they do not +** get corrupted by end-of-line translation facilities in some operating +** systems. +** +** This is like output_quoted_string() but with the addition of the \r\n +** escape mechanism. +*/ +static void output_quoted_escaped_string(FILE *out, const char *z){ + int i; + char c; + setBinaryMode(out, 1); + for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){} + if( c==0 ){ + utf8_printf(out,"'%s'",z); + }else{ + const char *zNL = 0; + const char *zCR = 0; + int nNL = 0; + int nCR = 0; + char zBuf1[20], zBuf2[20]; + for(i=0; z[i]; i++){ + if( z[i]=='\n' ) nNL++; + if( z[i]=='\r' ) nCR++; + } + if( nNL ){ + raw_printf(out, "replace("); + zNL = unused_string(z, "\\n", "\\012", zBuf1); + } + if( nCR ){ + raw_printf(out, "replace("); + zCR = unused_string(z, "\\r", "\\015", zBuf2); + } + raw_printf(out, "'"); + while( *z ){ + for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){} + if( c=='\'' ) i++; + if( i ){ + utf8_printf(out, "%.*s", i, z); + z += i; + } + if( c=='\'' ){ raw_printf(out, "'"); - inQuote = 0; + continue; } if( c==0 ){ break; } - for(i=0; (c = z[i])=='\r' || c=='\n'; i++){ - if( bStarted ) raw_printf(out, "||"); - raw_printf(out, "char(%d)", c); - bStarted = 1; + z++; + if( c=='\n' ){ + raw_printf(out, "%s", zNL); + continue; } - z += i; + raw_printf(out, "%s", zCR); + } + raw_printf(out, "'"); + if( nCR ){ + raw_printf(out, ",'%s',char(13))", zCR); + } + if( nNL ){ + raw_printf(out, ",'%s',char(10))", zNL); } - if( inQuote ) raw_printf(out, "'"); } setTextMode(out, 1); } @@ -1807,13 +1912,8 @@ static int shell_callback( p->actualWidth[i] = w; } if( showHdr ){ - if( w<0 ){ - utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], - i==nArg-1 ? rowSep : " "); - }else{ - utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], - i==nArg-1 ? rowSep : " "); - } + utf8_width_print(p->out, w, azCol[i]); + utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " "); } } if( showHdr ){ @@ -1849,15 +1949,8 @@ static int shell_callback( } p->iIndent++; } - if( w<0 ){ - utf8_printf(p->out,"%*.*s%s",-w,-w, - azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? rowSep : " "); - }else{ - utf8_printf(p->out,"%-*.*s%s",w,w, - azArg[i] ? azArg[i] : p->nullValue, - i==nArg-1 ? rowSep : " "); - } + utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue); + utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " "); } break; } @@ -1998,21 +2091,53 @@ static int shell_callback( setTextMode(p->out, 1); break; } - case MODE_Quote: case MODE_Insert: { if( azArg==0 ) break; - if( p->cMode==MODE_Insert ){ - utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); - if( p->showHeader ){ - raw_printf(p->out,"("); - for(i=0; i<nArg; i++){ - char *zSep = i>0 ? ",": ""; - utf8_printf(p->out, "%s%s", zSep, azCol[i]); + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); + if( p->showHeader ){ + raw_printf(p->out,"("); + for(i=0; i<nArg; i++){ + if( i>0 ) raw_printf(p->out, ","); + if( quoteChar(azCol[i]) ){ + char *z = sqlite3_mprintf("\"%w\"", azCol[i]); + utf8_printf(p->out, "%s", z); + sqlite3_free(z); + }else{ + raw_printf(p->out, "%s", azCol[i]); } - raw_printf(p->out,")"); } - raw_printf(p->out," VALUES("); - }else if( p->cnt==0 && p->showHeader ){ + raw_printf(p->out,")"); + } + p->cnt++; + for(i=0; i<nArg; i++){ + raw_printf(p->out, i>0 ? "," : " VALUES("); + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + utf8_printf(p->out,"NULL"); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + output_quoted_escaped_string(p->out, azArg[i]); + }else if( aiType && aiType[i]==SQLITE_INTEGER ){ + utf8_printf(p->out,"%s", azArg[i]); + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); + sqlite3_snprintf(50,z,"%!.20g", r); + raw_printf(p->out, "%s", z); + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + output_hex_blob(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + utf8_printf(p->out,"%s", azArg[i]); + }else{ + output_quoted_escaped_string(p->out, azArg[i]); + } + } + raw_printf(p->out,");\n"); + break; + } + case MODE_Quote: { + if( azArg==0 ) break; + if( p->cnt==0 && p->showHeader ){ for(i=0; i<nArg; i++){ if( i>0 ) raw_printf(p->out, ","); output_quoted_string(p->out, azCol[i]); @@ -2021,32 +2146,29 @@ static int shell_callback( } p->cnt++; for(i=0; i<nArg; i++){ - char *zSep = i>0 ? ",": ""; + if( i>0 ) raw_printf(p->out, ","); if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ - utf8_printf(p->out,"%sNULL",zSep); + utf8_printf(p->out,"NULL"); }else if( aiType && aiType[i]==SQLITE_TEXT ){ - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); output_quoted_string(p->out, azArg[i]); }else if( aiType && aiType[i]==SQLITE_INTEGER ){ - utf8_printf(p->out,"%s%s",zSep, azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_snprintf(50,z,"%!.20g", r); - raw_printf(p->out, "%s%s", zSep, z); + raw_printf(p->out, "%s", z); }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); int nBlob = sqlite3_column_bytes(p->pStmt, i); - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); output_hex_blob(p->out, pBlob, nBlob); }else if( isNumber(azArg[i], 0) ){ - utf8_printf(p->out,"%s%s",zSep, azArg[i]); + utf8_printf(p->out,"%s", azArg[i]); }else{ - if( zSep[0] ) utf8_printf(p->out,"%s",zSep); output_quoted_string(p->out, azArg[i]); } } - raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); + raw_printf(p->out,"\n"); break; } case MODE_Ascii: { @@ -4331,29 +4453,30 @@ static int lintFkeyIndexes( "SELECT " " 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '" " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " - " || fkey_collate_clause(f.[table], f.[to], s.name, f.[from]),' AND ')" + " || fkey_collate_clause(" + " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" ", " " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('" " || group_concat('*=?', ' AND ') || ')'" ", " " s.name || '(' || group_concat(f.[from], ', ') || ')'" ", " - " f.[table] || '(' || group_concat(COALESCE(f.[to], " - " (SELECT name FROM pragma_table_info(f.[table]) WHERE pk=seq+1)" - " )) || ')'" + " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'" ", " " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))" " || ' ON ' || quote(s.name) || '('" " || group_concat(quote(f.[from]) ||" - " fkey_collate_clause(f.[table], f.[to], s.name, f.[from]), ', ')" + " fkey_collate_clause(" + " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')" " || ');'" ", " " f.[table] " - "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f " + "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) " "GROUP BY s.name, f.id " "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)" ; + const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)"; for(i=2; i<nArg; i++){ int n = (int)strlen(azArg[i]); @@ -4402,7 +4525,10 @@ static int lintFkeyIndexes( if( rc!=SQLITE_OK ) break; if( SQLITE_ROW==sqlite3_step(pExplain) ){ const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3); - res = (0==sqlite3_strglob(zGlob, zPlan)); + res = ( + 0==sqlite3_strglob(zGlob, zPlan) + || 0==sqlite3_strglob(zGlobIPK, zPlan) + ); } rc = sqlite3_finalize(pExplain); if( rc!=SQLITE_OK ) break; @@ -4680,6 +4806,7 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ const char *zLike = 0; int i; + int savedShowHeader = p->showHeader; ShellClearFlag(p, SHFLG_PreserveRowid); for(i=1; i<nArg; i++){ if( azArg[i][0]=='-' ){ @@ -4715,6 +4842,7 @@ static int do_meta_command(char *zLine, ShellState *p){ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n"); raw_printf(p->out, "BEGIN TRANSACTION;\n"); p->writableSchema = 0; + p->showHeader = 0; /* Set writable_schema=ON since doing so forces SQLite to initialize ** as much of the schema as it can even if the sqlite_master table is ** corrupt. */ @@ -4756,6 +4884,7 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + p->showHeader = savedShowHeader; }else if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ |