| | @@ -590,10 +590,11 @@ |
| 590 | 590 | */ |
| 591 | 591 | typedef struct ShellState ShellState; |
| 592 | 592 | struct ShellState { |
| 593 | 593 | sqlite3 *db; /* The database */ |
| 594 | 594 | int echoOn; /* True to echo input commands */ |
| 595 | + int autoExplain; /* Automatically turn on .explain mode */ |
| 595 | 596 | int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ |
| 596 | 597 | int statsOn; /* True to display memory stats before each finalize */ |
| 597 | 598 | int scanstatsOn; /* True to display scan stats before each finalize */ |
| 598 | 599 | int countChanges; /* True to display change counts */ |
| 599 | 600 | int backslashOn; /* Resolve C-style \x escapes in SQL input text */ |
| | @@ -601,10 +602,12 @@ |
| 601 | 602 | int cnt; /* Number of records displayed so far */ |
| 602 | 603 | FILE *out; /* Write results here */ |
| 603 | 604 | FILE *traceOut; /* Output for sqlite3_trace() */ |
| 604 | 605 | int nErr; /* Number of errors seen */ |
| 605 | 606 | int mode; /* An output mode setting */ |
| 607 | + int cMode; /* temporary output mode for the current query */ |
| 608 | + int normalMode; /* Output mode before ".explain on" */ |
| 606 | 609 | int writableSchema; /* True if PRAGMA writable_schema=ON */ |
| 607 | 610 | int showHeader; /* True to show column names in List or Column mode */ |
| 608 | 611 | unsigned shellFlgs; /* Various flags */ |
| 609 | 612 | char *zDestTable; /* Name of destination table when MODE_Insert */ |
| 610 | 613 | char colSeparator[20]; /* Column separator character for several modes */ |
| | @@ -611,11 +614,10 @@ |
| 611 | 614 | char rowSeparator[20]; /* Row separator character for MODE_Ascii */ |
| 612 | 615 | int colWidth[100]; /* Requested width of each column when in column mode*/ |
| 613 | 616 | int actualWidth[100]; /* Actual width of each column */ |
| 614 | 617 | char nullValue[20]; /* The text to print when a NULL comes back from |
| 615 | 618 | ** the database */ |
| 616 | | - SavedModeInfo normalMode;/* Holds the mode just before .explain ON */ |
| 617 | 619 | char outfile[FILENAME_MAX]; /* Filename for *out */ |
| 618 | 620 | const char *zDbFilename; /* name of the database file */ |
| 619 | 621 | char *zFreeOnClose; /* Filename to free when closing */ |
| 620 | 622 | const char *zVfs; /* Name of VFS to use */ |
| 621 | 623 | sqlite3_stmt *pStmt; /* Current statement if any. */ |
| | @@ -880,11 +882,11 @@ |
| 880 | 882 | int *aiType /* Column types */ |
| 881 | 883 | ){ |
| 882 | 884 | int i; |
| 883 | 885 | ShellState *p = (ShellState*)pArg; |
| 884 | 886 | |
| 885 | | - switch( p->mode ){ |
| 887 | + switch( p->cMode ){ |
| 886 | 888 | case MODE_Line: { |
| 887 | 889 | int w = 5; |
| 888 | 890 | if( azArg==0 ) break; |
| 889 | 891 | for(i=0; i<nArg; i++){ |
| 890 | 892 | int len = strlen30(azCol[i] ? azCol[i] : ""); |
| | @@ -897,15 +899,28 @@ |
| 897 | 899 | } |
| 898 | 900 | break; |
| 899 | 901 | } |
| 900 | 902 | case MODE_Explain: |
| 901 | 903 | case MODE_Column: { |
| 904 | + static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13}; |
| 905 | + const int *colWidth; |
| 906 | + int showHdr; |
| 907 | + char *rowSep; |
| 908 | + if( p->cMode==MODE_Column ){ |
| 909 | + colWidth = p->colWidth; |
| 910 | + showHdr = p->showHeader; |
| 911 | + rowSep = p->rowSeparator; |
| 912 | + }else{ |
| 913 | + colWidth = aExplainWidths; |
| 914 | + showHdr = 1; |
| 915 | + rowSep = "\n"; |
| 916 | + } |
| 902 | 917 | if( p->cnt++==0 ){ |
| 903 | 918 | for(i=0; i<nArg; i++){ |
| 904 | 919 | int w, n; |
| 905 | 920 | if( i<ArraySize(p->colWidth) ){ |
| 906 | | - w = p->colWidth[i]; |
| 921 | + w = colWidth[i]; |
| 907 | 922 | }else{ |
| 908 | 923 | w = 0; |
| 909 | 924 | } |
| 910 | 925 | if( w==0 ){ |
| 911 | 926 | w = strlen30(azCol[i] ? azCol[i] : ""); |
| | @@ -914,21 +929,21 @@ |
| 914 | 929 | if( w<n ) w = n; |
| 915 | 930 | } |
| 916 | 931 | if( i<ArraySize(p->actualWidth) ){ |
| 917 | 932 | p->actualWidth[i] = w; |
| 918 | 933 | } |
| 919 | | - if( p->showHeader ){ |
| 934 | + if( showHdr ){ |
| 920 | 935 | if( w<0 ){ |
| 921 | 936 | utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], |
| 922 | | - i==nArg-1 ? p->rowSeparator : " "); |
| 937 | + i==nArg-1 ? rowSep : " "); |
| 923 | 938 | }else{ |
| 924 | 939 | utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], |
| 925 | | - i==nArg-1 ? p->rowSeparator : " "); |
| 940 | + i==nArg-1 ? rowSep : " "); |
| 926 | 941 | } |
| 927 | 942 | } |
| 928 | 943 | } |
| 929 | | - if( p->showHeader ){ |
| 944 | + if( showHdr ){ |
| 930 | 945 | for(i=0; i<nArg; i++){ |
| 931 | 946 | int w; |
| 932 | 947 | if( i<ArraySize(p->actualWidth) ){ |
| 933 | 948 | w = p->actualWidth[i]; |
| 934 | 949 | if( w<0 ) w = -w; |
| | @@ -936,11 +951,11 @@ |
| 936 | 951 | w = 10; |
| 937 | 952 | } |
| 938 | 953 | utf8_printf(p->out,"%-*.*s%s",w,w, |
| 939 | 954 | "----------------------------------------------------------" |
| 940 | 955 | "----------------------------------------------------------", |
| 941 | | - i==nArg-1 ? p->rowSeparator : " "); |
| 956 | + i==nArg-1 ? rowSep : " "); |
| 942 | 957 | } |
| 943 | 958 | } |
| 944 | 959 | } |
| 945 | 960 | if( azArg==0 ) break; |
| 946 | 961 | for(i=0; i<nArg; i++){ |
| | @@ -948,11 +963,11 @@ |
| 948 | 963 | if( i<ArraySize(p->actualWidth) ){ |
| 949 | 964 | w = p->actualWidth[i]; |
| 950 | 965 | }else{ |
| 951 | 966 | w = 10; |
| 952 | 967 | } |
| 953 | | - if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ |
| 968 | + if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){ |
| 954 | 969 | w = strlen30(azArg[i]); |
| 955 | 970 | } |
| 956 | 971 | if( i==1 && p->aiIndent && p->pStmt ){ |
| 957 | 972 | if( p->iIndent<p->nIndent ){ |
| 958 | 973 | utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
| | @@ -960,15 +975,15 @@ |
| 960 | 975 | p->iIndent++; |
| 961 | 976 | } |
| 962 | 977 | if( w<0 ){ |
| 963 | 978 | utf8_printf(p->out,"%*.*s%s",-w,-w, |
| 964 | 979 | azArg[i] ? azArg[i] : p->nullValue, |
| 965 | | - i==nArg-1 ? p->rowSeparator : " "); |
| 980 | + i==nArg-1 ? rowSep : " "); |
| 966 | 981 | }else{ |
| 967 | 982 | utf8_printf(p->out,"%-*.*s%s",w,w, |
| 968 | 983 | azArg[i] ? azArg[i] : p->nullValue, |
| 969 | | - i==nArg-1 ? p->rowSeparator : " "); |
| 984 | + i==nArg-1 ? rowSep : " "); |
| 970 | 985 | } |
| 971 | 986 | } |
| 972 | 987 | break; |
| 973 | 988 | } |
| 974 | 989 | case MODE_Semi: |
| | @@ -984,11 +999,11 @@ |
| 984 | 999 | char *z = azArg[i]; |
| 985 | 1000 | if( z==0 ) z = p->nullValue; |
| 986 | 1001 | utf8_printf(p->out, "%s", z); |
| 987 | 1002 | if( i<nArg-1 ){ |
| 988 | 1003 | utf8_printf(p->out, "%s", p->colSeparator); |
| 989 | | - }else if( p->mode==MODE_Semi ){ |
| 1004 | + }else if( p->cMode==MODE_Semi ){ |
| 990 | 1005 | utf8_printf(p->out, ";%s", p->rowSeparator); |
| 991 | 1006 | }else{ |
| 992 | 1007 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 993 | 1008 | } |
| 994 | 1009 | } |
| | @@ -1489,14 +1504,21 @@ |
| 1489 | 1504 | "Rewind", 0 }; |
| 1490 | 1505 | const char *azGoto[] = { "Goto", 0 }; |
| 1491 | 1506 | |
| 1492 | 1507 | /* Try to figure out if this is really an EXPLAIN statement. If this |
| 1493 | 1508 | ** cannot be verified, return early. */ |
| 1509 | + if( sqlite3_column_count(pSql)!=8 ){ |
| 1510 | + p->cMode = p->mode; |
| 1511 | + return; |
| 1512 | + } |
| 1494 | 1513 | zSql = sqlite3_sql(pSql); |
| 1495 | 1514 | if( zSql==0 ) return; |
| 1496 | 1515 | for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++); |
| 1497 | | - if( sqlite3_strnicmp(z, "explain", 7) ) return; |
| 1516 | + if( sqlite3_strnicmp(z, "explain", 7) ){ |
| 1517 | + p->cMode = p->mode; |
| 1518 | + return; |
| 1519 | + } |
| 1498 | 1520 | |
| 1499 | 1521 | for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){ |
| 1500 | 1522 | int i; |
| 1501 | 1523 | int iAddr = sqlite3_column_int(pSql, 0); |
| 1502 | 1524 | const char *zOp = (const char*)sqlite3_column_text(pSql, 1); |
| | @@ -1509,10 +1531,24 @@ |
| 1509 | 1531 | int p2 = sqlite3_column_int(pSql, 3); |
| 1510 | 1532 | int p2op = (p2 + (iOp-iAddr)); |
| 1511 | 1533 | |
| 1512 | 1534 | /* Grow the p->aiIndent array as required */ |
| 1513 | 1535 | if( iOp>=nAlloc ){ |
| 1536 | + if( iOp==0 ){ |
| 1537 | + /* Do further verfication that this is explain output. Abort if |
| 1538 | + ** it is not */ |
| 1539 | + static const char *explainCols[] = { |
| 1540 | + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" }; |
| 1541 | + int jj; |
| 1542 | + for(jj=0; jj<ArraySize(explainCols); jj++){ |
| 1543 | + if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){ |
| 1544 | + p->cMode = p->mode; |
| 1545 | + sqlite3_reset(pSql); |
| 1546 | + return; |
| 1547 | + } |
| 1548 | + } |
| 1549 | + } |
| 1514 | 1550 | nAlloc += 100; |
| 1515 | 1551 | p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); |
| 1516 | 1552 | abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); |
| 1517 | 1553 | } |
| 1518 | 1554 | abYield[iOp] = str_in_array(zOp, azYield); |
| | @@ -1612,14 +1648,24 @@ |
| 1612 | 1648 | } |
| 1613 | 1649 | sqlite3_finalize(pExplain); |
| 1614 | 1650 | sqlite3_free(zEQP); |
| 1615 | 1651 | } |
| 1616 | 1652 | |
| 1617 | | - /* If the shell is currently in ".explain" mode, gather the extra |
| 1618 | | - ** data required to add indents to the output.*/ |
| 1619 | | - if( pArg && pArg->mode==MODE_Explain ){ |
| 1620 | | - explain_data_prepare(pArg, pStmt); |
| 1653 | + if( pArg ){ |
| 1654 | + pArg->cMode = pArg->mode; |
| 1655 | + if( pArg->autoExplain |
| 1656 | + && sqlite3_column_count(pStmt)==8 |
| 1657 | + && sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0 |
| 1658 | + ){ |
| 1659 | + pArg->cMode = MODE_Explain; |
| 1660 | + } |
| 1661 | + |
| 1662 | + /* If the shell is currently in ".explain" mode, gather the extra |
| 1663 | + ** data required to add indents to the output.*/ |
| 1664 | + if( pArg->cMode==MODE_Explain ){ |
| 1665 | + explain_data_prepare(pArg, pStmt); |
| 1666 | + } |
| 1621 | 1667 | } |
| 1622 | 1668 | |
| 1623 | 1669 | /* perform the first step. this will tell us if we |
| 1624 | 1670 | ** have a result set or not and how wide it is. |
| 1625 | 1671 | */ |
| | @@ -1645,11 +1691,11 @@ |
| 1645 | 1691 | } |
| 1646 | 1692 | do{ |
| 1647 | 1693 | /* extract the data and data types */ |
| 1648 | 1694 | for(i=0; i<nCol; i++){ |
| 1649 | 1695 | aiTypes[i] = x = sqlite3_column_type(pStmt, i); |
| 1650 | | - if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){ |
| 1696 | + if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ |
| 1651 | 1697 | azVals[i] = ""; |
| 1652 | 1698 | }else{ |
| 1653 | 1699 | azVals[i] = (char*)sqlite3_column_text(pStmt, i); |
| 1654 | 1700 | } |
| 1655 | 1701 | if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ |
| | @@ -1865,12 +1911,11 @@ |
| 1865 | 1911 | " If TABLE specified, only dump tables matching\n" |
| 1866 | 1912 | " LIKE pattern TABLE.\n" |
| 1867 | 1913 | ".echo on|off Turn command echo on or off\n" |
| 1868 | 1914 | ".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n" |
| 1869 | 1915 | ".exit Exit this program\n" |
| 1870 | | - ".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n" |
| 1871 | | - " With no args, it turns EXPLAIN on.\n" |
| 1916 | + ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n" |
| 1872 | 1917 | ".fullschema Show schema and the content of sqlite_stat tables\n" |
| 1873 | 1918 | ".headers on|off Turn display of headers on or off\n" |
| 1874 | 1919 | ".help Show this message\n" |
| 1875 | 1920 | ".import FILE TABLE Import data from FILE into TABLE\n" |
| 1876 | 1921 | ".indexes ?TABLE? Show names of all indexes\n" |
| | @@ -2853,11 +2898,11 @@ |
| 2853 | 2898 | ShellState data; |
| 2854 | 2899 | char *zErrMsg = 0; |
| 2855 | 2900 | open_db(p, 0); |
| 2856 | 2901 | memcpy(&data, p, sizeof(data)); |
| 2857 | 2902 | data.showHeader = 1; |
| 2858 | | - data.mode = MODE_Column; |
| 2903 | + data.cMode = data.mode = MODE_Column; |
| 2859 | 2904 | data.colWidth[0] = 3; |
| 2860 | 2905 | data.colWidth[1] = 15; |
| 2861 | 2906 | data.colWidth[2] = 58; |
| 2862 | 2907 | data.cnt = 0; |
| 2863 | 2908 | sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); |
| | @@ -2948,41 +2993,28 @@ |
| 2948 | 2993 | if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc); |
| 2949 | 2994 | rc = 2; |
| 2950 | 2995 | }else |
| 2951 | 2996 | |
| 2952 | 2997 | if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ |
| 2953 | | - int val = nArg>=2 ? booleanValue(azArg[1]) : 1; |
| 2954 | | - if(val == 1) { |
| 2955 | | - if(!p->normalMode.valid) { |
| 2956 | | - p->normalMode.valid = 1; |
| 2957 | | - p->normalMode.mode = p->mode; |
| 2958 | | - p->normalMode.showHeader = p->showHeader; |
| 2959 | | - memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth)); |
| 2960 | | - } |
| 2961 | | - /* We could put this code under the !p->explainValid |
| 2962 | | - ** condition so that it does not execute if we are already in |
| 2963 | | - ** explain mode. However, always executing it allows us an easy |
| 2964 | | - ** was to reset to explain mode in case the user previously |
| 2965 | | - ** did an .explain followed by a .width, .mode or .header |
| 2966 | | - ** command. |
| 2967 | | - */ |
| 2998 | + int val = 1; |
| 2999 | + if( nArg>=2 ){ |
| 3000 | + if( strcmp(azArg[1],"auto")==0 ){ |
| 3001 | + val = 99; |
| 3002 | + }else{ |
| 3003 | + val = booleanValue(azArg[1]); |
| 3004 | + } |
| 3005 | + } |
| 3006 | + if( val==1 && p->mode!=MODE_Explain ){ |
| 3007 | + p->normalMode = p->mode; |
| 2968 | 3008 | p->mode = MODE_Explain; |
| 2969 | | - p->showHeader = 1; |
| 2970 | | - memset(p->colWidth,0,sizeof(p->colWidth)); |
| 2971 | | - p->colWidth[0] = 4; /* addr */ |
| 2972 | | - p->colWidth[1] = 13; /* opcode */ |
| 2973 | | - p->colWidth[2] = 4; /* P1 */ |
| 2974 | | - p->colWidth[3] = 4; /* P2 */ |
| 2975 | | - p->colWidth[4] = 4; /* P3 */ |
| 2976 | | - p->colWidth[5] = 13; /* P4 */ |
| 2977 | | - p->colWidth[6] = 2; /* P5 */ |
| 2978 | | - p->colWidth[7] = 13; /* Comment */ |
| 2979 | | - }else if (p->normalMode.valid) { |
| 2980 | | - p->normalMode.valid = 0; |
| 2981 | | - p->mode = p->normalMode.mode; |
| 2982 | | - p->showHeader = p->normalMode.showHeader; |
| 2983 | | - memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth)); |
| 3009 | + p->autoExplain = 0; |
| 3010 | + }else if( val==0 ){ |
| 3011 | + if( p->mode==MODE_Explain ) p->mode = p->normalMode; |
| 3012 | + p->autoExplain = 0; |
| 3013 | + }else if( val==99 ){ |
| 3014 | + if( p->mode==MODE_Explain ) p->mode = p->normalMode; |
| 3015 | + p->autoExplain = 1; |
| 2984 | 3016 | } |
| 2985 | 3017 | }else |
| 2986 | 3018 | |
| 2987 | 3019 | if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ |
| 2988 | 3020 | ShellState data; |
| | @@ -2994,11 +3026,11 @@ |
| 2994 | 3026 | goto meta_command_exit; |
| 2995 | 3027 | } |
| 2996 | 3028 | open_db(p, 0); |
| 2997 | 3029 | memcpy(&data, p, sizeof(data)); |
| 2998 | 3030 | data.showHeader = 0; |
| 2999 | | - data.mode = MODE_Semi; |
| 3031 | + data.cMode = data.mode = MODE_Semi; |
| 3000 | 3032 | rc = sqlite3_exec(p->db, |
| 3001 | 3033 | "SELECT sql FROM" |
| 3002 | 3034 | " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" |
| 3003 | 3035 | " FROM sqlite_master UNION ALL" |
| 3004 | 3036 | " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " |
| | @@ -3019,11 +3051,11 @@ |
| 3019 | 3051 | raw_printf(p->out, "/* No STAT tables available */\n"); |
| 3020 | 3052 | }else{ |
| 3021 | 3053 | raw_printf(p->out, "ANALYZE sqlite_master;\n"); |
| 3022 | 3054 | sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'", |
| 3023 | 3055 | callback, &data, &zErrMsg); |
| 3024 | | - data.mode = MODE_Insert; |
| 3056 | + data.cMode = data.mode = MODE_Insert; |
| 3025 | 3057 | data.zDestTable = "sqlite_stat1"; |
| 3026 | 3058 | shell_exec(p->db, "SELECT * FROM sqlite_stat1", |
| 3027 | 3059 | shell_callback, &data,&zErrMsg); |
| 3028 | 3060 | data.zDestTable = "sqlite_stat3"; |
| 3029 | 3061 | shell_exec(p->db, "SELECT * FROM sqlite_stat3", |
| | @@ -3251,11 +3283,11 @@ |
| 3251 | 3283 | ShellState data; |
| 3252 | 3284 | char *zErrMsg = 0; |
| 3253 | 3285 | open_db(p, 0); |
| 3254 | 3286 | memcpy(&data, p, sizeof(data)); |
| 3255 | 3287 | data.showHeader = 0; |
| 3256 | | - data.mode = MODE_List; |
| 3288 | + data.cMode = data.mode = MODE_List; |
| 3257 | 3289 | if( nArg==1 ){ |
| 3258 | 3290 | rc = sqlite3_exec(p->db, |
| 3259 | 3291 | "SELECT name FROM sqlite_master " |
| 3260 | 3292 | "WHERE type='index' AND name NOT LIKE 'sqlite_%' " |
| 3261 | 3293 | "UNION ALL " |
| | @@ -3437,10 +3469,11 @@ |
| 3437 | 3469 | }else { |
| 3438 | 3470 | raw_printf(stderr, "Error: mode should be one of: " |
| 3439 | 3471 | "ascii column csv html insert line list tabs tcl\n"); |
| 3440 | 3472 | rc = 1; |
| 3441 | 3473 | } |
| 3474 | + p->cMode = p->mode; |
| 3442 | 3475 | }else |
| 3443 | 3476 | |
| 3444 | 3477 | if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ |
| 3445 | 3478 | if( nArg==2 ){ |
| 3446 | 3479 | sqlite3_snprintf(sizeof(p->nullValue), p->nullValue, |
| | @@ -3626,11 +3659,11 @@ |
| 3626 | 3659 | ShellState data; |
| 3627 | 3660 | char *zErrMsg = 0; |
| 3628 | 3661 | open_db(p, 0); |
| 3629 | 3662 | memcpy(&data, p, sizeof(data)); |
| 3630 | 3663 | data.showHeader = 0; |
| 3631 | | - data.mode = MODE_Semi; |
| 3664 | + data.cMode = data.mode = MODE_Semi; |
| 3632 | 3665 | if( nArg==2 ){ |
| 3633 | 3666 | int i; |
| 3634 | 3667 | for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); |
| 3635 | 3668 | if( strcmp(azArg[1],"sqlite_master")==0 ){ |
| 3636 | 3669 | char *new_argv[2], *new_colv[2]; |
| | @@ -3774,11 +3807,12 @@ |
| 3774 | 3807 | rc = 1; |
| 3775 | 3808 | goto meta_command_exit; |
| 3776 | 3809 | } |
| 3777 | 3810 | utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off"); |
| 3778 | 3811 | utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off"); |
| 3779 | | - utf8_printf(p->out,"%9.9s: %s\n","explain",p->normalMode.valid?"on":"off"); |
| 3812 | + utf8_printf(p->out, "%12.12s: %s\n","explain", |
| 3813 | + p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off"); |
| 3780 | 3814 | utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off"); |
| 3781 | 3815 | utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]); |
| 3782 | 3816 | utf8_printf(p->out, "%12.12s: ", "nullvalue"); |
| 3783 | 3817 | output_c_string(p->out, p->nullValue); |
| 3784 | 3818 | raw_printf(p->out, "\n"); |
| | @@ -4573,11 +4607,12 @@ |
| 4573 | 4607 | /* |
| 4574 | 4608 | ** Initialize the state information in data |
| 4575 | 4609 | */ |
| 4576 | 4610 | static void main_init(ShellState *data) { |
| 4577 | 4611 | memset(data, 0, sizeof(*data)); |
| 4578 | | - data->mode = MODE_List; |
| 4612 | + data->normalMode = data->cMode = data->mode = MODE_List; |
| 4613 | + data->autoExplain = 1; |
| 4579 | 4614 | memcpy(data->colSeparator,SEP_Column, 2); |
| 4580 | 4615 | memcpy(data->rowSeparator,SEP_Row, 2); |
| 4581 | 4616 | data->showHeader = 0; |
| 4582 | 4617 | data->shellFlgs = SHFLG_Lookaside; |
| 4583 | 4618 | sqlite3_config(SQLITE_CONFIG_URI, 1); |
| | @@ -4906,10 +4941,11 @@ |
| 4906 | 4941 | }else{ |
| 4907 | 4942 | utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); |
| 4908 | 4943 | raw_printf(stderr,"Use -help for a list of options.\n"); |
| 4909 | 4944 | return 1; |
| 4910 | 4945 | } |
| 4946 | + data.cMode = data.mode; |
| 4911 | 4947 | } |
| 4912 | 4948 | |
| 4913 | 4949 | if( !readStdin ){ |
| 4914 | 4950 | /* Run all arguments that do not begin with '-' as if they were separate |
| 4915 | 4951 | ** command-line inputs, except for the argToSkip argument which contains |
| 4916 | 4952 | |