mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Have sqlite3changeset_concat() return SQLITE_SCHEMA if an attempt is made to concatenate changesets based on incompatible database schemas.
FossilOrigin-Name: 343b64517d244b75097e38342dc273eb5a52915b
This commit is contained in:
@ -63,6 +63,9 @@ proc do_concat_test {tn args} {
|
||||
catch { s_prev delete }
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases session5-1.* - simple tests.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
}
|
||||
@ -134,12 +137,15 @@ do_concat_test 1.2.7 {
|
||||
DELETE FROM t1 WHERE a = 'I';
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases session5-2.* - more complex tests.
|
||||
#
|
||||
db function indirect indirect
|
||||
proc indirect {{x -1}} {
|
||||
S indirect $x
|
||||
s_prev indirect $x
|
||||
}
|
||||
|
||||
do_concat_test 2.1 {
|
||||
CREATE TABLE abc(a, b, c PRIMARY KEY);
|
||||
INSERT INTO abc VALUES(NULL, NULL, 1);
|
||||
@ -185,4 +191,52 @@ do_concat_test 2.1 {
|
||||
UPDATE abc SET a='one point six' WHERE c = 'three';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that schema incompatibilities are detected correctly.
|
||||
#
|
||||
# session5-3.1: Incompatible number of columns.
|
||||
# session5-3.2: Incompatible PK definition.
|
||||
#
|
||||
proc sql_to_changeset {sql} {
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
execsql $sql
|
||||
set c [S changeset]
|
||||
S delete
|
||||
return $c
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
|
||||
set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }]
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
}
|
||||
set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3, 4) }]
|
||||
|
||||
list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
|
||||
do_test 3.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
|
||||
set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }]
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a, b PRIMARY KEY);
|
||||
}
|
||||
set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3) }]
|
||||
|
||||
list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -2862,19 +2862,28 @@ int sessionConcatChangeset(
|
||||
if( !pTab || zNew!=pTab->zName ){
|
||||
/* Search the list for a matching table */
|
||||
int nNew = strlen(zNew);
|
||||
u8 *abPK;
|
||||
|
||||
sqlite3changeset_pk(pIter, &abPK, 0);
|
||||
for(pTab = *ppTabList; pTab; pTab=pTab->pNext){
|
||||
if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break;
|
||||
}
|
||||
if( !pTab ){
|
||||
pTab = sqlite3_malloc(sizeof(SessionTable));
|
||||
if( !pTab ) break;
|
||||
if( !pTab ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
memset(pTab, 0, sizeof(SessionTable));
|
||||
pTab->pNext = *ppTabList;
|
||||
pTab->abPK = abPK;
|
||||
pTab->nCol = nCol;
|
||||
*ppTabList = pTab;
|
||||
}else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){
|
||||
rc = SQLITE_SCHEMA;
|
||||
break;
|
||||
}
|
||||
pTab->zName = (char *)zNew;
|
||||
pTab->nCol = nCol;
|
||||
sqlite3changeset_pk(pIter, &pTab->abPK, 0);
|
||||
}
|
||||
|
||||
if( sessionGrowHash(pTab) ) break;
|
||||
|
Reference in New Issue
Block a user