Details
-
Suggestion
-
Resolution: Out of scope
-
P3: Somewhat important
-
4.4.0
-
None
Description
By default we use the natively prepared queries for PostgreSQL version 8.2 or above. Using server-side prepared statements bring disadvantages like:
1. In case of applications that usually execute queries one time this feature makes the query slower, adds server-side overhead and increases the network /process round trip time of the query.
2. It makes database query logs much less useful.
3. It leads to the statement not being re-planned. When a table is being populated, for example, the initial plan of the statement will be based on the statistics of an empty table, leading to sequential scans rather than index scans.
If you then insert a million rows in the table the plan will no longer be appropriate and the performance will degrade to the point of being broken.
4. If QSqlQuery::exec() causes an error, aborting the transaction, and any QSqlQuery goes out of scope before QSqlDatabase::rollback(), QSqlQuery will fail to deallocate the prepared statement and throw "Warning: Unable to free statement: ERROR: current transaction is aborted, commands ignored until end of transaction block" to stderr. This will happen on every failed SQL query if you're using exceptions to handle errors and doing the rollback in the catch block, for example.
Considering all the above it would be better to let the user decide if he wants to use the prepared statement feature. At the moment there is no way to turn it off, as it's hard- coded in QPSQLDriver::hasFeature() based on server version.
Also to get much value from server-side prepares QSqlQuery should not destroy the prepared statement at deallocation,
rather it should keep a map of statement strings to prepared statement identifiers and reuse an existing prepared statement if possible.
For postgresql it should really use the PQprepare() and PQexecPrepared() interface, rather than using SQL "PREPARE" and "EXECUTE".