From: dan Date: Thu, 10 Apr 2025 16:48:04 +0000 (+0000) Subject: Improve the error messages returned by sqlite3session_diff(). X-Git-Tag: major-release~109 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da00cc101c208caeddfef8b1739d390a2bc60f8a;p=thirdparty%2Fsqlite.git Improve the error messages returned by sqlite3session_diff(). FossilOrigin-Name: a3217cdb75fd305705856f6504f8816c2b6b0a10907725cb74d025a5c4e369b8 --- diff --git a/ext/session/sessionD.test b/ext/session/sessionD.test index f60fbabc2a..74bb101e31 100644 --- a/ext/session/sessionD.test +++ b/ext/session/sessionD.test @@ -202,7 +202,7 @@ do_test 4.3.1 { S attach t4 execsql { CREATE TABLE t4(i PRIMARY KEY, b) } list [catch { S diff ixua t4 } msg] $msg -} {1 {SQLITE_SCHEMA - table schemas do not match}} +} {1 {SQLITE_SCHEMA - no such table: ixua.t4}} S delete do_catchsql_test 4.3.2 { SELECT * FROM ixua.t4; @@ -214,7 +214,7 @@ do_test 4.4.1 { execsql { ANALYZE } execsql { DROP TABLE ixua.sqlite_stat1 } list [catch { S diff ixua sqlite_stat1 } msg] $msg -} {1 {SQLITE_SCHEMA - table schemas do not match}} +} {1 {SQLITE_SCHEMA - no such table: ixua.sqlite_stat1}} S delete do_catchsql_test 4.4.2 { SELECT * FROM ixua.sqlite_stat1; @@ -258,4 +258,42 @@ do_changeset_test 4.2 S { S delete +#------------------------------------------------------------------------- +# Test that sqlite3session_diff() really does return errors if +# +reset_db +forcedelete test.db2 +do_execsql_test 5.0 { + ATTACH 'test.db2' AS two; + CREATE TABLE main.t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE main.t2(a INTEGER PRIMARY KEY, b); + CREATE TABLE two.t1(a, b INTEGER PRIMARY KEY); +} + +proc do_sessions_diff_error {tn db tbl err} { + sqlite3session S db main + set rc [catch {S diff $db $tbl} msg] + + set ::sdgot [list $rc $msg] + do_test $tn [list set sdgot] [list {*}$err] + + S delete +} + +# Test that it is an error if the named db is missing. +breakpoint +do_sessions_diff_error 5.1 nosuchdb t1 { + 1 {SQLITE_SCHEMA - no such table: nosuchdb.t1} +} + +# Test that it is an error if the named db is present, but named table is not. +do_sessions_diff_error 5.2 two t2 { + 1 {SQLITE_SCHEMA - no such table: two.t2} +} + +# Test that it is an error if the tables are present, but schemas do not match. +do_sessions_diff_error 5.3 two t1 { + 1 {SQLITE_SCHEMA - table schemas do not match} +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 6c386f42e2..d049f69862 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2229,17 +2229,43 @@ int sqlite3session_diff( if( rc==SQLITE_OK ){ int bHasPk = 0; int bMismatch = 0; - int nCol; /* Columns in zFrom.zTbl */ + int nCol = 0; /* Columns in zFrom.zTbl */ int bRowid = 0; - u8 *abPK; + u8 *abPK = 0; const char **azCol = 0; - rc = sessionTableInfo(0, db, zFrom, zTbl, - &nCol, 0, 0, &azCol, 0, 0, &abPK, - pSession->bImplicitPK ? &bRowid : 0 - ); + char *zDbExists = 0; + + /* Check that database zFrom is attached. */ + zDbExists = sqlite3_mprintf("SELECT * FROM %Q.sqlite_schema", zFrom); + if( zDbExists==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pDbExists = 0; + rc = sqlite3_prepare_v2(db, zDbExists, -1, &pDbExists, 0); + if( rc==SQLITE_ERROR ){ + rc = SQLITE_OK; + nCol = -1; + } + sqlite3_finalize(pDbExists); + sqlite3_free(zDbExists); + } + + if( rc==SQLITE_OK && nCol==0 ){ + rc = sessionTableInfo(0, db, zFrom, zTbl, + &nCol, 0, 0, &azCol, 0, 0, &abPK, + pSession->bImplicitPK ? &bRowid : 0 + ); + } if( rc==SQLITE_OK ){ if( pTo->nCol!=nCol ){ - bMismatch = 1; + if( nCol<=0 ){ + rc = SQLITE_SCHEMA; + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("no such table: %s.%s", zFrom, zTbl); + } + }else{ + bMismatch = 1; + } }else{ int i; for(i=0; i