1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Fix handling of schema mismatches in sqlite3session.c so that it matches the docs in sqlite3session.h.

FossilOrigin-Name: 506a0d7a710e1ff2f367821e73f5080fcf63fbc5
This commit is contained in:
dan
2011-03-24 16:04:54 +00:00
parent 244593c846
commit ca62ad57f0
5 changed files with 142 additions and 23 deletions

View File

@ -544,7 +544,7 @@ static int sessionTableInfo(
sqlite3 *db, /* Database connection */
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
int nCol, /* Expected number of columns */
int *pnCol, /* OUT: number of columns */
const char **pzTab, /* OUT: Copy of zThis */
const char ***pazCol, /* OUT: Array of column names for table */
u8 **pabPK /* OUT: Array of booleans - true for PK col */
@ -577,9 +577,6 @@ static int sessionTableInfo(
}
rc = sqlite3_reset(pStmt);
if( nDbCol!=nCol ){
rc = SQLITE_SCHEMA;
}
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
pAlloc = sqlite3_malloc(nByte);
@ -589,9 +586,9 @@ static int sessionTableInfo(
}
if( rc==SQLITE_OK ){
azCol = (char **)pAlloc;
pAlloc = (u8 *)&azCol[nCol];
pAlloc = (u8 *)&azCol[nDbCol];
abPK = (u8 *)pAlloc;
pAlloc = &abPK[nCol];
pAlloc = &abPK[nDbCol];
if( pzTab ){
memcpy(pAlloc, zThis, nThis+1);
*pzTab = (char *)pAlloc;
@ -619,9 +616,11 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
*pazCol = (const char **)azCol;
*pabPK = abPK;
*pnCol = nDbCol;
}else{
*pazCol = 0;
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
sqlite3_free(azCol);
}
@ -648,11 +647,13 @@ static int sessionTableInfo(
static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
if( pTab->nCol==0 ){
assert( pTab->azCol==0 || pTab->abPK==0 );
pTab->nCol = sqlite3_preupdate_count(pSession->db);
pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
pTab->zName, pTab->nCol, 0, &pTab->azCol, &pTab->abPK
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->abPK
);
}else if( pTab->nCol!=sqlite3_preupdate_count(pSession->db) ){
}
if( pSession->rc==SQLITE_OK
&& pTab->nCol!=sqlite3_preupdate_count(pSession->db)
){
pSession->rc = SQLITE_SCHEMA;
}
return pSession->rc;
@ -2402,6 +2403,7 @@ int sqlite3changeset_apply(
),
void *pCtx /* First argument passed to xConflict */
){
int schemaMismatch = 0;
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int rc; /* Return code */
const char *zTab = 0; /* Name of current table */
@ -2420,9 +2422,13 @@ int sqlite3changeset_apply(
int bReplace = 0;
int bRetry = 0;
const char *zNew;
sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0);
if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){
u8 *abPK;
schemaMismatch = 0;
sqlite3_free(sApply.azCol);
sqlite3_finalize(sApply.pDelete);
sqlite3_finalize(sApply.pUpdate);
@ -2430,23 +2436,47 @@ int sqlite3changeset_apply(
sqlite3_finalize(sApply.pSelect);
memset(&sApply, 0, sizeof(sApply));
sApply.db = db;
sApply.nCol = nCol;
sqlite3changeset_pk(pIter, &abPK, 0);
rc = sessionTableInfo(
db, "main", zNew, nCol, &zTab, &sApply.azCol, &sApply.abPK);
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
if( rc!=SQLITE_OK
|| (rc = sessionSelectRow(db, zTab, &sApply))
if( sApply.nCol==0 ){
schemaMismatch = 1;
sqlite3_log(SQLITE_SCHEMA,
"sqlite3changeset_apply(): no such table: %s", zTab
);
}
else if( sApply.nCol!=nCol ){
schemaMismatch = 1;
sqlite3_log(SQLITE_SCHEMA,
"sqlite3changeset_apply(): table %s has %d columns, expected %d",
zTab, sApply.nCol, nCol
);
}
else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){
schemaMismatch = 1;
sqlite3_log(SQLITE_SCHEMA,
"sqlite3changeset_apply(): primary key mismatch for table %s", zTab
);
}
else if(
(rc = sessionSelectRow(db, zTab, &sApply))
|| (rc = sessionUpdateRow(db, zTab, &sApply))
|| (rc = sessionDeleteRow(db, zTab, &sApply))
|| (rc = sessionInsertRow(db, zTab, &sApply))
){
break;
}
nTab = strlen(zTab);
}
/* If there is a schema mismatch on the current table, proceed to the
** next change. A log message has already been issued. */
if( schemaMismatch ) continue;
rc = sessionApplyOneOp(pIter, &sApply, xConflict, pCtx, &bReplace, &bRetry);
if( rc==SQLITE_OK && bRetry ){