summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-04-06 23:46:02 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-04-06 23:46:02 +0000
commit2a171e818c2e7cfadcd286399a3740147ff0df45 (patch)
treec91044514931106b35272c56213ea55274a7f7f4 /lib/sqlalchemy/sql.py
parent5bda70e770489a09a848d5ac3bfbee0aabd805ab (diff)
downloadsqlalchemy-2a171e818c2e7cfadcd286399a3740147ff0df45.tar.gz
split up Session into Session/LegacySession, added some new constructor args
created AbstractEngine class which provides base for SQLEngine and will also provide base for ConnectionProxy, so SQL binding can be to an engine or specific connection resource ClauseElements get using() method which can take AbstractEngines for execution made more separation between SchemaItems and bound engine
Diffstat (limited to 'lib/sqlalchemy/sql.py')
-rw-r--r--lib/sqlalchemy/sql.py66
1 files changed, 38 insertions, 28 deletions
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py
index f6e2d03c9..2bc025e9f 100644
--- a/lib/sqlalchemy/sql.py
+++ b/lib/sqlalchemy/sql.py
@@ -246,6 +246,12 @@ def _is_literal(element):
def is_column(col):
return isinstance(col, ColumnElement)
+class AbstractEngine(object):
+ def execute_compiled(self, compiled, parameters, echo=None, **kwargs):
+ raise NotImplementedError()
+ def compiler(self, statement, parameters, **kwargs):
+ raise NotImplementedError()
+
class ClauseParameters(util.OrderedDict):
"""represents a dictionary/iterator of bind parameter key names/values. Includes parameters compiled with a Compiled object as well as additional arguments passed to the Compiled object's get_params() method. Parameter values will be converted as per the TypeEngine objects present in the bind parameter objects. The non-converted value can be retrieved via the get_original method. For Compiled objects that compile positional parameters, the values() iteration of the object will return the parameter values in the correct order."""
def __init__(self, engine=None):
@@ -340,8 +346,11 @@ class Compiled(ClauseVisitor):
"""executes this compiled object using the underlying SQLEngine"""
if len(multiparams):
params = multiparams
-
- return self.engine.execute_compiled(self, params)
+
+ e = self.engine
+ if e is None:
+ raise InvalidRequestError("This Compiled object is not bound to any engine.")
+ return e.execute_compiled(self, params)
def scalar(self, *multiparams, **params):
"""executes this compiled object via the execute() method, then
@@ -356,7 +365,26 @@ class Compiled(ClauseVisitor):
return row[0]
else:
return None
-
+
+class Executor(object):
+ """handles the compilation/execution of a ClauseElement within the context of a particular AbtractEngine. This
+ AbstractEngine will usually be a SQLEngine or ConnectionProxy."""
+ def __init__(self, clauseelement, abstractengine=None):
+ self.engine=abstractengine
+ self.clauseelement = clauseelement
+ def execute(self, *multiparams, **params):
+ return self.compile(*multiparams, **params).execute(*multiparams, **params)
+ def scalar(self, *multiparams, **params):
+ return self.compile(*multiparams, **params).scalar(*multiparams, **params)
+ def compile(self, *multiparams, **params):
+ if len(multiparams):
+ bindparams = multiparams[0]
+ else:
+ bindparams = params
+ compiler = self.engine.compiler(self.clauseelement, bindparams)
+ compiler.compile()
+ return compiler
+
class ClauseElement(object):
"""base class for elements of a programmatically constructed SQL expression."""
def _get_from_objects(self):
@@ -415,10 +443,12 @@ class ClauseElement(object):
engine = property(lambda s: s._find_engine(), doc="attempts to locate a SQLEngine within this ClauseElement structure, or returns None if none found.")
-
+ def using(self, abstractengine):
+ return Executor(self, abstractengine)
+
def compile(self, engine = None, parameters = None, typemap=None, compiler=None):
"""compiles this SQL expression using its underlying SQLEngine to produce
- a Compiled object. If no engine can be found, an ansisql engine is used.
+ a Compiled object. If no engine can be found, an ANSICompiler is used with no engine.
bindparams is a dictionary representing the default bind parameters to be used with
the statement. """
@@ -430,7 +460,7 @@ class ClauseElement(object):
if compiler is None:
import sqlalchemy.ansisql as ansisql
- compiler = ansisql.ANSICompiler(self, parameters=parameters, typemap=typemap)
+ compiler = ansisql.ANSICompiler(self, parameters=parameters)
compiler.compile()
return compiler
@@ -438,30 +468,10 @@ class ClauseElement(object):
return str(self.compile())
def execute(self, *multiparams, **params):
- """compiles and executes this SQL expression using its underlying SQLEngine. the
- given **params are used as bind parameters when compiling and executing the
- expression. the DBAPI cursor object is returned."""
- e = self.engine
- if len(multiparams):
- bindparams = multiparams[0]
- else:
- bindparams = params
- c = self.compile(e, parameters=bindparams)
- return c.execute(*multiparams, **params)
+ return self.using(self.engine).execute(*multiparams, **params)
def scalar(self, *multiparams, **params):
- """executes this SQL expression via the execute() method, then
- returns the first column of the first row. Useful for executing functions,
- sequences, rowcounts, etc."""
- # we are still going off the assumption that fetching only the first row
- # in a result set is not performance-wise any different than specifying limit=1
- # else we'd have to construct a copy of the select() object with the limit
- # installed (else if we change the existing select, not threadsafe)
- row = self.execute(*multiparams, **params).fetchone()
- if row is not None:
- return row[0]
- else:
- return None
+ return self.using(self.engine).scalar(*multiparams, **params)
def __and__(self, other):
return and_(self, other)