Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: third_party/sqlite/src/tool/sqldiff.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/sqlite/src/tool/speed-check.sh ('k') | third_party/sqlite/src/tool/srcck1.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/sqlite/src/tool/sqldiff.c
diff --git a/third_party/sqlite/src/tool/sqldiff.c b/third_party/sqlite/src/tool/sqldiff.c
index 56ff53ee25766d6e4941c60a1f85c5a73a89c73a..67f3197bbfeb75a04a75fa43a84a9b59ae9642d5 100644
--- a/third_party/sqlite/src/tool/sqldiff.c
+++ b/third_party/sqlite/src/tool/sqldiff.c
@@ -33,6 +33,7 @@ struct GlobalVars {
const char *zArgv0; /* Name of program */
int bSchemaOnly; /* Only show schema differences */
int bSchemaPK; /* Use the schema-defined PK, not the true PK */
+ int bHandleVtab; /* Handle fts3, fts4, fts5 and rtree vtabs */
unsigned fDebug; /* Debug flags */
sqlite3 *db; /* The database connection */
} g;
@@ -402,7 +403,8 @@ static void printQuoted(FILE *out, sqlite3_value *X){
}
fprintf(out, "'");
}else{
- fprintf(out, "NULL");
+ /* Could be an OOM, could be a zero-byte blob */
+ fprintf(out, "X''");
}
break;
}
@@ -683,7 +685,7 @@ static void diff_one_table(const char *zTab, FILE *out){
/* Run the query and output differences */
if( !g.bSchemaOnly ){
- pStmt = db_prepare(sql.z);
+ pStmt = db_prepare("%s", sql.z);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
int iType = sqlite3_column_int(pStmt, nPk);
if( iType==1 || iType==2 ){
@@ -994,7 +996,7 @@ static int rbuDeltaCreate(
zDelta += lenOut;
putInt(checksum(zOut, lenOut), &zDelta);
*(zDelta++) = ';';
- return zDelta - zOrigDelta;
+ return (int)(zDelta - zOrigDelta);
}
/* Compute the hash table used to locate matching sections in the
@@ -1141,7 +1143,7 @@ static int rbuDeltaCreate(
putInt(checksum(zOut, lenOut), &zDelta);
*(zDelta++) = ';';
sqlite3_free(collide);
- return zDelta - zOrigDelta;
+ return (int)(zDelta - zOrigDelta);
}
/*
@@ -1178,8 +1180,9 @@ static void getRbudiffQuery(
strPrintf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
strPrintf(pSql, " SELECT 1 FROM ", zTab);
strPrintf(pSql, " main.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n)");
+ strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
+ strPrintf(pSql, "\n) AND ");
+ strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
/* Deleted rows: */
strPrintf(pSql, "\nUNION ALL\nSELECT ");
@@ -1193,8 +1196,9 @@ static void getRbudiffQuery(
strPrintf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
strPrintf(pSql, " SELECT 1 FROM ", zTab);
strPrintf(pSql, " aux.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) ");
+ strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
+ strPrintf(pSql, "\n) AND ");
+ strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
/* Updated rows. If all table columns are part of the primary key, there
** can be no updates. In this case this part of the compound SELECT can
@@ -1225,7 +1229,7 @@ static void getRbudiffQuery(
);
strPrintf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ", zTab, zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
+ strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
strPrintf(pSql, " AND ota_control LIKE '%%x%%'");
}
@@ -1244,6 +1248,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
Str sql = {0, 0, 0}; /* Query to find differences */
Str insert = {0, 0, 0}; /* First part of output INSERT statement */
sqlite3_stmt *pStmt = 0;
+ int nRow = 0; /* Total rows in data_xxx table */
/* --rbu mode must use real primary keys. */
g.bSchemaPK = 1;
@@ -1289,6 +1294,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
/* Output the first part of the INSERT statement */
fprintf(out, "%s", insert.z);
+ nRow++;
if( sqlite3_column_type(pStmt, nCol)==SQLITE_INTEGER ){
for(i=0; i<=nCol; i++){
@@ -1299,7 +1305,7 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
char *zOtaControl;
int nOtaControl = sqlite3_column_bytes(pStmt, nCol);
- zOtaControl = (char*)sqlite3_malloc(nOtaControl);
+ zOtaControl = (char*)sqlite3_malloc(nOtaControl+1);
memcpy(zOtaControl, sqlite3_column_text(pStmt, nCol), nOtaControl+1);
for(i=0; i<nCol; i++){
@@ -1342,6 +1348,12 @@ static void rbudiff_one_table(const char *zTab, FILE *out){
}
sqlite3_finalize(pStmt);
+ if( nRow>0 ){
+ Str cnt = {0, 0, 0};
+ strPrintf(&cnt, "INSERT INTO rbu_count VALUES('data_%q', %d);", zTab, nRow);
+ fprintf(out, "%s\n", cnt.z);
+ strFree(&cnt);
+ }
strFree(&ct);
strFree(&sql);
@@ -1452,7 +1464,7 @@ static void summarize_one_table(const char *zTab, FILE *out){
}
/* Run the query and output difference summary */
- pStmt = db_prepare(sql.z);
+ pStmt = db_prepare("%s", sql.z);
nUpdate = 0;
nInsert = 0;
nDelete = 0;
@@ -1728,6 +1740,144 @@ end_changeset_one_table:
}
/*
+** Extract the next SQL keyword or quoted string from buffer zIn and copy it
+** (or a prefix of it if it will not fit) into buffer zBuf, size nBuf bytes.
+** Return a pointer to the character within zIn immediately following
+** the token or quoted string just extracted.
+*/
+const char *gobble_token(const char *zIn, char *zBuf, int nBuf){
+ const char *p = zIn;
+ char *pOut = zBuf;
+ char *pEnd = &pOut[nBuf-1];
+ char q = 0; /* quote character, if any */
+
+ if( p==0 ) return 0;
+ while( *p==' ' ) p++;
+ switch( *p ){
+ case '"': q = '"'; break;
+ case '\'': q = '\''; break;
+ case '`': q = '`'; break;
+ case '[': q = ']'; break;
+ }
+
+ if( q ){
+ p++;
+ while( *p && pOut<pEnd ){
+ if( *p==q ){
+ p++;
+ if( *p!=q ) break;
+ }
+ if( pOut<pEnd ) *pOut++ = *p;
+ p++;
+ }
+ }else{
+ while( *p && *p!=' ' && *p!='(' ){
+ if( pOut<pEnd ) *pOut++ = *p;
+ p++;
+ }
+ }
+
+ *pOut = '\0';
+ return p;
+}
+
+/*
+** This function is the implementation of SQL scalar function "module_name":
+**
+** module_name(SQL)
+**
+** The only argument should be an SQL statement of the type that may appear
+** in the sqlite_master table. If the statement is a "CREATE VIRTUAL TABLE"
+** statement, then the value returned is the name of the module that it
+** uses. Otherwise, if the statement is not a CVT, NULL is returned.
+*/
+static void module_name_func(
+ sqlite3_context *pCtx,
+ int nVal, sqlite3_value **apVal
+){
+ const char *zSql;
+ char zToken[32];
+
+ assert( nVal==1 );
+ zSql = (const char*)sqlite3_value_text(apVal[0]);
+
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+ if( zSql==0 || sqlite3_stricmp(zToken, "create") ) return;
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+ if( zSql==0 || sqlite3_stricmp(zToken, "virtual") ) return;
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+ if( zSql==0 || sqlite3_stricmp(zToken, "table") ) return;
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+ if( zSql==0 ) return;
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+ if( zSql==0 || sqlite3_stricmp(zToken, "using") ) return;
+ zSql = gobble_token(zSql, zToken, sizeof(zToken));
+
+ sqlite3_result_text(pCtx, zToken, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** Return the text of an SQL statement that itself returns the list of
+** tables to process within the database.
+*/
+const char *all_tables_sql(){
+ if( g.bHandleVtab ){
+ int rc;
+
+ rc = sqlite3_exec(g.db,
+ "CREATE TEMP TABLE tblmap(module COLLATE nocase, postfix);"
+ "INSERT INTO temp.tblmap VALUES"
+ "('fts3', '_content'), ('fts3', '_segments'), ('fts3', '_segdir'),"
+
+ "('fts4', '_content'), ('fts4', '_segments'), ('fts4', '_segdir'),"
+ "('fts4', '_docsize'), ('fts4', '_stat'),"
+
+ "('fts5', '_data'), ('fts5', '_idx'), ('fts5', '_content'),"
+ "('fts5', '_docsize'), ('fts5', '_config'),"
+
+ "('rtree', '_node'), ('rtree', '_rowid'), ('rtree', '_parent');"
+ , 0, 0, 0
+ );
+ assert( rc==SQLITE_OK );
+
+ rc = sqlite3_create_function(
+ g.db, "module_name", 1, SQLITE_UTF8, 0, module_name_func, 0, 0
+ );
+ assert( rc==SQLITE_OK );
+
+ return
+ "SELECT name FROM main.sqlite_master\n"
+ " WHERE type='table' AND (\n"
+ " module_name(sql) IS NULL OR \n"
+ " module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
+ " ) AND name NOT IN (\n"
+ " SELECT a.name || b.postfix \n"
+ "FROM main.sqlite_master AS a, temp.tblmap AS b \n"
+ "WHERE module_name(a.sql) = b.module\n"
+ " )\n"
+ "UNION \n"
+ "SELECT name FROM aux.sqlite_master\n"
+ " WHERE type='table' AND (\n"
+ " module_name(sql) IS NULL OR \n"
+ " module_name(sql) IN (SELECT module FROM temp.tblmap)\n"
+ " ) AND name NOT IN (\n"
+ " SELECT a.name || b.postfix \n"
+ "FROM aux.sqlite_master AS a, temp.tblmap AS b \n"
+ "WHERE module_name(a.sql) = b.module\n"
+ " )\n"
+ " ORDER BY name";
+ }else{
+ return
+ "SELECT name FROM main.sqlite_master\n"
+ " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
+ " UNION\n"
+ "SELECT name FROM aux.sqlite_master\n"
+ " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
+ " ORDER BY name";
+ }
+}
+
+/*
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
@@ -1743,6 +1893,7 @@ static void showHelp(void){
" --summary Show only a summary of the differences\n"
" --table TAB Show only differences in table TAB\n"
" --transaction Show SQL output inside a transaction\n"
+" --vtab Handle fts3, fts4, fts5 and rtree tables\n"
);
}
@@ -1757,8 +1908,10 @@ int main(int argc, char **argv){
char *zTab = 0;
FILE *out = stdout;
void (*xDiff)(const char*,FILE*) = diff_one_table;
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
int nExt = 0;
char **azExt = 0;
+#endif
int useTransaction = 0;
int neverUseTransaction = 0;
@@ -1811,6 +1964,9 @@ int main(int argc, char **argv){
if( strcmp(z,"transaction")==0 ){
useTransaction = 1;
}else
+ if( strcmp(z,"vtab")==0 ){
+ g.bHandleVtab = 1;
+ }else
{
cmdlineError("unknown option: %s", argv[i]);
}
@@ -1841,8 +1997,8 @@ int main(int argc, char **argv){
cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
}
}
-#endif
free(azExt);
+#endif
zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
if( rc || zErrMsg ){
@@ -1854,19 +2010,18 @@ int main(int argc, char **argv){
}
if( neverUseTransaction ) useTransaction = 0;
- if( useTransaction ) printf("BEGIN TRANSACTION;\n");
+ if( useTransaction ) fprintf(out, "BEGIN TRANSACTION;\n");
+ if( xDiff==rbudiff_one_table ){
+ fprintf(out, "CREATE TABLE IF NOT EXISTS rbu_count"
+ "(tbl TEXT PRIMARY KEY COLLATE NOCASE, cnt INTEGER) "
+ "WITHOUT ROWID;\n"
+ );
+ }
if( zTab ){
xDiff(zTab, out);
}else{
/* Handle tables one by one */
- pStmt = db_prepare(
- "SELECT name FROM main.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " UNION\n"
- "SELECT name FROM aux.sqlite_master\n"
- " WHERE type='table' AND sql NOT LIKE 'CREATE VIRTUAL%%'\n"
- " ORDER BY name"
- );
+ pStmt = db_prepare("%s", all_tables_sql() );
while( SQLITE_ROW==sqlite3_step(pStmt) ){
xDiff((const char*)sqlite3_column_text(pStmt,0), out);
}
« no previous file with comments | « third_party/sqlite/src/tool/speed-check.sh ('k') | third_party/sqlite/src/tool/srcck1.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698