Hello again ! I forgot also to mention that sqlite do not check for duplicates table constraint declarations see the extended example bellow:
--------- PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE aa(id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE ab(id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE ac(id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE ad(id INTEGER PRIMARY KEY, name TEXT); CREATE TABLE aconstrained( id INTEGER PRIMARY KEY, a_id INTEGER NOT NULL, b_id INTEGER NOT NULL, c_id INTEGER NOT NULL, d_id INTEGER NOT NULL, CONSTRAINT constrained_fkey_aa_id FOREIGN KEY(a_id) REFERENCES aa(id) -- missing comma separator sqlite accept it but postgresql rejects it CONSTRAINT constrained_fkey_ab_id FOREIGN KEY(b_id) REFERENCES? ab(id) -- missing comma separator sqlite accept it but postgresql rejects it CONSTRAINT constrained_fkey_ac_id FOREIGN KEY(c_id) REFERENCES ac(id), -- here we have the comma separating a constraint CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) ); COMMIT; --------- > Wed Aug 05 2015 12:16:09 CEST from "sqlite-mail" ><sqlite-mail at dev.dadbiz.es> Subject: Re: [sqlite] Bug in >sqlite3_trace/trigger/delete > > >>Hello ! >> >> There is also another small bug in sqlite3 parsing of table >> constraints the documentation say that "CREATE TABLE" will accept one >> or more table constraints separated by comma but the parser do not >> catch the absence of a comma, it still seem to works as expected but >> if we try to move the same sql statements to another database like >> postgresql they'll be rejected. See the example bellow. >> >> And on the original issue of sqlite3_trace/trigger/delete I could see >> that the bug of views created out of order on dump/restore was somehow >> solved with this commit >> https://www.sqlite.org/src/info/70b57dafb3216feb but no mention or >> feedback for the problem with recursive loop when deleting a record >> with a trigger for one specific database also provided on the original >> email. Can someone give some feedback on that open issue ? >> >> >> >> > --------- > > >>PRAGMA foreign_keys=OFF; >> >> BEGIN TRANSACTION; >> >> CREATE TABLE aa(id INTEGER PRIMARY KEY, name TEXT); >> CREATE TABLE ab(id INTEGER PRIMARY KEY, name TEXT); >> CREATE TABLE ac(id INTEGER PRIMARY KEY, name TEXT); >> CREATE TABLE ad(id INTEGER PRIMARY KEY, name TEXT); >> >> CREATE TABLE aconstrained( >> id INTEGER PRIMARY KEY, >> a_id INTEGER NOT NULL, >> b_id INTEGER NOT NULL, >> c_id INTEGER NOT NULL, >> d_id INTEGER NOT NULL, >> CONSTRAINT constrained_fkey_aa_id FOREIGN KEY(a_id) REFERENCES >> aa(id) -- missing comma separator sqlite accept it but postgresql >> rejects it >> CONSTRAINT constrained_fkey_ab_id FOREIGN KEY(b_id) REFERENCES >> ab(id) -- missing comma separator sqlite accept it but postgresql >> rejects it >> CONSTRAINT constrained_fkey_ac_id FOREIGN KEY(c_id) REFERENCES >> ac(id), -- here we have the comma separating a constraint >> CONSTRAINT constrained_fkey_ad_id FOREIGN KEY(d_id) REFERENCES ad(id) >> ); >> >> COMMIT; >> >> --------- >> >> Thanks in advance for your time and attention ! >> >> Mon Aug 03 2015 13:08:08 CEST from "Dan Kennedy" >> <danielk1977 at gmail.com> Subject: Re: [sqlite] Bug in >> sqlite3_trace/trigger/delete >> 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. >> >> -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 >> >> _______________________________________________ >> sqlite-users mailing list >> sqlite-users at mailinglists.sqlite.org >> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > _______________________________________________ > sqlite-users mailing list > sqlite-users at mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > > > ?