I literally have no time to work on this, but I'm fairly certain that yes it is. IIRC, there's a few pragmas that are run in the cache.py file, and turning on foreign keys is one of them.
Now I've looked at it, it's right there in the top of the database schema TradeDangerous.sql at line 27, just after Oliver's comments - PRAGMA foreign_keys=ON;
But you never start the transaction yourself. What if the internal transaction-algorythums of the sqlite3 module does an rollback if an IntegrityError is raised?
Yes we do - or rather pysqlite does it for us.
"pysqlite is notorious for implementing weird transactional semantics. By default, pysqlite will open a transaction when you issue your first write query (it does this by examining every query you execute). The transaction will be automatically committed when you either call Connection.commit() or execute any other query that is not a SELECT, INSERT, UPDATE, or DELETE (for example CREATE TABLE or PRAGMA)." [1]
Now it may be that we would be better off managing the transactions ourselves. But I've put a lot of thought into this, so riddle me this:
If there is a problem with transactions, or a funky write-lock, or any other SQLite error you want to come up with - why then is it not random. It picks on stations - KUKI AN/BOKEILI HUB (station_id '43119') is my test case. Almost invariably (emphasis on almost) it will not update when I send a schema (with EDMC or EDDiscovery) , at least on server side, normally that station updates fine via listener on my local PC, but then it seems that other people have their own particular test cases - maybe if I looked hard enough, I could find one my PC hates on. I should probably also test the PC in server mode.
UPDATE: I did test the PC in server mode. It still didn't hate on station 43119, but I did find other interesting results, as below.
Nevertheless, you got me to thinking about transactions and such, so I put the database into auto-commit mode, changing the connection in tradedb.py to read.
conn = sqlite3.connect(self.dbFilename, isolation_level=None)
And stopping the (now unecessary) db.commits in the listener by altering lines 551 & 687 to read
success = True
This had three effects.
1: Completely expected slowing down of the database. Particularly when running in server mode.
2: Trying to read the database, I would frequently get locking problems.
Code:
sqlite> SELECT * FROM StationItem WHERE station_id == 43119;
Error: database is locked
3: The problem went away, my bugbear station updated as it should, over and over again.
As another issue - getting back to server mode, something happens speedwise when running in this way. Compare
Code:
Server running updates
Market update for NINHURSAG/DANNY B MATTISSEN finished in 3.186 seconds.
Market update for PROCYON/DAVY DOCK finished in 2.219 seconds.
Market update for ROBIGO/HAUSER'S REACH finished in 2.98 seconds.
Market update for CORNENGU/MARGULIES DOCK finished in 0.719 seconds.
Market update for NLTT 53690/THAGARD TERMINAL finished in 1.45 seconds.
Local PC running updates in client mode
Market update for ZHANG FEI/SEREBROV HORIZONS finished in 0.009 seconds.
Market update for HIP 85360/MACAN PLATFORM finished in 0.62 seconds.
Market update for HIP 53688/WHITE GATEWAY finished in 0.599 seconds.
Market update for XINCA/FINCH MARKET finished in 0.341 seconds.
Local PC running updates in server mode
Market update for G 139-3/O'CONNOR DOCK finished in 3.561 seconds.
Market update for GATEWAY/WICCA TOWN finished in 2.494 seconds.
Market update for HR 1183/ARC'S FAITH finished in 3.219 seconds.
Market update for SHINRARTA DEZHRA/JAMESON MEMORIAL finished in 3.439 seconds.
Market update for ALIOTH/GOTHAM PARK finished in 2.051 seconds.
Market update for SHINRARTA DEZHRA/JAMESON MEMORIAL finished in 3.087 seconds.
For completeness I also ran the "server" in "client" mode. That ran faster than my PC and used about 25% of the CPU time it eats in server mode. Sadly the speed increase did not fix the problem in the same way that running autocommit had done.
So - a lot to think about, but I think that might be a bit of forward progress.
We can cure the problem by using autocommit.
In server mode the listener runs dog slow (it actually falls way behind in processing, so it can end up being minutes from a schema submission, to it finally getting processed). This slowness is further exacerbated by using autocommit.
Therefore there are two issues that need looking at -
1: Pysqlite and it's funky transactional methods which my testing suggests is the root of missing stations.
2: The listener running horribly horribly horribly in server mode, for which I can see no good reason.
[1]
http://charlesleifer.com/blog/going-fast-with-sqlite-and-python