** schema TEXT HIDDEN
** );
*/
-#if !defined(SQLITEINT_H)
+#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
typedef unsigned char u8;
-typedef unsigned int u32;
+typedef unsigned long u32;
#endif
SQLITE_EXTENSION_INIT1
/* Only for the sqlite_dbdata table */
u8 *pRec; /* Buffer containing current record */
int nRec; /* Size of pRec[] in bytes */
- int nField; /* Number of fields in pRec */
+ int nHdr; /* Size of header in bytes */
int iField; /* Current field number */
+ u8 *pHdrPtr;
+ u8 *pPtr;
+
sqlite3_int64 iIntkey; /* Integer key value */
};
return 9;
}
+static int dbdataValueBytes(int eType){
+ switch( eType ){
+ case 0: case 8: case 9:
+ case 10: case 11:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return 2;
+ case 3:
+ return 3;
+ case 4:
+ return 4;
+ case 5:
+ return 6;
+ case 6:
+ case 7:
+ return 8;
+ default:
+ return ((eType-12) / 2);
+ }
+}
+
+static void dbdataValue(sqlite3_context *pCtx, int eType, u8 *pData){
+ switch( eType ){
+ case 0:
+ case 10:
+ case 11:
+ sqlite3_result_null(pCtx);
+ break;
+
+ case 8:
+ sqlite3_result_int(pCtx, 0);
+ break;
+ case 9:
+ sqlite3_result_int(pCtx, 1);
+ break;
+
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+ sqlite3_uint64 v = (signed char)pData[0];
+ pData++;
+ switch( eType ){
+ case 7:
+ case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
+ case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
+ case 4: v = (v<<8) + pData[0]; pData++;
+ case 3: v = (v<<8) + pData[0]; pData++;
+ case 2: v = (v<<8) + pData[0]; pData++;
+ }
+
+ if( eType==7 ){
+ double r;
+ memcpy(&r, &v, sizeof(r));
+ sqlite3_result_double(pCtx, r);
+ }else{
+ sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+ }
+ break;
+ }
+
+ default: {
+ int n = ((eType-12) / 2);
+ if( eType % 2 ){
+ sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+ }
+ }
+ }
+}
+
+
/*
** Move a dbdata cursor to the next entry in the file.
*/
}
}
- /* Figure out how many fields in the record */
- pCsr->nField = 0;
iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
- while( iHdr<nHdr ){
- sqlite3_int64 iDummy;
- iHdr += dbdataGetVarint(&pCsr->pRec[iHdr], &iDummy);
- pCsr->nField++;
+ pCsr->nHdr = nHdr;
+ pCsr->pHdrPtr = &pCsr->pRec[iHdr];
+ pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+ pCsr->iField = (bHasRowid ? -1 : 0);
+ }else{
+ pCsr->iField++;
+ if( pCsr->iField>0 ){
+ sqlite3_int64 iType;
+ pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
+ pCsr->pPtr += dbdataValueBytes(iType);
}
-
- pCsr->iField = (bHasRowid ? -2 : -1);
}
-
- pCsr->iField++;
- if( pCsr->iField<pCsr->nField ) return SQLITE_OK;
+
+ if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+ return SQLITE_OK;
+ }
/* Advance to the next cell. The next iteration of the loop will load
** the record and so on. */
dbdataResetCursor(pCsr);
assert( pCsr->iPgno==1 );
if( idxNum & 0x01 ){
- zSchema = sqlite3_value_text(argv[0]);
+ zSchema = (const char*)sqlite3_value_text(argv[0]);
}
if( idxNum & 0x02 ){
pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
+ }else{
+ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
}
if( rc==SQLITE_OK ){
rc = dbdataNext(pCursor);
return rc;
}
-static int dbdataValueBytes(int eType){
- switch( eType ){
- case 0: case 8: case 9:
- case 10: case 11:
- return 0;
- case 1:
- return 1;
- case 2:
- return 2;
- case 3:
- return 3;
- case 4:
- return 4;
- case 5:
- return 6;
- case 6:
- case 7:
- return 8;
- default:
- return ((eType-12) / 2);
- }
-}
-
-static void dbdataValue(sqlite3_context *pCtx, int eType, u8 *pData){
- switch( eType ){
- case 0:
- case 10:
- case 11:
- sqlite3_result_null(pCtx);
- break;
-
- case 8:
- sqlite3_result_int(pCtx, 0);
- break;
- case 9:
- sqlite3_result_int(pCtx, 1);
- break;
-
- case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
- sqlite3_uint64 v = (signed char)pData[0];
- pData++;
- switch( eType ){
- case 7:
- case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
- case 4: v = (v<<8) + pData[0]; pData++;
- case 3: v = (v<<8) + pData[0]; pData++;
- case 2: v = (v<<8) + pData[0]; pData++;
- }
-
- if( eType==7 ){
- double r;
- memcpy(&r, &v, sizeof(r));
- sqlite3_result_double(pCtx, r);
- }else{
- sqlite3_result_int64(pCtx, (sqlite3_int64)v);
- }
- break;
- }
-
- default: {
- int n = ((eType-12) / 2);
- if( eType % 2 ){
- sqlite3_result_text(pCtx, pData, n, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
- }
- }
- }
-}
-
/* Return a column for the sqlite_dbdata table */
static int dbdataColumn(
sqlite3_vtab_cursor *pCursor,
if( pCsr->iField<0 ){
sqlite3_result_int64(ctx, pCsr->iIntkey);
}else{
- int iHdr;
sqlite3_int64 iType;
- sqlite3_int64 iOff;
- int i;
- iHdr = dbdataGetVarint(pCsr->pRec, &iOff);
- for(i=0; i<pCsr->iField; i++){
- iHdr += dbdataGetVarint(&pCsr->pRec[iHdr], &iType);
- iOff += dbdataValueBytes(iType);
- }
- dbdataGetVarint(&pCsr->pRec[iHdr], &iType);
-
- dbdataValue(ctx, iType, &pCsr->pRec[iOff]);
+ dbdataGetVarint(pCsr->pHdrPtr, &iType);
+ dbdataValue(ctx, iType, pCsr->pPtr);
}
break;
}
-C Add\sthe\ssqlite_dbptr\svirtual\stable\sto\sthe\sdbdata\sextension.\sFor\squerying\sthe\slinks\sbetween\sb-tree\spages.
-D 2019-04-18T21:14:11.260
+C Add\sthe\s".recovery"\scommand\sto\sthe\sshell\stool.\sFor\srecovering\sthe\smaximum\samount\sdata\sfrom\scorrupt\sdatabases.\sStill\sneeds\swork.
+D 2019-04-20T20:57:28.136
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
F ext/misc/csv.c 7f047aeb68f5802e7ce6639292095d622a488bb43526ed04810e0649faa71ceb
-F ext/misc/dbdata.c 20d85d7d7503817a5f9ac7d93c4ae7bf5fcc40570a77adc417acab0500058c99
+F ext/misc/dbdata.c 8f74f25565e1f57942f75134ef94ab73058849bed87d92be619be7d3b8a7d054
F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287c336
F ext/misc/eval.c 4b4757592d00fd32e44c7a067e6a0e4839c81a4d57abc4131ee7806d1be3104e
F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 23d3660f7053d196aef76938bf78b10fc3ce1831a85d96bd71565758788f34d4
+F main.mk 125adda36bb32c99dc3a11340bd029ef373b9523eac2b2af76087bfe82d4fdf8
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49
-F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810
+F src/shell.c.in 3646e448cc207fa3118266c2a23f177306b068e42aae6fee64323ffb13307680
F src/sqlite.h.in 38390767acc1914d58930e03149595ee4710afa4e3c43ab6c3a8aea3f1a6b8cd
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl 49039adedafbc430d2959400da2e0e8f20ef8dcf6898e447c946e7d50ef5906b
-F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
+F tool/mkshellc.tcl d18a6769f766bd5a0fd5fd60e6bbde38ed6d1a41fced5fe32ac01ab9d2e0d5ec
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a3ab58832935e1399ecc7e4d8daefa3a6afa6b301792ce7176bc5d7c173510fb
-R 901e9e476021499846a29c847f49c578
+P 3213a15f2133afbb0a4fec3b8f6e0eeca8c0befafd6658c41074e84f589d5d32
+R 9a7e323fe9ebfe9eb0759e1c70136795
U dan
-Z e0c2ac18f5bd53328c7a0485e8c7ef97
+Z 100e3ccaddf1d19d0bacd74d773a93b7
INCLUDE ../ext/expert/sqlite3expert.h
INCLUDE ../ext/expert/sqlite3expert.c
+INCLUDE ../ext/misc/dbdata.c
+
#if defined(SQLITE_ENABLE_SESSION)
/*
** State information for a single open session
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
+#define SHFLG_Recover 0x00000080 /* .dump is --recover */
/*
** Macros for testing and setting shellFlgs
sqlite3_fileio_init(p->db, 0, 0);
sqlite3_shathree_init(p->db, 0, 0);
sqlite3_completion_init(p->db, 0, 0);
+ sqlite3_dbdata_init(p->db, 0, 0);
#ifdef SQLITE_HAVE_ZLIB
sqlite3_zipfile_init(p->db, 0, 0);
sqlite3_sqlar_init(p->db, 0, 0);
**********************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
+static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
+ int rc = *pRc;
+ if( rc==SQLITE_OK ){
+ char *zErr = 0;
+ rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
+ if( rc!=SQLITE_OK ){
+ raw_printf(stderr, "SQL error: %s\n", zErr);
+ }
+ *pRc = rc;
+ }
+}
+
+static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
+ void *pRet = 0;
+ if( *pRc==SQLITE_OK ){
+ pRet = sqlite3_malloc64(nByte);
+ if( pRet==0 ){
+ *pRc = SQLITE_NOMEM;
+ }else{
+ memset(pRet, 0, nByte);
+ }
+ }
+ return pRet;
+}
+
+static char *shellMPrintf(int *pRc, const char *zFmt, ...){
+ char *z = 0;
+ if( *pRc==SQLITE_OK ){
+ va_list ap;
+ va_start(ap, zFmt);
+ z = sqlite3_vmprintf(zFmt, ap);
+ va_end(ap);
+ if( z==0 ){
+ *pRc = SQLITE_NOMEM;
+ }
+ }
+ return z;
+}
+
+typedef struct RecoverTable RecoverTable;
+struct RecoverTable {
+ char *zName; /* Name of table */
+ char *zQuoted; /* Quoted version of zName */
+ char *zCreate; /* SQL to create table in default schema */
+ int nCol; /* Number of columns in table */
+ char **azlCol; /* Array of column lists */
+};
+
+/*
+** Free a RecoverTable object allocated by recoverNewTable()
+*/
+static void recoverFreeTable(RecoverTable *pTab){
+ if( pTab ){
+ sqlite3_free(pTab->zName);
+ sqlite3_free(pTab->zQuoted);
+ sqlite3_free(pTab->zCreate);
+ if( pTab->azlCol ){
+ int i;
+ for(i=0; i<pTab->nCol; i++){
+ sqlite3_free(pTab->azlCol[i]);
+ }
+ sqlite3_free(pTab->azlCol);
+ }
+ sqlite3_free(pTab);
+ }
+}
+
+static RecoverTable *recoverNewTable(
+ ShellState *pState,
+ int *pRc,
+ int iRoot,
+ int nCol
+){
+ RecoverTable *pRet = 0;
+
+ pRet = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
+ if( pRet ){
+ sqlite3_stmt *pStmt = 0;
+ pRet->zName = shellMPrintf(pRc, "orphan_%d_%d", nCol, iRoot);
+ pRet->zQuoted = shellMPrintf(pRc, "%Q", pRet->zName);
+ pRet->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * nCol);
+ pRet->nCol = nCol;
+
+ shellPreparePrintf(pState->db, pRc, &pStmt,
+ "WITH s(i) AS ("
+ " SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<%d"
+ ")"
+ "SELECT i-1, group_concat('c' || i, ', ') OVER (ORDER BY i) FROM s",
+ nCol
+ );
+ while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ int idx = sqlite3_column_int(pStmt, 0);
+ const char *zText = (const char*)sqlite3_column_text(pStmt, 1);
+ pRet->azlCol[idx] = shellMPrintf(pRc, "%s", zText);
+ }
+ shellFinalize(pRc, pStmt);
+
+ pRet->zCreate = shellMPrintf(pRc, "CREATE TABLE %Q (id, %s)",
+ pRet->zName, pRet->azlCol[nCol-1]
+ );
+ }
+
+ if( *pRc!=SQLITE_OK ){
+ recoverFreeTable(pRet);
+ pRet = 0;
+ }
+
+ return pRet;
+}
+
+/*
+** This function is called to recover data from the database. A script
+** to construct a new database containing all recovered data is output
+** on stream pState->out.
+*/
+static int recoverDatabaseCmd(ShellState *pState){
+ const char *zSql;
+ int rc = SQLITE_OK;
+ sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
+
+ shellExec(pState->db, &rc,
+ /* Attach an in-memory database named 'recovery'. Create an indexed
+ ** cache of the sqlite_dbptr virtual table. */
+ "ATTACH '' AS recovery;"
+ "CREATE TABLE recovery.dbptr("
+ " pgno, child, PRIMARY KEY(child, pgno)"
+ ") WITHOUT ROWID;"
+ "INSERT OR IGNORE INTO dbptr(pgno, child) SELECT * FROM sqlite_dbptr;"
+
+ /* Delete any pointer to page 1. This ensures that page 1 is considered
+ ** a root page, regardless of how corrupt the db is. */
+ "DELETE FROM recovery.dbptr WHERE child = 1;"
+
+ /* Delete all pointers to any pages that have more than one pointer
+ ** to them. Such pages will be treated as root pages when recovering
+ ** data. */
+ "DELETE FROM recovery.dbptr WHERE child IN ("
+ " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
+ ");"
+
+ /* Create the "map" table that will (eventually) contain instructions
+ ** for dealing with each page in the db that contains one or more
+ ** records. */
+ "CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, maxlen INT, root INT);"
+
+ /* Populate table [map]. If there are circular loops of pages in the
+ ** database, the following adds all pages in such a loop to the map
+ ** as individual root pages. This could be handled better. */
+ "WITH pages(i, maxlen) AS ("
+ " SELECT page_count, max(field+1) "
+ " FROM pragma_page_count, sqlite_dbdata WHERE pgno=page_count"
+ " UNION ALL"
+ " SELECT * FROM (SELECT i-1, max(field+1)"
+ " FROM pages, sqlite_dbdata WHERE pgno=i-1 AND i>=2)"
+ ")"
+ "INSERT INTO recovery.map(pgno, maxlen, root) SELECT i, maxlen, ("
+ " WITH p(orig, pgno, parent) AS ("
+ " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
+ " UNION ALL"
+ " SELECT i, p.parent, "
+ " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
+ " )"
+ " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
+ ") "
+ "FROM pages WHERE maxlen > 0;"
+
+ /* Extract data from page 1 and any linked pages into table
+ ** recovery.schema. With the same schema as an sqlite_master table. */
+ "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
+ "INSERT INTO recovery.schema SELECT "
+ " max(CASE WHEN field=0 THEN value ELSE NULL END),"
+ " max(CASE WHEN field=1 THEN value ELSE NULL END),"
+ " max(CASE WHEN field=2 THEN value ELSE NULL END),"
+ " max(CASE WHEN field=3 THEN value ELSE NULL END),"
+ " max(CASE WHEN field=4 THEN value ELSE NULL END)"
+ "FROM sqlite_dbdata WHERE pgno IN ("
+ " SELECT pgno FROM recovery.map WHERE root=1"
+ ")"
+ "GROUP BY pgno, cell;"
+ );
+
+#if 0
+ zSql = "SELECT type ||','|| name ||','|| tbl_name ||','|| rootpage ||','|| sql FROM recovery.schema;";
+ shellPrepare(pState->db, &rc, zSql, &pLoop);
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
+ raw_printf(pState->out, "%s\n", (const char*)sqlite3_column_text(pLoop, 0));
+ }
+ shellFinalize(&rc, pLoop);
+ return rc;
+#endif
+
+ /* Loop through each root page. */
+ zSql = "SELECT root,max(maxlen) FROM recovery.map WHERE root>1 GROUP BY root";
+ shellPrepare(pState->db, &rc, zSql, &pLoop);
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
+ int iRoot = sqlite3_column_int(pLoop, 0);
+ int nCol = sqlite3_column_int(pLoop, 1);
+ RecoverTable *pTab;
+
+ pTab = recoverNewTable(pState, &rc, iRoot, nCol);
+ if( pTab ){
+ sqlite3_stmt *pData = 0;
+ raw_printf(pState->out, "%s;\n", pTab->zCreate);
+ shellPreparePrintf(pState->db, &rc, &pData,
+ "SELECT max(field), group_concat(quote(value), ', ') "
+ "FROM sqlite_dbdata WHERE pgno IN ("
+ " SELECT pgno FROM recovery.map WHERE root=%d"
+ ")"
+ "GROUP BY pgno, cell;", iRoot
+ );
+ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pData) ){
+ int iMax = sqlite3_column_int(pData, 0);
+ const char *zVal = (const char*)sqlite3_column_text(pData, 1);
+ if( iMax+1==pTab->nCol ){
+ raw_printf(pState->out, "INSERT INTO %s VALUES( %s );\n",
+ pTab->zQuoted, zVal);
+ }else{
+ raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
+ pTab->zQuoted, pTab->azlCol[iMax], zVal
+ );
+ }
+ }
+ shellFinalize(&rc, pData);
+ }
+ recoverFreeTable(pTab);
+ }
+ shellFinalize(&rc, pLoop);
+
+ sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
+ return rc;
+}
+
/*
** If an input line begins with "." then invoke this routine to
rc = shell_dbinfo_command(p, nArg, azArg);
}else
+ if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
+ open_db(p, 0);
+ rc = recoverDatabaseCmd(p);
+ }else
+
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
const char *zLike = 0;
int i;
zLike = azArg[i];
}
}
+
open_db(p, 0);
+
/* When playing back a "dump", the content might appear in an order
** which causes immediate foreign key constraints to be violated.
** So disable foreign-key constraint enforcement to prevent problems. */
p->nErr = 0;
if( zLike==0 ){
run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
- );
+ "SELECT name, type, sql FROM sqlite_master "
+ "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
+ );
run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE name=='sqlite_sequence'"
- );
+ "SELECT name, type, sql FROM sqlite_master "
+ "WHERE name=='sqlite_sequence'"
+ );
run_table_dump_query(p,
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
- );
+ "SELECT sql FROM sqlite_master "
+ "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
+ );
}else{
char *zSql;
zSql = sqlite3_mprintf(
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE tbl_name LIKE %Q AND type=='table'"
- " AND sql NOT NULL", zLike);
+ "SELECT name, type, sql FROM sqlite_master "
+ "WHERE tbl_name LIKE %Q AND type=='table'"
+ " AND sql NOT NULL", zLike);
run_schema_dump_query(p,zSql);
sqlite3_free(zSql);
zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL"
- " AND type IN ('index','trigger','view')"
- " AND tbl_name LIKE %Q", zLike);
+ "SELECT sql FROM sqlite_master "
+ "WHERE sql NOT NULL"
+ " AND type IN ('index','trigger','view')"
+ " AND tbl_name LIKE %Q", zLike);
run_table_dump_query(p, zSql, 0);
sqlite3_free(zSql);
}
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
p->showHeader = savedShowHeader;
p->shellFlgs = savedShellFlags;
}else