summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/engine
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-10-15 16:09:59 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-10-15 16:09:59 +0000
commitbc351a2dc423987f05f4bf88db4987be507ee0a1 (patch)
tree9f6f8c8ab74abfa8d2d03690178693d0412ca462 /lib/sqlalchemy/engine
parentad89932715193275d37b5e22b830f092e350b1fe (diff)
downloadsqlalchemy-bc351a2dc423987f05f4bf88db4987be507ee0a1.tar.gz
- DefaultRunner and subclasses have been removed. The job
of this object has been simplified and moved into ExecutionContext. Dialects which support sequences should add a `fire_sequence()` method to their execution context implementation. [ticket:1566]
Diffstat (limited to 'lib/sqlalchemy/engine')
-rw-r--r--lib/sqlalchemy/engine/__init__.py2
-rw-r--r--lib/sqlalchemy/engine/base.py73
-rw-r--r--lib/sqlalchemy/engine/default.py67
3 files changed, 56 insertions, 86 deletions
diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py
index 694a2f71f..fed28c094 100644
--- a/lib/sqlalchemy/engine/__init__.py
+++ b/lib/sqlalchemy/engine/__init__.py
@@ -60,7 +60,6 @@ from sqlalchemy.engine.base import (
Compiled,
Connectable,
Connection,
- DefaultRunner,
Dialect,
Engine,
ExecutionContext,
@@ -83,7 +82,6 @@ __all__ = (
'Compiled',
'Connectable',
'Connection',
- 'DefaultRunner',
'Dialect',
'Engine',
'ExecutionContext',
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 26e44dd6b..829f97558 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -14,7 +14,7 @@ and result contexts.
__all__ = [
'BufferedColumnResultProxy', 'BufferedColumnRow', 'BufferedRowResultProxy',
- 'Compiled', 'Connectable', 'Connection', 'DefaultRunner', 'Dialect', 'Engine',
+ 'Compiled', 'Connectable', 'Connection', 'Dialect', 'Engine',
'ExecutionContext', 'NestedTransaction', 'ResultProxy', 'RootTransaction',
'RowProxy', 'SchemaIterator', 'StringIO', 'Transaction', 'TwoPhaseTransaction',
'connection_memoize']
@@ -57,10 +57,6 @@ class Dialect(object):
type of encoding to use for unicode, usually defaults to
'utf-8'.
- defaultrunner
- a :class:`~sqlalchemy.schema.SchemaVisitor` class which executes
- defaults.
-
statement_compiler
a :class:`~Compiled` class used to compile SQL statements
@@ -1012,9 +1008,8 @@ class Connection(Connectable):
return self._execute_clauseelement(func.select(), multiparams, params)
def _execute_default(self, default, multiparams, params):
- ret = self.engine.dialect.\
- defaultrunner(self.__create_execution_context()).\
- traverse_single(default)
+ ctx = self.__create_execution_context()
+ ret = ctx._exec_default(default)
if self.__close_with_result:
self.close()
return ret
@@ -2154,68 +2149,6 @@ class BufferedColumnResultProxy(ResultProxy):
return l
-class DefaultRunner(schema.SchemaVisitor):
- """A visitor which accepts ColumnDefault objects, produces the
- dialect-specific SQL corresponding to their execution, and
- executes the SQL, returning the result value.
-
- DefaultRunners are used internally by Engines and Dialects.
- Specific database modules should provide their own subclasses of
- DefaultRunner to allow database-specific behavior.
- """
-
- def __init__(self, context):
- self.context = context
- self.dialect = context.dialect
- self.cursor = context.cursor
-
- def get_column_default(self, column):
- if column.default is not None:
- return self.traverse_single(column.default)
- else:
- return None
-
- def get_column_onupdate(self, column):
- if column.onupdate is not None:
- return self.traverse_single(column.onupdate)
- else:
- return None
-
- def visit_passive_default(self, default):
- return None
-
- def visit_sequence(self, seq):
- return None
-
- def exec_default_sql(self, default):
- conn = self.context.connection
- c = expression.select([default.arg]).compile(bind=conn)
- return conn._execute_compiled(c, (), {}).scalar()
-
- def execute_string(self, stmt, params=None):
- """execute a string statement, using the raw cursor, and return a scalar result."""
-
- conn = self.context._connection
- if isinstance(stmt, unicode) and not self.dialect.supports_unicode_statements:
- stmt = stmt.encode(self.dialect.encoding)
- conn._cursor_execute(self.cursor, stmt, params)
- return self.cursor.fetchone()[0]
-
- def visit_column_onupdate(self, onupdate):
- if isinstance(onupdate.arg, expression.ClauseElement):
- return self.exec_default_sql(onupdate)
- elif util.callable(onupdate.arg):
- return onupdate.arg(self.context)
- else:
- return onupdate.arg
-
- def visit_column_default(self, default):
- if isinstance(default.arg, expression.ClauseElement):
- return self.exec_default_sql(default)
- elif util.callable(default.arg):
- return default.arg(self.context)
- else:
- return default.arg
def connection_memoize(key):
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index e062abce6..12ab605e4 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -28,7 +28,6 @@ class DefaultDialect(base.Dialect):
ddl_compiler = compiler.DDLCompiler
type_compiler = compiler.GenericTypeCompiler
preparer = compiler.IdentifierPreparer
- defaultrunner = base.DefaultRunner
supports_alter = True
supports_sequences = False
@@ -198,10 +197,7 @@ class DefaultExecutionContext(base.ExecutionContext):
self.result_map = None
self.cursor = self.create_cursor()
self.compiled_parameters = []
- if self.dialect.positional:
- self.parameters = [()]
- else:
- self.parameters = [{}]
+ self.parameters = [self._default_params]
elif compiled_sql is not None:
self.compiled = compiled = compiled_sql
@@ -273,6 +269,27 @@ class DefaultExecutionContext(base.ExecutionContext):
bool(self.compiled.returning) and \
not self.compiled.statement._returning
+ @util.memoized_property
+ def _default_params(self):
+ if self.dialect.positional:
+ return ()
+ else:
+ return {}
+
+ def _execute_scalar(self, stmt):
+ """Execute a string statement on the current cursor, returning a scalar result.
+
+ Used to fire off sequences, default phrases, and "select lastrowid" types of statements individually
+ or in the context of a parent INSERT or UPDATE statement.
+
+ """
+
+ conn = self._connection
+ if isinstance(stmt, unicode) and not self.dialect.supports_unicode_statements:
+ stmt = stmt.encode(self.dialect.encoding)
+ conn._cursor_execute(self.cursor, stmt, self._default_params)
+ return self.cursor.fetchone()[0]
+
@property
def connection(self):
return self._connection._branch()
@@ -286,10 +303,8 @@ class DefaultExecutionContext(base.ExecutionContext):
if self.dialect.positional or self.dialect.supports_unicode_statements:
if params:
return params
- elif self.dialect.positional:
- return [()]
else:
- return [{}]
+ return [self._default_params]
else:
def proc(d):
# sigh, sometimes we get positional arguments with a dialect
@@ -460,6 +475,32 @@ class DefaultExecutionContext(base.ExecutionContext):
self._connection._handle_dbapi_exception(e, None, None, None, self)
raise
+ def _exec_default(self, default):
+ if default.is_sequence:
+ return self.fire_sequence(default)
+ elif default.is_callable:
+ return default.arg(self)
+ elif default.is_clause_element:
+ # TODO: expensive branching here should be
+ # pulled into _exec_scalar()
+ conn = self.connection
+ c = expression.select([default.arg]).compile(bind=conn)
+ return conn._execute_compiled(c, (), {}).scalar()
+ else:
+ return default.arg
+
+ def get_insert_default(self, column):
+ if column.default is None:
+ return None
+ else:
+ return self._exec_default(column.default)
+
+ def get_update_default(self, column):
+ if column.onupdate is None:
+ return None
+ else:
+ return self._exec_default(column.onupdate)
+
def __process_defaults(self):
"""Generate default values for compiled insert/update statements,
and generate inserted_primary_key collection.
@@ -467,28 +508,26 @@ class DefaultExecutionContext(base.ExecutionContext):
if self.executemany:
if len(self.compiled.prefetch):
- drunner = self.dialect.defaultrunner(self)
params = self.compiled_parameters
for param in params:
self.current_parameters = param
for c in self.compiled.prefetch:
if self.isinsert:
- val = drunner.get_column_default(c)
+ val = self.get_insert_default(c)
else:
- val = drunner.get_column_onupdate(c)
+ val = self.get_update_default(c)
if val is not None:
param[c.key] = val
del self.current_parameters
else:
self.current_parameters = compiled_parameters = self.compiled_parameters[0]
- drunner = self.dialect.defaultrunner(self)
for c in self.compiled.prefetch:
if self.isinsert:
- val = drunner.get_column_default(c)
+ val = self.get_insert_default(c)
else:
- val = drunner.get_column_onupdate(c)
+ val = self.get_update_default(c)
if val is not None:
compiled_parameters[c.key] = val