# # patch "ChangeLog" # from [a15e74590ec8cf1f93bf9092b96c23eec64d00de] # to [7dcf83a1f5e8245b181a95b2ec16a97d4a57de1b] # # patch "database.cc" # from [fbfde0c769bcd4355cb09beb67d6b6ad826f1e96] # to [31bf34b9a9899ae714bd8cb34c880d49f851ca69] # # patch "sqlite/sqlite3.h" # from [cc5e1e2dfeb2a834e420412da25a92b742d76711] # to [7b7b319cea0de0a53fe74689c4dbca93828fa6bd] # # patch "sqlite/tokenize.c" # from [103cbaa932c790f540f8eceb63cd3010e117bdff] # to [add95e9afcf12b9d821e5c7a75f191e94ede3f62] # --- ChangeLog +++ ChangeLog @@ -1,3 +1,12 @@ +2005-07-03 Matthew Gregan + + * sqlite/{sqlite3.h,tokenize.c} (sqlite3_complete_last): New + function to find the last valid SQL statement in a string; based + on sqlite3_complete. This change should be offered upstream, but + probably not before sqlite3_complete_last16 is implemented. + * database.cc (database::load): Load and execute dump in chunks, + fixes bug 13570. + 2005-07-01 Matthew Gregan * tests/t_cvsimport_drepper2.at: Canonicalise monotone output so --- database.cc +++ database.cc @@ -345,11 +345,19 @@ if (error) throw oops(string("could not open database: ") + filename.string() + (string(sqlite3_errmsg(__sql)))); - + while(in) { in.read(buf, constants::bufsz); tmp.append(buf, in.gcount()); + + const char* last_statement = 0; + sqlite3_complete_last(tmp.c_str(), &last_statement); + if (last_statement == 0) + continue; + string::size_type len = last_statement + 1 - tmp.c_str(); + execute(tmp.substr(0, len).c_str()); + tmp.erase(0, len); } execute(tmp.c_str()); --- sqlite/sqlite3.h +++ sqlite/sqlite3.h @@ -257,8 +257,10 @@ ** false. */ int sqlite3_complete(const char *sql); +int sqlite3_complete_last(const char *sql, const char **last); int sqlite3_complete16(const void *sql); + /* ** This routine identifies a callback function that is invoked ** whenever an attempt is made to open a database table that is --- sqlite/tokenize.c +++ sqlite/tokenize.c @@ -500,8 +500,14 @@ ** is look for a semicolon that is not part of an string or comment. */ int sqlite3_complete(const char *zSql){ + const char *tmp; + return sqlite3_complete_last(zSql, &tmp); +} + +int sqlite3_complete_last(const char *zSql, const char **last){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ + const char* lastseen = 0; #ifndef SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER @@ -551,7 +557,7 @@ } zSql += 2; while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } - if( zSql[0]==0 ) return 0; + if( zSql[0]==0 ) { *last = lastseen; return 0; } zSql++; token = tkWS; break; @@ -562,14 +568,14 @@ break; } while( *zSql && *zSql!='\n' ){ zSql++; } - if( *zSql==0 ) return state==0; + if( *zSql==0 ) { *last = lastseen; return state==0; } token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } - if( *zSql==0 ) return 0; + if( *zSql==0 ) { *last = lastseen; return 0; } token = tkOTHER; break; } @@ -578,7 +584,7 @@ int c = *zSql; zSql++; while( *zSql && *zSql!=c ){ zSql++; } - if( *zSql==0 ) return 0; + if( *zSql==0 ) { *last = lastseen; return 0; } token = tkOTHER; break; } @@ -641,8 +647,11 @@ } } state = trans[state][token]; + if (state == 0) + lastseen = zSql; zSql++; } + *last = lastseen; return state==0; }