/ Check-in [67a87399]
Login

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

Overview
Comment:Fix the CLI so that the ".open --hexdb" command works even if it is contained in a subscript that is read using ".read".
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 67a87399b8ad8f1ce3052ee3159906f5c6df3d7b5691b3acac856bd2f1c82088
User & Date: drh 2018-12-13 18:30:01
Context
2018-12-13
18:59
Fix the CLI to keep proper track of input line numbers for use in error messages, even after processing in-line hex database inputs using ".open --hexdb". check-in: 7ffa9858 user: drh tags: trunk
18:30
Fix the CLI so that the ".open --hexdb" command works even if it is contained in a subscript that is read using ".read". check-in: 67a87399 user: drh tags: trunk
15:06
Add the "dbtotxt" utility program and the ability to read "dbtotxt" output as a deserialized input database in the CLI, using the --hexdb option to the ".open" command. check-in: e3bf1d3e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.in.

  1007   1007     u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  1008   1008     u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  1009   1009     u8 nEqpLevel;          /* Depth of the EQP output graph */
  1010   1010     u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
  1011   1011     unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
  1012   1012     int outCount;          /* Revert to stdout when reaching zero */
  1013   1013     int cnt;               /* Number of records displayed so far */
         1014  +  FILE *in;              /* Read commands from this stream */
  1014   1015     FILE *out;             /* Write results here */
  1015   1016     FILE *traceOut;        /* Output for sqlite3_trace() */
  1016   1017     int nErr;              /* Number of errors seen */
  1017   1018     int mode;              /* An output mode setting */
  1018   1019     int modePrior;         /* Saved mode */
  1019   1020     int cMode;             /* temporary output mode for the current query */
  1020   1021     int normalMode;        /* Output mode before ".explain on" */
................................................................................
  3591   3592       }
  3592   3593       sqlite3_free(zPat);
  3593   3594     }
  3594   3595     return n;
  3595   3596   }
  3596   3597   
  3597   3598   /* Forward reference */
  3598         -static int process_input(ShellState *p, FILE *in);
         3599  +static int process_input(ShellState *p);
  3599   3600   
  3600   3601   /*
  3601   3602   ** Read the content of file zName into memory obtained from sqlite3_malloc64()
  3602   3603   ** and return a pointer to the buffer. The caller is responsible for freeing
  3603   3604   ** the memory.
  3604   3605   **
  3605   3606   ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
................................................................................
  3745   3746     if( p->zDbFilename ){
  3746   3747       in = fopen(p->zDbFilename, "r");
  3747   3748       if( in==0 ){
  3748   3749         utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
  3749   3750         return 0;
  3750   3751       }
  3751   3752     }else{
  3752         -    in = stdin;
         3753  +    in = p->in;
  3753   3754     }
  3754   3755     *pnData = 0;
  3755   3756     if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
  3756   3757     rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
  3757   3758     if( rc!=2 ) goto readHexDb_error;
  3758   3759     if( n<=0 ) goto readHexDb_error;
  3759   3760     a = sqlite3_malloc( n );
................................................................................
  3785   3786           utf8_printf(stderr, "continue exceeds file size\n");
  3786   3787           goto readHexDb_error;
  3787   3788         }
  3788   3789         memcpy(a+k, x, 16);
  3789   3790       }
  3790   3791     }
  3791   3792     *pnData = n;
  3792         -  if( in!=stdin ) fclose(in);
         3793  +  if( in!=p->in ) fclose(in);
  3793   3794     return a;
  3794   3795   
  3795   3796   readHexDb_error:
  3796   3797     if( in!=stdin ){
  3797   3798       fclose(in);
  3798   3799     }else{
  3799         -    while( fgets(zLine, sizeof(zLine), in)!=0 ){
         3800  +    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
  3800   3801         if(strncmp(zLine, "| end ", 6)==0 ) break;
  3801   3802       }
  3802   3803     }
  3803   3804     sqlite3_free(a);
  3804   3805     utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
  3805   3806     return 0;
  3806   3807   }
................................................................................
  6966   6967     }else
  6967   6968   
  6968   6969     if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
  6969   6970       rc = 2;
  6970   6971     }else
  6971   6972   
  6972   6973     if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
  6973         -    FILE *alt;
         6974  +    FILE *inSaved = p->in;
  6974   6975       if( nArg!=2 ){
  6975   6976         raw_printf(stderr, "Usage: .read FILE\n");
  6976   6977         rc = 1;
  6977   6978         goto meta_command_exit;
  6978   6979       }
  6979         -    alt = fopen(azArg[1], "rb");
  6980         -    if( alt==0 ){
         6980  +    p->in = fopen(azArg[1], "rb");
         6981  +    if( p->in==0 ){
  6981   6982         utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
  6982   6983         rc = 1;
  6983   6984       }else{
  6984         -      rc = process_input(p, alt);
  6985         -      fclose(alt);
         6985  +      rc = process_input(p);
         6986  +      fclose(p->in);
  6986   6987       }
         6988  +    p->in = inSaved;
  6987   6989     }else
  6988   6990   
  6989   6991     if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
  6990   6992       const char *zSrcFile;
  6991   6993       const char *zDb;
  6992   6994       sqlite3 *pSrc;
  6993   6995       sqlite3_backup *pBackup;
................................................................................
  8320   8322   ** is interactive - the user is typing it it.  Otherwise, input
  8321   8323   ** is coming from a file or device.  A prompt is issued and history
  8322   8324   ** is saved only if input is interactive.  An interrupt signal will
  8323   8325   ** cause this routine to exit immediately, unless input is interactive.
  8324   8326   **
  8325   8327   ** Return the number of errors.
  8326   8328   */
  8327         -static int process_input(ShellState *p, FILE *in){
         8329  +static int process_input(ShellState *p){
  8328   8330     char *zLine = 0;          /* A single input line */
  8329   8331     char *zSql = 0;           /* Accumulated SQL text */
  8330   8332     int nLine;                /* Length of current line */
  8331   8333     int nSql = 0;             /* Bytes of zSql[] used */
  8332   8334     int nAlloc = 0;           /* Allocated zSql[] space */
  8333   8335     int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  8334   8336     int rc;                   /* Error code */
  8335   8337     int errCnt = 0;           /* Number of errors seen */
  8336   8338     int lineno = 0;           /* Current line number */
  8337   8339     int startline = 0;        /* Line number for start of current input */
  8338   8340   
  8339         -  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
         8341  +  while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
  8340   8342       fflush(p->out);
  8341         -    zLine = one_input_line(in, zLine, nSql>0);
         8343  +    zLine = one_input_line(p->in, zLine, nSql>0);
  8342   8344       if( zLine==0 ){
  8343   8345         /* End of input */
  8344         -      if( in==0 && stdin_is_interactive ) printf("\n");
         8346  +      if( p->in==0 && stdin_is_interactive ) printf("\n");
  8345   8347         break;
  8346   8348       }
  8347   8349       if( seenInterrupt ){
  8348         -      if( in!=0 ) break;
         8350  +      if( p->in!=0 ) break;
  8349   8351         seenInterrupt = 0;
  8350   8352       }
  8351   8353       lineno++;
  8352   8354       if( nSql==0 && _all_whitespace(zLine) ){
  8353   8355         if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
  8354   8356         continue;
  8355   8357       }
................................................................................
  8385   8387       }else{
  8386   8388         zSql[nSql++] = '\n';
  8387   8389         memcpy(zSql+nSql, zLine, nLine+1);
  8388   8390         nSql += nLine;
  8389   8391       }
  8390   8392       if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
  8391   8393                   && sqlite3_complete(zSql) ){
  8392         -      errCnt += runOneSqlLine(p, zSql, in, startline);
         8394  +      errCnt += runOneSqlLine(p, zSql, p->in, startline);
  8393   8395         nSql = 0;
  8394   8396         if( p->outCount ){
  8395   8397           output_reset(p);
  8396   8398           p->outCount = 0;
  8397   8399         }else{
  8398   8400           clearTempFile(p);
  8399   8401         }
  8400   8402       }else if( nSql && _all_whitespace(zSql) ){
  8401   8403         if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
  8402   8404         nSql = 0;
  8403   8405       }
  8404   8406     }
  8405   8407     if( nSql && !_all_whitespace(zSql) ){
  8406         -    errCnt += runOneSqlLine(p, zSql, in, startline);
         8408  +    errCnt += runOneSqlLine(p, zSql, p->in, startline);
  8407   8409     }
  8408   8410     free(zSql);
  8409   8411     free(zLine);
  8410   8412     return errCnt>0;
  8411   8413   }
  8412   8414   
  8413   8415   /*
................................................................................
  8488   8490   static void process_sqliterc(
  8489   8491     ShellState *p,                  /* Configuration data */
  8490   8492     const char *sqliterc_override   /* Name of config file. NULL to use default */
  8491   8493   ){
  8492   8494     char *home_dir = NULL;
  8493   8495     const char *sqliterc = sqliterc_override;
  8494   8496     char *zBuf = 0;
  8495         -  FILE *in = NULL;
         8497  +  FILE *inSaved = p->in;
  8496   8498   
  8497   8499     if (sqliterc == NULL) {
  8498   8500       home_dir = find_home_dir(0);
  8499   8501       if( home_dir==0 ){
  8500   8502         raw_printf(stderr, "-- warning: cannot find home directory;"
  8501   8503                         " cannot read ~/.sqliterc\n");
  8502   8504         return;
  8503   8505       }
  8504   8506       zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
  8505   8507       sqliterc = zBuf;
  8506   8508     }
  8507         -  in = fopen(sqliterc,"rb");
  8508         -  if( in ){
         8509  +  p->in = fopen(sqliterc,"rb");
         8510  +  if( p->in ){
  8509   8511       if( stdin_is_interactive ){
  8510   8512         utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
  8511   8513       }
  8512         -    process_input(p,in);
  8513         -    fclose(in);
         8514  +    process_input(p);
         8515  +    fclose(p->in);
  8514   8516     }
         8517  +  p->in = inSaved;
  8515   8518     sqlite3_free(zBuf);
  8516   8519   }
  8517   8520   
  8518   8521   /*
  8519   8522   ** Show available command line options
  8520   8523   */
  8521   8524   static const char zOptions[] =
................................................................................
  9119   9122         }
  9120   9123         if( zHistory ){ shell_read_history(zHistory); }
  9121   9124   #if HAVE_READLINE || HAVE_EDITLINE
  9122   9125         rl_attempted_completion_function = readline_completion;
  9123   9126   #elif HAVE_LINENOISE
  9124   9127         linenoiseSetCompletionCallback(linenoise_completion);
  9125   9128   #endif
  9126         -      rc = process_input(&data, 0);
         9129  +      data.in = 0;
         9130  +      rc = process_input(&data);
  9127   9131         if( zHistory ){
  9128   9132           shell_stifle_history(2000);
  9129   9133           shell_write_history(zHistory);
  9130   9134           free(zHistory);
  9131   9135         }
  9132   9136       }else{
  9133         -      rc = process_input(&data, stdin);
         9137  +      data.in = stdin;
         9138  +      rc = process_input(&data);
  9134   9139       }
  9135   9140     }
  9136   9141     set_table_name(&data, 0);
  9137   9142     if( data.db ){
  9138   9143       session_close_all(&data);
  9139   9144       close_db(data.db);
  9140   9145     }