/ Check-in [be3ec8fd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the ".imposter" command to the command-line shell.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: be3ec8fdcf1541017ca9375df07645db2a9a3f5a
User & Date: drh 2016-11-03 13:01:38
Context
2016-11-03
13:12
In the command-line shell, fix the .imposter command so that it works with indexes on expressions. Fix the ".mode quote" mode so that it works with ".headers ON". check-in: ba9873da user: drh tags: trunk
13:01
Add the ".imposter" command to the command-line shell. check-in: be3ec8fd user: drh tags: trunk
02:25
Fix an possible NULL pointer deference in the command-line shell that can occur when using imposter mode. check-in: ad08753a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

  2160   2160     ".eqp on|off|full       Enable or disable automatic EXPLAIN QUERY PLAN\n"
  2161   2161     ".exit                  Exit this program\n"
  2162   2162     ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"
  2163   2163     ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
  2164   2164     ".headers on|off        Turn display of headers on or off\n"
  2165   2165     ".help                  Show this message\n"
  2166   2166     ".import FILE TABLE     Import data from FILE into TABLE\n"
         2167  +#ifndef SQLITE_OMIT_TEST_CONTROL
         2168  +  ".imposter INDEX TABLE  Create imposter table TABLE on index INDEX\n"
         2169  +#endif
  2167   2170     ".indexes ?TABLE?       Show names of all indexes\n"
  2168   2171     "                         If TABLE specified, only show indexes for tables\n"
  2169   2172     "                         matching LIKE pattern TABLE.\n"
  2170   2173   #ifdef SQLITE_ENABLE_IOTRACE
  2171   2174     ".iotrace FILE          Enable I/O diagnostic logging to FILE\n"
  2172   2175   #endif
  2173   2176     ".limit ?LIMIT? ?VAL?   Display or change the value of an SQLITE_LIMIT\n"
................................................................................
  3842   3845       }else if( rc != SQLITE_OK ){
  3843   3846         raw_printf(stderr,
  3844   3847                    "Error: querying sqlite_master and sqlite_temp_master\n");
  3845   3848         rc = 1;
  3846   3849       }
  3847   3850     }else
  3848   3851   
         3852  +#ifndef SQLITE_OMIT_BUILTIN_TEST
         3853  +  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
         3854  +    char *zSql;
         3855  +    char *zCollist = 0;
         3856  +    sqlite3_stmt *pStmt;
         3857  +    int tnum = 0;
         3858  +    if( nArg!=3 ){
         3859  +      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n");
         3860  +      rc = 1;
         3861  +      goto meta_command_exit;
         3862  +    }
         3863  +    open_db(p, 0);
         3864  +    zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
         3865  +                           " WHERE name='%q' AND type='index'", azArg[1]);
         3866  +    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         3867  +    sqlite3_free(zSql);
         3868  +    if( sqlite3_step(pStmt)==SQLITE_ROW ){
         3869  +      tnum = sqlite3_column_int(pStmt, 0);
         3870  +    }
         3871  +    sqlite3_finalize(pStmt);
         3872  +    if( tnum==0 ){
         3873  +      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
         3874  +      rc = 1;
         3875  +      goto meta_command_exit;
         3876  +    }
         3877  +    zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
         3878  +    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         3879  +    sqlite3_free(zSql);
         3880  +    while( sqlite3_step(pStmt)==SQLITE_ROW ){
         3881  +      const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
         3882  +      if( zCol==0 ) zCol = "_ROWID_";
         3883  +      if( zCollist==0 ){
         3884  +        zCollist = sqlite3_mprintf("\"%w\"", zCol);
         3885  +      }else{
         3886  +        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
         3887  +      }
         3888  +    }
         3889  +    sqlite3_finalize(pStmt);
         3890  +    zSql = sqlite3_mprintf(
         3891  +          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
         3892  +          azArg[2], zCollist, zCollist);
         3893  +    sqlite3_free(zCollist);
         3894  +    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
         3895  +    if( rc==SQLITE_OK ){
         3896  +      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
         3897  +      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
         3898  +      if( rc ){
         3899  +        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
         3900  +      }else{
         3901  +        utf8_printf(stdout, "%s;\n", zSql);
         3902  +        utf8_printf(stdout, 
         3903  +           "WARNING: writing to an imposter table will corrupt the index!\n"
         3904  +        );
         3905  +      }
         3906  +    }else{
         3907  +      utf8_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
         3908  +      rc = 1;
         3909  +    }
         3910  +    sqlite3_free(zSql);
         3911  +  }else
         3912  +#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
         3913  +
  3849   3914   #ifdef SQLITE_ENABLE_IOTRACE
  3850   3915     if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
  3851   3916       SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
  3852   3917       if( iotrace && iotrace!=stdout ) fclose(iotrace);
  3853   3918       iotrace = 0;
  3854   3919       if( nArg<2 ){
  3855   3920         sqlite3IoTrace = 0;
................................................................................
  3864   3929           rc = 1;
  3865   3930         }else{
  3866   3931           sqlite3IoTrace = iotracePrintf;
  3867   3932         }
  3868   3933       }
  3869   3934     }else
  3870   3935   #endif
         3936  +
  3871   3937     if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
  3872   3938       static const struct {
  3873   3939          const char *zLimitName;   /* Name of a limit */
  3874   3940          int limitCode;            /* Integer code for that limit */
  3875   3941       } aLimit[] = {
  3876   3942         { "length",                SQLITE_LIMIT_LENGTH                    },
  3877   3943         { "sql_length",            SQLITE_LIMIT_SQL_LENGTH                },
................................................................................
  4704   4770       if( nArg>=2 ){
  4705   4771         sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
  4706   4772       }else{
  4707   4773         sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
  4708   4774       }
  4709   4775     }else
  4710   4776   
         4777  +#ifndef SQLITE_OMIT_BUILTIN_TEST
  4711   4778     if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
  4712   4779       static const struct {
  4713   4780          const char *zCtrlName;   /* Name of a test-control option */
  4714   4781          int ctrlCode;            /* Integer code for that option */
  4715   4782       } aCtrl[] = {
  4716   4783         { "prng_save",             SQLITE_TESTCTRL_PRNG_SAVE              },
  4717   4784         { "prng_restore",          SQLITE_TESTCTRL_PRNG_RESTORE           },
................................................................................
  4879   4946       if( p->traceOut==0 ){
  4880   4947         sqlite3_trace_v2(p->db, 0, 0, 0);
  4881   4948       }else{
  4882   4949         sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
  4883   4950       }
  4884   4951   #endif
  4885   4952     }else
         4953  +#endif /* !defined(SQLITE_OMIT_BUILTIN_TEST) */
  4886   4954   
  4887   4955   #if SQLITE_USER_AUTHENTICATION
  4888   4956     if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
  4889   4957       if( nArg<2 ){
  4890   4958         raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
  4891   4959         rc = 1;
  4892   4960         goto meta_command_exit;