summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/postgresql/psycopg2.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-01-16 22:44:04 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-01-16 22:44:04 +0000
commitabccc0624228def744b0382e84f01cf95e0d3aed (patch)
treefca7eb29b90211daa699da6d0358f81243c243d9 /lib/sqlalchemy/dialects/postgresql/psycopg2.py
parent00df05061e7a0333022d02705c21270f9de4edab (diff)
downloadsqlalchemy-abccc0624228def744b0382e84f01cf95e0d3aed.tar.gz
- added "statement_options()" to Query, to so options can be
passed to the resulting statement. Currently only Select-statements have these options, and the only option used is "stream_results", and the only dialect which knows "stream_results" is psycopg2. - Query.yield_per() will set the "stream_results" statement option automatically. - Added "statement_options()" to Selects, which set statement specific options. These enable e.g. dialect specific options such as whether to enable using server side cursors, etc. - The psycopg2 now respects the statement option "stream_results". This option overrides the connection setting "server_side_cursors". If true, server side cursors will be used for the statement. If false, they will not be used, even if "server_side_cursors" is true on the connection. [ticket:1619] - added a "frozendict" from http://code.activestate.com/recipes/414283/, adding more default collections as immutable class vars on Query, Insert, Select
Diffstat (limited to 'lib/sqlalchemy/dialects/postgresql/psycopg2.py')
-rw-r--r--lib/sqlalchemy/dialects/postgresql/psycopg2.py40
1 files changed, 28 insertions, 12 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
index a46fdbddb..7733aadcd 100644
--- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py
+++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py
@@ -35,6 +35,15 @@ Transactions
The psycopg2 dialect fully supports SAVEPOINT and two-phase commit operations.
+Statement options
+-----------------
+
+The following statement options are respected:
+
+* *stream_results* - Enable or disable usage of server side cursors for the SELECT-statement.
+ If *None* or not set, the *server_side_cursors* option of the connection is used. If
+ auto-commit is enabled, the option is ignored.
+
"""
import decimal, random, re
@@ -93,8 +102,9 @@ class _PGArray(ARRAY):
if isinstance(self.item_type, sqltypes.String) and \
self.item_type.convert_unicode:
self.item_type.convert_unicode = "force"
-
-# TODO: filter out 'FOR UPDATE' statements
+
+# When we're handed literal SQL, ensure it's a SELECT-query. Since
+# 8.3, combining cursors and "FOR UPDATE" has been fine.
SERVER_SIDE_CURSOR_RE = re.compile(
r'\s*SELECT',
re.I | re.UNICODE)
@@ -102,16 +112,22 @@ SERVER_SIDE_CURSOR_RE = re.compile(
class PostgreSQL_psycopg2ExecutionContext(PGExecutionContext):
def create_cursor(self):
# TODO: coverage for server side cursors + select.for_update()
- is_server_side = \
- self.dialect.server_side_cursors and \
- not self.should_autocommit and \
- ((self.compiled and isinstance(self.compiled.statement, expression.Selectable)
- and not getattr(self.compiled.statement, 'for_update', False)) \
- or \
- (
- (not self.compiled or isinstance(self.compiled.statement, expression._TextClause))
- and self.statement and SERVER_SIDE_CURSOR_RE.match(self.statement))
- )
+ stream_results_option = self.statement_options.get('stream_results')
+ is_server_side = (
+ # Enabled for this statement ...
+ (stream_results_option or
+ # ... or enabled for all statements
+ (self.dialect.server_side_cursors and
+ # ... and not explicitly disabled for this one.
+ (stream_results_option or stream_results_option is None))
+ ) and (
+ # But don't use SS-cursors when autocommit is on ...
+ (not self.should_autocommit and
+ self.compiled and isinstance(self.compiled.statement, expression.Selectable))
+ or (
+ # ... or if it's not even a SELECT.
+ (not self.compiled or isinstance(self.compiled.statement, expression._TextClause))
+ and self.statement and SERVER_SIDE_CURSOR_RE.match(self.statement))))
self.__is_server_side = is_server_side
if is_server_side: