|
| 1 | +py-postgresql gotchas |
| 2 | +===================== |
| 3 | + |
| 4 | +It is recognized that decisions were made that may not always be ideal for a |
| 5 | +given user. In order to highlight those potential issues and hopefully bring |
| 6 | +some sense into a confusing situation, this document was drawn. |
| 7 | + |
| 8 | +Cursors are not usable after transaction commits or aborts |
| 9 | +---------------------------------------------------------- |
| 10 | + |
| 11 | +`postgresql.driver` uses protocol level cursors. When a cursor is bound, there |
| 12 | +is no way for the driver to state that the cursor should be held via the |
| 13 | +protocol. This causes two potentially unfortunate things: |
| 14 | + |
| 15 | + - In auto-commit mode, the entire cursor is read. |
| 16 | + - When a transaction closes, all cursors created become unusable. |
| 17 | + |
| 18 | +Prepared statements, in contrast, are not automatically closed. |
| 19 | + |
| 20 | + |
| 21 | +client_encoding and TimeZone GUCs should not be altered |
| 22 | +------------------------------------------------------- |
| 23 | + |
| 24 | +`postgresql.driver`'s cursor implementation reads a fixed set of rows when it |
| 25 | +queries the server for more. In order to optimized some situations, the driver |
| 26 | +will send a request for more data, but makes no attempt to wait and process the |
| 27 | +data as it is not yet needed. When the user comes back to read more data from |
| 28 | +the cursor, it will then look at this new data. The problem being, if the |
| 29 | +`client_encoding` or the `TimeZone` was switched, it may use the wrong codec and |
| 30 | +tzinfo to transform the wire data into higher level Python objects. |
| 31 | + |
| 32 | +To avoid this problem from ever happening, set the `TimeZone` or |
| 33 | +`client_encoding` early. Furthermore, it is probably best to never change the |
| 34 | +`client_encoding` as the driver automatically makes the necessary tranformation |
| 35 | +to Python strings. |
| 36 | + |
| 37 | + |
| 38 | +The user and password is correct, but does it not work when using `postgresql.driver` |
| 39 | +------------------------------------------------------------------------------------- |
| 40 | + |
| 41 | +This issue likely comes from the possibility that the information sent to the |
| 42 | +server early in the negotiation phase may not be in an encoding that is |
| 43 | +consistent with the server's encoding. |
| 44 | + |
| 45 | +One problem is that PostgreSQL does not provide the client with the server |
| 46 | +encoding early enough in the negotiation phase, and, therefore, is unable to |
| 47 | +process the password data in a way that is consistent with the server's |
| 48 | +expectations. |
| 49 | + |
| 50 | +Another problem is that PostgreSQL takes much of the data in the startup message |
| 51 | +as-is, so a decision about the best way to encode parameters is difficult. |
| 52 | + |
| 53 | +The easy way to avoid *most* issues with this problem is to initialize the |
| 54 | +database in the `utf-8` encoding. The driver defaults the expected server |
| 55 | +encoding to `utf-8`. However, this can be overridden by creating the `Connector` |
| 56 | +with a `server_encoding` parameter. Setting `server_encoding` to the proper |
| 57 | +value of the target server will allow the driver to properly encode *some* of |
| 58 | +the parameters. Also, any GUC parameters passed via the `settings` parameter |
| 59 | +should use typed objects when possible to hint that the server encoding should |
| 60 | +not be used on that parameter. |
0 commit comments