/ Check-in [72e8f529]
Login

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

Overview
Comment:Simplification to the shell_exec() mechanism in the CLI.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 72e8f529ac8a268611f16456b13d55cc6c62df7f1a0aaa78a169338a0d95b960
User & Date: drh 2018-03-09 15:24:33
References
2018-05-08
23:15 New ticket [e63a34a0] Incorrectly formatted output for the ".fullschema" command in the CLI. artifact: b316ee8e user: drh
Context
2018-03-09
16:37
Setting ".stats 2" in the CLI causes column metadata for each prepared statement to be displayed. check-in: 7fea00fd user: drh tags: trunk
15:24
Simplification to the shell_exec() mechanism in the CLI. check-in: 72e8f529 user: drh tags: trunk
14:11
Fix a problem in test file nockpt.test causing errors with SQLITE_DEFAULT_AUTOVACUUM builds. check-in: e547c83f user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.in.

  2560   2560   }
  2561   2561   
  2562   2562   /*
  2563   2563   ** Run a prepared statement
  2564   2564   */
  2565   2565   static void exec_prepared_stmt(
  2566   2566     ShellState *pArg,                                /* Pointer to ShellState */
  2567         -  sqlite3_stmt *pStmt,                             /* Statment to run */
  2568         -  int (*xCallback)(void*,int,char**,char**,int*)   /* Callback function */
         2567  +  sqlite3_stmt *pStmt                              /* Statment to run */
  2569   2568   ){
  2570   2569     int rc;
  2571   2570   
  2572   2571     /* perform the first step.  this will tell us if we
  2573   2572     ** have a result set or not and how wide it is.
  2574   2573     */
  2575   2574     rc = sqlite3_step(pStmt);
  2576   2575     /* if we have a result set... */
  2577   2576     if( SQLITE_ROW == rc ){
  2578         -    /* if we have a callback... */
  2579         -    if( xCallback ){
  2580         -      /* allocate space for col name ptr, value ptr, and type */
  2581         -      int nCol = sqlite3_column_count(pStmt);
  2582         -      void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
  2583         -      if( !pData ){
  2584         -        rc = SQLITE_NOMEM;
  2585         -      }else{
  2586         -        char **azCols = (char **)pData;      /* Names of result columns */
  2587         -        char **azVals = &azCols[nCol];       /* Results */
  2588         -        int *aiTypes = (int *)&azVals[nCol]; /* Result types */
  2589         -        int i, x;
  2590         -        assert(sizeof(int) <= sizeof(char *));
  2591         -        /* save off ptrs to column names */
         2577  +    /* allocate space for col name ptr, value ptr, and type */
         2578  +    int nCol = sqlite3_column_count(pStmt);
         2579  +    void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
         2580  +    if( !pData ){
         2581  +      rc = SQLITE_NOMEM;
         2582  +    }else{
         2583  +      char **azCols = (char **)pData;      /* Names of result columns */
         2584  +      char **azVals = &azCols[nCol];       /* Results */
         2585  +      int *aiTypes = (int *)&azVals[nCol]; /* Result types */
         2586  +      int i, x;
         2587  +      assert(sizeof(int) <= sizeof(char *));
         2588  +      /* save off ptrs to column names */
         2589  +      for(i=0; i<nCol; i++){
         2590  +        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
         2591  +      }
         2592  +      do{
         2593  +        /* extract the data and data types */
  2592   2594           for(i=0; i<nCol; i++){
  2593         -          azCols[i] = (char *)sqlite3_column_name(pStmt, i);
  2594         -        }
  2595         -        do{
  2596         -          /* extract the data and data types */
  2597         -          for(i=0; i<nCol; i++){
  2598         -            aiTypes[i] = x = sqlite3_column_type(pStmt, i);
  2599         -            if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
  2600         -              azVals[i] = "";
  2601         -            }else{
  2602         -              azVals[i] = (char*)sqlite3_column_text(pStmt, i);
  2603         -            }
  2604         -            if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
  2605         -              rc = SQLITE_NOMEM;
  2606         -              break; /* from for */
  2607         -            }
  2608         -          } /* end for */
  2609         -
  2610         -          /* if data and types extracted successfully... */
  2611         -          if( SQLITE_ROW == rc ){
  2612         -            /* call the supplied callback with the result row data */
  2613         -            if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
  2614         -              rc = SQLITE_ABORT;
  2615         -            }else{
  2616         -              rc = sqlite3_step(pStmt);
  2617         -            }
  2618         -          }
  2619         -        } while( SQLITE_ROW == rc );
  2620         -        sqlite3_free(pData);
  2621         -      }
  2622         -    }else{
  2623         -      do{
  2624         -        rc = sqlite3_step(pStmt);
  2625         -      } while( rc == SQLITE_ROW );
         2595  +          aiTypes[i] = x = sqlite3_column_type(pStmt, i);
         2596  +          if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
         2597  +            azVals[i] = "";
         2598  +          }else{
         2599  +            azVals[i] = (char*)sqlite3_column_text(pStmt, i);
         2600  +          }
         2601  +          if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
         2602  +            rc = SQLITE_NOMEM;
         2603  +            break; /* from for */
         2604  +          }
         2605  +        } /* end for */
         2606  +
         2607  +        /* if data and types extracted successfully... */
         2608  +        if( SQLITE_ROW == rc ){
         2609  +          /* call the supplied callback with the result row data */
         2610  +          if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
         2611  +            rc = SQLITE_ABORT;
         2612  +          }else{
         2613  +            rc = sqlite3_step(pStmt);
         2614  +          }
         2615  +        }
         2616  +      } while( SQLITE_ROW == rc );
         2617  +      sqlite3_free(pData);
  2626   2618       }
  2627   2619     }
  2628   2620   }
  2629   2621   
  2630   2622   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2631   2623   /*
  2632   2624   ** This function is called to process SQL if the previous shell command
................................................................................
  2764   2756   ** set via the supplied callback.
  2765   2757   **
  2766   2758   ** This is very similar to SQLite's built-in sqlite3_exec()
  2767   2759   ** function except it takes a slightly different callback
  2768   2760   ** and callback data argument.
  2769   2761   */
  2770   2762   static int shell_exec(
  2771         -  sqlite3 *db,                              /* An open database */
  2772         -  const char *zSql,                         /* SQL to be evaluated */
  2773         -  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
  2774         -                                            /* (not the same as sqlite3_exec) */
  2775   2763     ShellState *pArg,                         /* Pointer to ShellState */
         2764  +  const char *zSql,                         /* SQL to be evaluated */
  2776   2765     char **pzErrMsg                           /* Error msg written here */
  2777   2766   ){
  2778   2767     sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
  2779   2768     int rc = SQLITE_OK;             /* Return Code */
  2780   2769     int rc2;
  2781   2770     const char *zLeftover;          /* Tail of unprocessed SQL */
         2771  +  sqlite3 *db = pArg->db;
  2782   2772   
  2783   2773     if( pzErrMsg ){
  2784   2774       *pzErrMsg = NULL;
  2785   2775     }
  2786   2776   
  2787   2777   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2788   2778     if( pArg->expert.pExpert ){
................................................................................
  2845   2835           if( pArg->autoEQP>=AUTOEQP_full ){
  2846   2836             /* Also do an EXPLAIN for ".eqp full" mode */
  2847   2837             zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
  2848   2838             rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
  2849   2839             if( rc==SQLITE_OK ){
  2850   2840               pArg->cMode = MODE_Explain;
  2851   2841               explain_data_prepare(pArg, pExplain);
  2852         -            exec_prepared_stmt(pArg, pExplain, xCallback);
         2842  +            exec_prepared_stmt(pArg, pExplain);
  2853   2843               explain_data_delete(pArg);
  2854   2844             }
  2855   2845             sqlite3_finalize(pExplain);
  2856   2846             sqlite3_free(zEQP);
  2857   2847           }
  2858   2848           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, triggerEQP, 0);
  2859   2849           restore_debug_trace_modes();
................................................................................
  2871   2861           /* If the shell is currently in ".explain" mode, gather the extra
  2872   2862           ** data required to add indents to the output.*/
  2873   2863           if( pArg->cMode==MODE_Explain ){
  2874   2864             explain_data_prepare(pArg, pStmt);
  2875   2865           }
  2876   2866         }
  2877   2867   
  2878         -      exec_prepared_stmt(pArg, pStmt, xCallback);
         2868  +      exec_prepared_stmt(pArg, pStmt);
  2879   2869         explain_data_delete(pArg);
  2880   2870   
  2881   2871         /* print usage stats if stats on */
  2882   2872         if( pArg && pArg->statsOn ){
  2883   2873           display_stats(db, pArg, 0);
  2884   2874         }
  2885   2875   
................................................................................
  3134   3124       appendText(&sSelect, " FROM ", 0);
  3135   3125       appendText(&sSelect, zTable, quoteChar(zTable));
  3136   3126   
  3137   3127       savedDestTable = p->zDestTable;
  3138   3128       savedMode = p->mode;
  3139   3129       p->zDestTable = sTable.z;
  3140   3130       p->mode = p->cMode = MODE_Insert;
  3141         -    rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0);
         3131  +    rc = shell_exec(p, sSelect.z, 0);
  3142   3132       if( (rc&0xff)==SQLITE_CORRUPT ){
  3143   3133         raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
  3144   3134         toggleSelectOrder(p->db);
  3145         -      shell_exec(p->db, sSelect.z, shell_callback, p, 0);
         3135  +      shell_exec(p, sSelect.z, 0);
  3146   3136         toggleSelectOrder(p->db);
  3147   3137       }
  3148   3138       p->zDestTable = savedDestTable;
  3149   3139       p->mode = savedMode;
  3150   3140       freeText(&sTable);
  3151   3141       freeText(&sSelect);
  3152   3142       if( rc ) p->nErr++;
................................................................................
  5815   5805         raw_printf(p->out, "/* No STAT tables available */\n");
  5816   5806       }else{
  5817   5807         raw_printf(p->out, "ANALYZE sqlite_master;\n");
  5818   5808         sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
  5819   5809                      callback, &data, &zErrMsg);
  5820   5810         data.cMode = data.mode = MODE_Insert;
  5821   5811         data.zDestTable = "sqlite_stat1";
  5822         -      shell_exec(p->db, "SELECT * FROM sqlite_stat1",
  5823         -                 shell_callback, &data,&zErrMsg);
         5812  +      shell_exec(p, "SELECT * FROM sqlite_stat1", &zErrMsg);
  5824   5813         data.zDestTable = "sqlite_stat3";
  5825         -      shell_exec(p->db, "SELECT * FROM sqlite_stat3",
  5826         -                 shell_callback, &data,&zErrMsg);
         5814  +      shell_exec(p, "SELECT * FROM sqlite_stat3", &zErrMsg);
  5827   5815         data.zDestTable = "sqlite_stat4";
  5828         -      shell_exec(p->db, "SELECT * FROM sqlite_stat4",
  5829         -                 shell_callback, &data, &zErrMsg);
         5816  +      shell_exec(p, "SELECT * FROM sqlite_stat4", &zErrMsg);
  5830   5817         raw_printf(p->out, "ANALYZE sqlite_master;\n");
  5831   5818       }
  5832   5819     }else
  5833   5820   
  5834   5821     if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
  5835   5822       if( nArg==2 ){
  5836   5823         p->showHeader = booleanValue(azArg[1]);
................................................................................
  7092   7079             sSql.z, iSize);
  7093   7080       }
  7094   7081       freeText(&sQuery);
  7095   7082       freeText(&sSql);
  7096   7083       if( bDebug ){
  7097   7084         utf8_printf(p->out, "%s\n", zSql);
  7098   7085       }else{
  7099         -      shell_exec(p->db, zSql, shell_callback, p, 0);
         7086  +      shell_exec(p, zSql, 0);
  7100   7087       }
  7101   7088       sqlite3_free(zSql);
  7102   7089     }else
  7103   7090   
  7104   7091   #ifndef SQLITE_NOHAVE_SYSTEM
  7105   7092     if( c=='s'
  7106   7093      && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
................................................................................
  7731   7718   static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
  7732   7719     int rc;
  7733   7720     char *zErrMsg = 0;
  7734   7721   
  7735   7722     open_db(p, 0);
  7736   7723     if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
  7737   7724     BEGIN_TIMER;
  7738         -  rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
         7725  +  rc = shell_exec(p, zSql, &zErrMsg);
  7739   7726     END_TIMER;
  7740   7727     if( rc || zErrMsg ){
  7741   7728       char zPrefix[100];
  7742   7729       if( in!=0 || !stdin_is_interactive ){
  7743   7730         sqlite3_snprintf(sizeof(zPrefix), zPrefix,
  7744   7731                          "Error: near line %d:", startline);
  7745   7732       }else{
................................................................................
  8408   8395         if( i==argc-1 ) break;
  8409   8396         z = cmdline_option_value(argc,argv,++i);
  8410   8397         if( z[0]=='.' ){
  8411   8398           rc = do_meta_command(z, &data);
  8412   8399           if( rc && bail_on_error ) return rc==2 ? 0 : rc;
  8413   8400         }else{
  8414   8401           open_db(&data, 0);
  8415         -        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
         8402  +        rc = shell_exec(&data, z, &zErrMsg);
  8416   8403           if( zErrMsg!=0 ){
  8417   8404             utf8_printf(stderr,"Error: %s\n", zErrMsg);
  8418   8405             if( bail_on_error ) return rc!=0 ? rc : 1;
  8419   8406           }else if( rc!=0 ){
  8420   8407             utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
  8421   8408             if( bail_on_error ) return rc;
  8422   8409           }
................................................................................
  8453   8440       */
  8454   8441       for(i=0; i<nCmd; i++){
  8455   8442         if( azCmd[i][0]=='.' ){
  8456   8443           rc = do_meta_command(azCmd[i], &data);
  8457   8444           if( rc ) return rc==2 ? 0 : rc;
  8458   8445         }else{
  8459   8446           open_db(&data, 0);
  8460         -        rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
         8447  +        rc = shell_exec(&data, azCmd[i], &zErrMsg);
  8461   8448           if( zErrMsg!=0 ){
  8462   8449             utf8_printf(stderr,"Error: %s\n", zErrMsg);
  8463   8450             return rc!=0 ? rc : 1;
  8464   8451           }else if( rc!=0 ){
  8465   8452             utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
  8466   8453             return rc;
  8467   8454           }