Skip to content

Conversation

@elprans
Copy link
Member

@elprans elprans commented Mar 30, 2017

PostgreSQL will raise an exception when it detects that the result type of the
query has changed from when the statement was prepared. This may happen, for
example, after an ALTER TABLE or SET search_path.

When this happens, and there is no transaction running, we can simply
re-prepare the statement and try again.

If the transaction is running, this error will put it into an error state,
and we have no choice but to raise an exception. The original error is
somewhat cryptic, so we raise a custom InvalidCachedStatementError with the
original server exception as context.

In either case we clear the statement cache for this connection and all other
connections of the pool this connection belongs to (if any).

See #72 and #76 for discussion.

Fixes: #72.

@elprans elprans requested a review from 1st1 March 30, 2017 17:56
@elprans elprans self-assigned this Mar 30, 2017
if not state.closed:
return state

return await self._prepare_statement(query, timeout, cache)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't split the _get_statement method please.



class InvalidCachedStatementError(AsyncpgError):
"""Cached statement is not longer valid."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: not -> no

@elprans elprans force-pushed the invalidate-cache-on-schema-change branch 2 times, most recently from 181f8a1 to 51a01e9 Compare March 30, 2017 18:02
if e.server_source_function == 'RevalidateCachedQuery':
# Handle query plan rejection due to schema or config changes.
# See comment in Connection._do_execute.
raise exceptions.InvalidCachedStatementError(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this logic to PostgresMessage.new()?


def is_in_transaction(self):
return self.xact_status == PQTRANS_INTRANS
return self.xact_status in (PQTRANS_INTRANS, PQTRANS_INERROR)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment here why PQTRANS_INERROR?

@elprans elprans force-pushed the invalidate-cache-on-schema-change branch from 51a01e9 to 33c592d Compare March 30, 2017 19:04
# connection belongs to (if any).
#
# Note that we specifically do not rely on the error
# message, as it is localizable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outdated comment

if self._protocol.is_in_transaction():
raise
else:
stmt = await self._get_statement(query, timeout)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment explaining that we only do 1 retry.

@elprans elprans force-pushed the invalidate-cache-on-schema-change branch 2 times, most recently from 9d14705 to 47ce1c4 Compare March 30, 2017 19:16
finally:
await self.con.execute('DROP TABLE tab1')
await pool.release(con2)
await pool.release(con1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to release connections if you're closing the pool

PostgreSQL will raise an exception when it detects that the result type of the
query has changed from when the statement was prepared.  This may happen, for
example, after an ALTER TABLE or SET search_path.

When this happens, and there is no transaction running, we can simply
re-prepare the statement and try again.

If the transaction _is_ running, this error will put it into an error state,
and we have no choice but to raise an exception.  The original error is
somewhat cryptic, so we raise a custom InvalidCachedStatementError with the
original server exception as context.

In either case we clear the statement cache for this connection and all other
connections of the pool this connection belongs to (if any).

See #72 and #76 for discussion.

Fixes: #72.
Copy link
Member

@1st1 1st1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can update the docs describing what to do if you see InvalidCachedStatementError exception? (i.e. you can disable the statement cache).

@elprans elprans force-pushed the invalidate-cache-on-schema-change branch from 47ce1c4 to baf5ce7 Compare March 30, 2017 19:36
@elprans elprans merged commit 749d857 into master Mar 30, 2017
@elprans elprans deleted the invalidate-cache-on-schema-change branch March 30, 2017 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants