canonical / sqlair

Friendly type mapping for SQL databases
Apache License 2.0
17 stars 8 forks source link

Prepare statements on DB when Query created #81

Closed Aflynn50 closed 11 months ago

Aflynn50 commented 1 year ago

Prepare SQLair statements on the database when a new Query is created with DB.Query or TX.Query. DB prepared statements are cached for reuse.

Each statement is assigned a unique ID which is used as the key to the cache of *sql.Stmts. When the statement is added to the cache a finalizer is set on the sqlair.Statement object which will remove it from the cache and and close the prepared statement when it is garbage collected. This does mean that any errors thrown when the prepared statement is closed are ignored.

A single sqlair.Statement can be prepared on multiple databases. So the cache is double indexed, first by the statement ID, then by the database ID (it is of type map[stmtID]map[dbID]*sql.Stmt). There is also a separate store indexed first by the database ID and then by the statement ID (map[dbID]map[stmtID]bool) that is used to record which statements are prepared on which DB so that they can be efficiently removed from the cache when the finalizer on the database is triggered.

Whilst testing for this PR a bug was discovered with the setup of the database test suite. The sqlite database was opened with sql.Open("sqlite3", ":memory:"), this in fact means that every new connection to the database creates a new, empty, DB. And since the Go database driver handles connections behind the scenes this lead to some unexpected bugs.

To fix this problem is now fixed but it turned out that the DROP TABLE statements had never been working as intended (this went unnoticed as a new connection/DB was created for each test before).