On 07/31/2015 08:34 PM, sqlite-mail wrote: > Hello ! > > I'm using sqlite for a project and with this specific database > https://dev.dadbiz.es/tmp/odoo.db.zip (12MB compressed / 38MB uncompressed) > this is happening: > > -1 Registering an sqlite3_trace function when trying to delete a record just > inserted on the table "res_users" the registered sqlite3_trace function is > called lots of times and sometimes it segfaults (I think stack overflow), I > think it enters in a unintended loop.
If I build the test program below using the command line provided with SQLite 3.8.11.1 and then run it against the oodo.db file from the link above, I get a single line of output: SQL: DELETE FROM res_users WHERE id=7 No errors under valgrind. Is this the expected result? Does it mean bug (1) has been fixed already? Dan. > > -2 If we do a dump "sqlite3 odoo.db .dump > odoo.db.sql" and try to recreate > the database with "sqlite3 new-odoo.db < odoo.db.sql" we get errors for > tables/views declarations out of order (trying to create a view > https://www.endad.eu/tmp/odoo.db.zipthat refer to other views not yet > created). > > Attached there is the simple "C" test file with a shell file to make it with > the flags I use on this project. > > This database uses a lot of foreign keys. > > The trigger on the "res_users" table is very simple: > ----- > BEFORE DELETE ON "res_users" > BEGIN > SELECT RAISE(ABORT, 'Can not remove root/admin user!') > WHERE OLD.id = 1; > END; > ----- > > I've also tested with a fresh sqlite3.c/h from > https://www.sqlite.org/snapshot/sqlite-amalgamation-201507231639.zip. > > When tested with a single table with the above trigger with a fresh database > the test program behaves as expected. > ----- > CREATE TABLE IF NOT EXISTS tbl(id INTEGER PRIMARY KEY, name varchar); > INSERT OR IGNORE INTO tbl(id, name) VALUES > (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'); > CREATE TRIGGER IF NOT EXISTS tbl_delete_trigger BEFORE DELETE ON tbl > BEGIN > SELECT RAISE(ABORT, 'Can not remove root/admin user!') WHERE OLD.id = > 1; > END; > ----- > > > I found a small test that shows how to create a database that after ".dump" > will not properly be restored. > > After writing to you about this bug with sqlite3_trace/trigger I start > thinking what I did with this database (odoo.db) that could possibly make > it's ".dump" not usable to restore and I found the reason. > > On that database I was constantly droping and recreating tables/views with > slight different fields and that seems what makes sqlite3 get lost. > > Example that creates a database not correctly restorable: > -------- > begin; > create table if not exists tbl(id integer primary key, name varchar); > insert or ignore into tbl(id, name) values (1,'a'), (2, 'b'); > create view if not exists tbl_view as select * from tbl; > create view if not exists tbl_view_view as select * from tbl_view; > drop view if exists tbl_view; > create view if not exists tbl_view as select * from tbl; > end; > -------- > > After creating a database with the above sql we get the following from > ".dump": > -------- > PRAGMA foreign_keys=OFF; > BEGIN TRANSACTION; > CREATE TABLE tbl(id integer primary key, name varchar); > INSERT INTO "tbl" VALUES(1,'a'); > INSERT INTO "tbl" VALUES(2,'b'); > CREATE VIEW tbl_view_view as select * from tbl_view; --<<<<<< here we > are trying to create a view on another view not yet created > CREATE VIEW tbl_view as select * from tbl; > COMMIT; > -------- > > On the ".dump"/".restore" problem it seems that sqlite3 shell rely on > sqlite3_master rowid order to perform the ".dump" and when we drop/recreate a > table/view that other tables/views depends sqlite3 do not detect it and > simply add a new entry at the end of sqlite3_master. > > > -------- shell script to make the bug test program > MYINC=$HOME/dev/sqlite3 > #MYINC=. > > gcc \ > -DTHREADSAFE=1 \ > -DSQLITE_DEFAULT_FILE_FORMAT=4 \ > -DSQLITE_DEFAULT_AUTOVACUUM=1 \ > -DSQLITE_DEFAULT_FOREIGN_KEYS= 1 \ > -DSQLITE_ENABLE_COLUMN_METADATA=1 \ > -DSQLITE_ENABLE_FTS4=1 \ > -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 \ > -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 \ > -DSQLITE_ENABLE_RTREE=1 \ > -DSQLITE_ENABLE_STAT4=1 \ > -DSQLITE_OMIT_TCL_VARIABLE=1 \ > -DSQLITE_USE_URI=1 \ > -DSQLITE_SOUNDEX=1\ > -o test-sqlite-bug test-sqlite-bug.c -I $MYINC $MYINC/sqlite3.c > -lpthread -lm -ldl > --------- > --------- test-sqlite-bug.c > #include <stdio.h> > #include "sqlite3.h" > > static const char test_sql[] = > "CREATE TABLE IF NOT EXISTS tbl(id INTEGER PRIMARY KEY, name > varchar);" > "INSERT OR IGNORE INTO tbl(id, name) VALUES " > "(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd');" > "CREATE TRIGGER IF NOT EXISTS tbl_delete_trigger BEFORE DELETE ON tbl > " > "BEGIN" > " SELECT RAISE(ABORT, 'Can not remove root/admin user!') WHERE > OLD.id = 1;" > "END;"; > > static void db_trace_callback(void *user, const char *sql) > { > printf("SQL: %s\n", sql ? sql : "??"); > } > > static void insertRecord(sqlite3 *db) > { > char *errmsg; > const char szSQL[] = "INSERT INTO > \"res_users\"(\"alias_id\",\"company_id\",\"create_uid\",\"login\",\"partner_i > d\") VALUES('10','3',4,'daddad','12')"; > sqlite3_trace(db, db_trace_callback, NULL); > int rc = sqlite3_exec(db, szSQL, NULL, NULL, &errmsg); > } > > int main(int argc, char *argv[]) > { > sqlite3 *db; > int rc = sqlite3_open("../odoo.db", &db); > if(rc == SQLITE_OK) > { > char *errmsg; > const char szSQL[] = "DELETE FROM res_users WHERE id=7"; > sqlite3_trace(db, db_trace_callback, NULL); > insertRecord(db); > //rc = sqlite3_exec(db, test_sql, NULL, NULL, &errmsg); > rc = sqlite3_exec(db, szSQL, NULL, NULL, &errmsg); > sqlite3_close(db); > } > return 0; > } > ------- > ------- output of test-sqlite-bug > SQL: INSERT INTO > "res_users"("alias_id","company_id","create_uid","login","partner_id") > VALUES('10','3',4,'daddad','12') > SQL: DELETE FROM res_users WHERE id=7 > SQL: -- TRIGGER res_users_admin_trigger > SQL: -- TRIGGER > .. <<<<<< the above line repeated 1000 times > ------- > > Thanks in advance for your time, attention and great work ! > Cheers ! > _______________________________________________ > sqlite-users mailing list > sqlite-users at mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users