/ Check-in [dd0db3f0]
Login

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

Overview
Comment:Add additional error messages and a progress spinner to the ".clone" command.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:dd0db3f0cef1be46cea16d4e61ea3348b3b3bd3e
User & Date: drh 2014-02-06 02:46:08
Context
2014-02-06
13:18
Change the spellfix1 virtual table to deterministically names its shadow tables. check-in: 5219cdfc user: drh tags: trunk
02:46
Add additional error messages and a progress spinner to the ".clone" command. check-in: dd0db3f0 user: drh tags: trunk
01:15
Rename the '.repair' shell command to '.clone'. check-in: 4f9d9562 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

  1539   1539   
  1540   1540   /*
  1541   1541   ** Text of a help message
  1542   1542   */
  1543   1543   static char zHelp[] =
  1544   1544     ".backup ?DB? FILE      Backup DB (default \"main\") to FILE\n"
  1545   1545     ".bail ON|OFF           Stop after hitting an error.  Default OFF\n"
         1546  +  ".clone NEWDB           Clone data into NEWDB from the existing database\n"
  1546   1547     ".databases             List names and files of attached databases\n"
  1547   1548     ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
  1548   1549     "                         If TABLE specified, only dump tables matching\n"
  1549   1550     "                         LIKE pattern TABLE.\n"
  1550   1551     ".echo ON|OFF           Turn command echo on or off\n"
  1551   1552     ".exit                  Exit this program\n"
  1552   1553     ".explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.\n"
................................................................................
  1577   1578     ".open ?FILENAME?       Close existing database and reopen FILENAME\n"
  1578   1579     ".output FILENAME       Send output to FILENAME\n"
  1579   1580     ".output stdout         Send output to the screen\n"
  1580   1581     ".print STRING...       Print literal STRING\n"
  1581   1582     ".prompt MAIN CONTINUE  Replace the standard prompts\n"
  1582   1583     ".quit                  Exit this program\n"
  1583   1584     ".read FILENAME         Execute SQL in FILENAME\n"
  1584         -  ".clone NEWDB           Clone data into NEWDB from the existing database\n"
  1585   1585     ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"
  1586   1586     ".schema ?TABLE?        Show the CREATE statements\n"
  1587   1587     "                         If TABLE specified, only show tables matching\n"
  1588   1588     "                         LIKE pattern TABLE.\n"
  1589   1589     ".separator STRING      Change separator used by output mode and .import\n"
  1590   1590     ".show                  Show the current values for various settings\n"
  1591   1591     ".stats ON|OFF          Turn stats on or off\n"
................................................................................
  1894   1894       p->cTerm = c;
  1895   1895     }
  1896   1896     if( p->z ) p->z[p->n] = 0;
  1897   1897     return p->z;
  1898   1898   }
  1899   1899   
  1900   1900   /*
  1901         -** Try to transfer data for table zTable
         1901  +** Try to transfer data for table zTable.  If an error is seen while
         1902  +** moving forward, try to go backwards.  The backwards movement won't
         1903  +** work for WITHOUT ROWID tables.
  1902   1904   */
  1903   1905   static void tryToCloneData(
  1904   1906     struct callback_data *p,
  1905   1907     sqlite3 *newDb,
  1906   1908     const char *zTable
  1907   1909   ){
  1908   1910     sqlite3_stmt *pQuery = 0; 
................................................................................
  1909   1911     sqlite3_stmt *pInsert = 0;
  1910   1912     char *zQuery = 0;
  1911   1913     char *zInsert = 0;
  1912   1914     int rc;
  1913   1915     int i, j, n;
  1914   1916     int nTable = (int)strlen(zTable);
  1915   1917     int k = 0;
         1918  +  int cnt = 0;
         1919  +  const int spinRate = 10000;
  1916   1920   
  1917   1921     zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
  1918   1922     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  1919   1923     if( rc ){
  1920         -    fprintf(stderr, "Error: (%d) %s on [%s]\n",
         1924  +    fprintf(stderr, "Error %d: %s on [%s]\n",
  1921   1925               sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
  1922   1926               zQuery);
  1923   1927       goto end_data_xfer;
  1924   1928     }
  1925   1929     n = sqlite3_column_count(pQuery);
  1926   1930     zInsert = sqlite3_malloc(200 + nTable + n*3);
  1927   1931     if( zInsert==0 ){
................................................................................
  1934   1938     for(j=1; j<n; j++){
  1935   1939       memcpy(zInsert+i, ",?", 2);
  1936   1940       i += 2;
  1937   1941     }
  1938   1942     memcpy(zInsert+i, ");", 3);
  1939   1943     rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
  1940   1944     if( rc ){
  1941         -    fprintf(stderr, "Error: (%d) %s on [%s]\n",
         1945  +    fprintf(stderr, "Error %d: %s on [%s]\n",
  1942   1946               sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
  1943   1947               zQuery);
  1944   1948       goto end_data_xfer;
  1945   1949     }
  1946   1950     for(k=0; k<2; k++){
  1947   1951       while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
  1948   1952         for(i=0; i<n; i++){
................................................................................
  1969   1973               sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
  1970   1974                                               sqlite3_column_bytes(pQuery,i),
  1971   1975                                               SQLITE_STATIC);
  1972   1976               break;
  1973   1977             }
  1974   1978           }
  1975   1979         } /* End for */
  1976         -      sqlite3_step(pInsert);
         1980  +      rc = sqlite3_step(pInsert);
         1981  +      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
         1982  +        fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
         1983  +                        sqlite3_errmsg(newDb));
         1984  +      }
  1977   1985         sqlite3_reset(pInsert);
         1986  +      cnt++;
         1987  +      if( (cnt%spinRate)==0 ){
         1988  +        printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
         1989  +        fflush(stdout);
         1990  +      }
  1978   1991       } /* End while */
  1979   1992       if( rc==SQLITE_DONE ) break;
  1980   1993       sqlite3_finalize(pQuery);
  1981   1994       sqlite3_free(zQuery);
  1982   1995       zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
  1983   1996                                zTable);
  1984   1997       rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  1985   1998       if( rc ){
  1986         -       fprintf(stderr, "Error: (%d) %s on [%s]\n",
  1987         -          sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
  1988         -          zQuery);
  1989         -       goto end_data_xfer;
         1999  +      fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
         2000  +      break;
  1990   2001       }
  1991   2002     } /* End for(k=0...) */
  1992   2003   
  1993   2004   end_data_xfer:
  1994   2005     sqlite3_finalize(pQuery);
  1995   2006     sqlite3_finalize(pInsert);
  1996   2007     sqlite3_free(zQuery);
................................................................................
  1997   2008     sqlite3_free(zInsert);
  1998   2009   }
  1999   2010   
  2000   2011   
  2001   2012   /*
  2002   2013   ** Try to transfer all rows of the schema that match zWhere.  For
  2003   2014   ** each row, invoke xForEach() on the object defined by that row.
         2015  +** If an error is encountered while moving forward through the
         2016  +** sqlite_master table, try again moving backwards.
  2004   2017   */
  2005   2018   static void tryToCloneSchema(
  2006   2019     struct callback_data *p,
  2007   2020     sqlite3 *newDb,
  2008   2021     const char *zWhere,
  2009   2022     void (*xForEach)(struct callback_data*,sqlite3*,const char*)
  2010   2023   ){
  2011   2024     sqlite3_stmt *pQuery = 0;
  2012   2025     char *zQuery = 0;
  2013   2026     int rc;
  2014   2027     const unsigned char *zName;
  2015   2028     const unsigned char *zSql;
         2029  +  char *zErrMsg = 0;
  2016   2030   
  2017   2031     zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
  2018   2032                              " WHERE %s", zWhere);
  2019   2033     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
  2020   2034     if( rc ){
  2021   2035       fprintf(stderr, "Error: (%d) %s on [%s]\n",
  2022   2036                       sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
................................................................................
  2023   2037                       zQuery);
  2024   2038       goto end_schema_xfer;
  2025   2039     }
  2026   2040     while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
  2027   2041       zName = sqlite3_column_text(pQuery, 0);
  2028   2042       zSql = sqlite3_column_text(pQuery, 1);
  2029   2043       printf("%s... ", zName); fflush(stdout);
  2030         -    sqlite3_exec(newDb, (const char*)zSql, 0, 0, 0);
         2044  +    sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
         2045  +    if( zErrMsg ){
         2046  +      fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
         2047  +      sqlite3_free(zErrMsg);
         2048  +      zErrMsg = 0;
         2049  +    }
  2031   2050       if( xForEach ){
  2032   2051         xForEach(p, newDb, (const char*)zName);
  2033   2052       }
  2034   2053       printf("done\n");
  2035   2054     }
  2036   2055     if( rc!=SQLITE_DONE ){
  2037   2056       sqlite3_finalize(pQuery);
................................................................................
  2045   2064                         zQuery);
  2046   2065         goto end_schema_xfer;
  2047   2066       }
  2048   2067       while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
  2049   2068         zName = sqlite3_column_text(pQuery, 0);
  2050   2069         zSql = sqlite3_column_text(pQuery, 1);
  2051   2070         printf("%s... ", zName); fflush(stdout);
  2052         -      sqlite3_exec(newDb, (const char*)zSql, 0, 0, 0);
         2071  +      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
         2072  +      if( zErrMsg ){
         2073  +        fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
         2074  +        sqlite3_free(zErrMsg);
         2075  +        zErrMsg = 0;
         2076  +      }
  2053   2077         if( xForEach ){
  2054   2078           xForEach(p, newDb, (const char*)zName);
  2055   2079         }
  2056   2080         printf("done\n");
  2057   2081       }
  2058   2082     }
  2059   2083   end_schema_xfer: