/ Check-in [8a8dcd6b]
Login

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

Overview
Comment:If errors are encountered while processing the ".dump" command in the command-line shell, print error messages as comments in the output and ROLLBACK at the end rather than committing. Ticket [ee19e690ec9a5a2]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8a8dcd6bd043d82dc04b6ad0614c64d20ace8e5f
User & Date: drh 2011-10-13 00:41:49
Context
2011-10-13
01:01
Fix a harmless compiler warning introduced into os_unix.c by one of the recent changes. check-in: 4bf4d5eb user: drh tags: trunk
00:41
If errors are encountered while processing the ".dump" command in the command-line shell, print error messages as comments in the output and ROLLBACK at the end rather than committing. Ticket [ee19e690ec9a5a2] check-in: 8a8dcd6b user: drh tags: trunk
00:11
Be sure to allocate plenty of space for error messages coming out of sqlite3_load_extension(), so that filenames and procedure names are not truncated. Ticket [7d32c69b50f89d] check-in: af8bcdd9 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

   403    403   */
   404    404   struct callback_data {
   405    405     sqlite3 *db;           /* The database */
   406    406     int echoOn;            /* True to echo input commands */
   407    407     int statsOn;           /* True to display memory stats before each finalize */
   408    408     int cnt;               /* Number of records displayed so far */
   409    409     FILE *out;             /* Write results here */
          410  +  int nErr;              /* Number of errors seen */
   410    411     int mode;              /* An output mode setting */
   411    412     int writableSchema;    /* True if PRAGMA writable_schema=ON */
   412    413     int showHeader;        /* True to show column names in List or Column mode */
   413    414     char *zDestTable;      /* Name of destination table when MODE_Insert */
   414    415     char separator[20];    /* Separator character for MODE_List */
   415    416     int colWidth[100];     /* Requested width of each column when in column mode*/
   416    417     int actualWidth[100];  /* Actual width of each column */
................................................................................
   928    929   ** Execute a query statement that has a single result column.  Print
   929    930   ** that result column on a line by itself with a semicolon terminator.
   930    931   **
   931    932   ** This is used, for example, to show the schema of the database by
   932    933   ** querying the SQLITE_MASTER table.
   933    934   */
   934    935   static int run_table_dump_query(
   935         -  FILE *out,              /* Send output here */
   936         -  sqlite3 *db,            /* Database to query */
   937         -  const char *zSelect,    /* SELECT statement to extract content */
   938         -  const char *zFirstRow   /* Print before first row, if not NULL */
          936  +  struct callback_data *p, /* Query context */
          937  +  const char *zSelect,     /* SELECT statement to extract content */
          938  +  const char *zFirstRow    /* Print before first row, if not NULL */
   939    939   ){
   940    940     sqlite3_stmt *pSelect;
   941    941     int rc;
   942         -  rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
          942  +  rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
   943    943     if( rc!=SQLITE_OK || !pSelect ){
          944  +    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
          945  +    p->nErr++;
   944    946       return rc;
   945    947     }
   946    948     rc = sqlite3_step(pSelect);
   947    949     while( rc==SQLITE_ROW ){
   948    950       if( zFirstRow ){
   949         -      fprintf(out, "%s", zFirstRow);
          951  +      fprintf(p->out, "%s", zFirstRow);
   950    952         zFirstRow = 0;
   951    953       }
   952         -    fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
          954  +    fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));
   953    955       rc = sqlite3_step(pSelect);
   954    956     }
   955         -  return sqlite3_finalize(pSelect);
          957  +  rc = sqlite3_finalize(pSelect);
          958  +  if( rc!=SQLITE_OK ){
          959  +    fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
          960  +    p->nErr++;
          961  +  }
          962  +  return rc;
   956    963   }
   957    964   
   958    965   /*
   959    966   ** Allocate space and save off current error string.
   960    967   */
   961    968   static char *save_err_msg(
   962    969     sqlite3 *db            /* Database to query */
................................................................................
  1274   1281       if( rc!=SQLITE_OK || nRow==0 ){
  1275   1282         free(zSelect);
  1276   1283         return 1;
  1277   1284       }
  1278   1285       zSelect = appendText(zSelect, "|| ')' FROM  ", 0);
  1279   1286       zSelect = appendText(zSelect, zTable, '"');
  1280   1287   
  1281         -    rc = run_table_dump_query(p->out, p->db, zSelect, zPrepStmt);
         1288  +    rc = run_table_dump_query(p, zSelect, zPrepStmt);
  1282   1289       if( rc==SQLITE_CORRUPT ){
  1283   1290         zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
  1284         -      rc = run_table_dump_query(p->out, p->db, zSelect, 0);
         1291  +      run_table_dump_query(p, zSelect, 0);
  1285   1292       }
  1286   1293       if( zSelect ) free(zSelect);
  1287   1294     }
  1288   1295     return 0;
  1289   1296   }
  1290   1297   
  1291   1298   /*
................................................................................
  1293   1300   ** the contents of the query are output as SQL statements.
  1294   1301   **
  1295   1302   ** If we get a SQLITE_CORRUPT error, rerun the query after appending
  1296   1303   ** "ORDER BY rowid DESC" to the end.
  1297   1304   */
  1298   1305   static int run_schema_dump_query(
  1299   1306     struct callback_data *p, 
  1300         -  const char *zQuery,
  1301         -  char **pzErrMsg
         1307  +  const char *zQuery
  1302   1308   ){
  1303   1309     int rc;
  1304         -  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
         1310  +  char *zErr = 0;
         1311  +  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  1305   1312     if( rc==SQLITE_CORRUPT ){
  1306   1313       char *zQ2;
  1307   1314       int len = strlen30(zQuery);
  1308         -    if( pzErrMsg ) sqlite3_free(*pzErrMsg);
         1315  +    fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
         1316  +    if( zErr ){
         1317  +      fprintf(p->out, "/****** %s ******/\n", zErr);
         1318  +      sqlite3_free(zErr);
         1319  +      zErr = 0;
         1320  +    }
  1309   1321       zQ2 = malloc( len+100 );
  1310   1322       if( zQ2==0 ) return rc;
  1311   1323       sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery);
  1312         -    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
         1324  +    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
         1325  +    if( rc ){
         1326  +      fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
         1327  +    }else{
         1328  +      rc = SQLITE_CORRUPT;
         1329  +    }
         1330  +    sqlite3_free(zErr);
  1313   1331       free(zQ2);
  1314   1332     }
  1315   1333     return rc;
  1316   1334   }
  1317   1335   
  1318   1336   /*
  1319   1337   ** Text of a help message
................................................................................
  1551   1569         fprintf(stderr,"Error: %s\n", zErrMsg);
  1552   1570         sqlite3_free(zErrMsg);
  1553   1571         rc = 1;
  1554   1572       }
  1555   1573     }else
  1556   1574   
  1557   1575     if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
  1558         -    char *zErrMsg = 0;
  1559   1576       open_db(p);
  1560   1577       /* When playing back a "dump", the content might appear in an order
  1561   1578       ** which causes immediate foreign key constraints to be violated.
  1562   1579       ** So disable foreign-key constraint enforcement to prevent problems. */
  1563   1580       fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
  1564   1581       fprintf(p->out, "BEGIN TRANSACTION;\n");
  1565   1582       p->writableSchema = 0;
  1566   1583       sqlite3_exec(p->db, "PRAGMA writable_schema=ON", 0, 0, 0);
         1584  +    p->nErr = 0;
  1567   1585       if( nArg==1 ){
  1568   1586         run_schema_dump_query(p, 
  1569   1587           "SELECT name, type, sql FROM sqlite_master "
  1570         -        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'", 0
         1588  +        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
  1571   1589         );
  1572   1590         run_schema_dump_query(p, 
  1573   1591           "SELECT name, type, sql FROM sqlite_master "
  1574         -        "WHERE name=='sqlite_sequence'", 0
         1592  +        "WHERE name=='sqlite_sequence'"
  1575   1593         );
  1576         -      run_table_dump_query(p->out, p->db,
         1594  +      run_table_dump_query(p,
  1577   1595           "SELECT sql FROM sqlite_master "
  1578   1596           "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
  1579   1597         );
  1580   1598       }else{
  1581   1599         int i;
  1582   1600         for(i=1; i<nArg; i++){
  1583   1601           zShellStatic = azArg[i];
  1584   1602           run_schema_dump_query(p,
  1585   1603             "SELECT name, type, sql FROM sqlite_master "
  1586   1604             "WHERE tbl_name LIKE shellstatic() AND type=='table'"
  1587         -          "  AND sql NOT NULL", 0);
  1588         -        run_table_dump_query(p->out, p->db,
         1605  +          "  AND sql NOT NULL");
         1606  +        run_table_dump_query(p,
  1589   1607             "SELECT sql FROM sqlite_master "
  1590   1608             "WHERE sql NOT NULL"
  1591   1609             "  AND type IN ('index','trigger','view')"
  1592   1610             "  AND tbl_name LIKE shellstatic()", 0
  1593   1611           );
  1594   1612           zShellStatic = 0;
  1595   1613         }
  1596   1614       }
  1597   1615       if( p->writableSchema ){
  1598   1616         fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
  1599   1617         p->writableSchema = 0;
  1600   1618       }
  1601   1619       sqlite3_exec(p->db, "PRAGMA writable_schema=OFF", 0, 0, 0);
  1602         -    if( zErrMsg ){
  1603         -      fprintf(stderr,"Error: %s\n", zErrMsg);
  1604         -      sqlite3_free(zErrMsg);
  1605         -    }else{
  1606         -      fprintf(p->out, "COMMIT;\n");
  1607         -    }
         1620  +    fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
  1608   1621     }else
  1609   1622   
  1610   1623     if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
  1611   1624       p->echoOn = booleanValue(azArg[1]);
  1612   1625     }else
  1613   1626   
  1614   1627     if( c=='e' && strncmp(azArg[0], "exit", n)==0  && nArg==1 ){