[horde] horde 3.0.5, postgresql session handler fails
Chris Stromsoe
cbs+horde at cts.ucla.edu
Sat Oct 8 14:13:02 PDT 2005
I can't get session handling working with the postgresql session handler with
horde 3.0.5. After authenticating, I'm returned to the login page. If I use
the default "none" / php files-based handler, sessions seem to work fine.
Looking at the query logs and comparing against the SQL for mysql, it looks
like read()/write() are broken for the postgres handler.
On the initial page load -- before authenticating -- read() gets called with a
session id, starts a transaction, then selects on the session id FOR UPDATE to
lock the row. If the query doesn't return any information, it does an INSERT,
then re-selects the row. It then calls write() with the same session id, which
does an UPDATE on the session id and commits the transaction.
After passing in authentication credentials, read() gets called with a session
id as above, starts a transaction, and selects on the sesion id FOR UPDATE to
lock it. In login.php on line 71 Horde::getCleanSession() is called,
generating a new session id. write() gets called with the new session id,
which does an UPDATE which fails because there is no row in the table with the
new session id.
Compounding the problem, the failure is not detected. From
lib/Horde/SessionHanderl/pgsql.php:
/* Build the SQL query. */
$query = sprintf('UPDATE %s SET session_lastmodified = %s,
session_data= %s WHERE session_id = %s; COMMIT;',
$this->_params['table'],
time(),
$this->quote($session_data),
$this->quote($id));
/* Log the query at a DEBUG log level. */
Horde::logMessage(sprintf('SQL Query by SessionHandler_pgsql::write():
query = "%s"', $query),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$result = @pg_query($this->_db, $query);
$success = (pg_affected_rows($result) == 0);
pg_free_result($result);
Because the update query includes the COMMIT, I'm pretty sure that
pg_affected_rows() will return the result of the COMMIT not the result of the
UPDATE, which means that the test for pg_affected_rows() == 0 will always be
true. Testing to see if the UPDATE was succesful should probably be testing
for pg_affected_rows() == 1.
-Chris
More information about the horde
mailing list