summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-12-13 00:15:32 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2010-12-13 00:15:32 -0500
commit86e8e7c558b296018613ed979012b2aca493ffbb (patch)
tree62340b7d477c59d9ba7c2c2cad488652176188d8 /lib/sqlalchemy
parent1125a4b8b1a7b41111396b5b58887047a847b59e (diff)
downloadsqlalchemy-86e8e7c558b296018613ed979012b2aca493ffbb.tar.gz
- why type.dialect_impl(dialect).bind_processor(dialect), caching just the impl?
just call type._cached_bind_processor(dialect), cache the impl *and* the processor function. same for result sets. - use plain dict + update for defaultexecutioncontext.execution_options
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/engine/base.py5
-rw-r--r--lib/sqlalchemy/engine/default.py25
-rw-r--r--lib/sqlalchemy/schema.py6
-rw-r--r--lib/sqlalchemy/sql/compiler.py4
-rw-r--r--lib/sqlalchemy/sql/expression.py3
-rw-r--r--lib/sqlalchemy/types.py131
-rw-r--r--lib/sqlalchemy/util/_collections.py2
7 files changed, 85 insertions, 91 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 00aaca01e..f3f32f833 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -701,7 +701,7 @@ class Compiled(object):
"""Return the string text of the generated SQL or DDL."""
return self.string or ''
-
+
def construct_params(self, params=None):
"""Return the bind params for this compiled object.
@@ -2221,8 +2221,7 @@ class ResultMetaData(object):
name, obj, type_ = \
colname, None, typemap.get(coltype, types.NULLTYPE)
- processor = type_.dialect_impl(dialect).\
- result_processor(dialect, coltype)
+ processor = type_._cached_result_processor(dialect, coltype)
processors.append(processor)
rec = (processor, i)
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 22fff3312..8647ba385 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -307,7 +307,6 @@ class DefaultDialect(base.Dialect):
class DefaultExecutionContext(base.ExecutionContext):
- execution_options = util.frozendict()
isinsert = False
isupdate = False
isdelete = False
@@ -329,12 +328,10 @@ class DefaultExecutionContext(base.ExecutionContext):
self.compiled = compiled = compiled_ddl
self.isddl = True
- if compiled.statement._execution_options:
- self.execution_options = compiled.statement._execution_options
+ self.execution_options = compiled.statement._execution_options
if connection._execution_options:
- self.execution_options = self.execution_options.union(
- connection._execution_options
- )
+ self.execution_options = dict(self.execution_options)
+ self.execution_options.update(connection._execution_options)
if not dialect.supports_unicode_statements:
self.unicode_statement = unicode(compiled)
@@ -366,12 +363,10 @@ class DefaultExecutionContext(base.ExecutionContext):
if not compiled.can_execute:
raise exc.ArgumentError("Not an executable clause: %s" % compiled)
- if compiled.statement._execution_options:
- self.execution_options = compiled.statement._execution_options
+ self.execution_options = compiled.statement._execution_options
if connection._execution_options:
- self.execution_options = self.execution_options.union(
- connection._execution_options
- )
+ self.execution_options = dict(self.execution_options)
+ self.execution_options.update(connection._execution_options)
# compiled clauseelement. process bind params, process table defaults,
# track collections used by ResultProxy to target and process results
@@ -451,9 +446,7 @@ class DefaultExecutionContext(base.ExecutionContext):
self.engine = connection.engine
# plain text statement
- if connection._execution_options:
- self.execution_options = self.execution_options.\
- union(connection._execution_options)
+ self.execution_options = connection._execution_options
if not parameters:
if self.dialect.positional:
@@ -493,9 +486,7 @@ class DefaultExecutionContext(base.ExecutionContext):
self.dialect = dialect
self._connection = self.root_connection = connection
self.engine = connection.engine
- if connection._execution_options:
- self.execution_options = self.execution_options.\
- union(connection._execution_options)
+ self.execution_options = connection._execution_options
self.cursor = self.create_cursor()
return self
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 6d6a4485d..cb6b27e36 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -504,7 +504,7 @@ class Column(SchemaItem, expression.ColumnClause):
usage within the :mod:`~sqlalchemy.ext.declarative` extension.
:param type\_: The column's type, indicated using an instance which
- subclasses :class:`~sqlalchemy.types.AbstractType`. If no arguments
+ subclasses :class:`~sqlalchemy.types.TypeEngine`. If no arguments
are required for the type, the class of the type can be sent
as well, e.g.::
@@ -684,9 +684,9 @@ class Column(SchemaItem, expression.ColumnClause):
if args:
coltype = args[0]
- if (isinstance(coltype, types.AbstractType) or
+ if (isinstance(coltype, types.TypeEngine) or
(isinstance(coltype, type) and
- issubclass(coltype, types.AbstractType))):
+ issubclass(coltype, types.TypeEngine))):
if type_ is not None:
raise exc.ArgumentError(
"May not pass type_ positionally and as a keyword.")
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index d5b877a35..0c76f3e74 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -262,7 +262,7 @@ class SQLCompiler(engine.Compiled):
self._memos[key] = processors = dict(
(key, value) for key, value in
( (self.bind_names[bindparam],
- bindparam.bind_processor(dialect))
+ bindparam.type._cached_bind_processor(dialect))
for bindparam in self.bind_names )
if value is not None
)
@@ -596,7 +596,7 @@ class SQLCompiler(engine.Compiled):
def render_literal_bindparam(self, bindparam, **kw):
value = bindparam.value
- processor = bindparam.bind_processor(self.dialect)
+ processor = bindparam.type._cached_bind_processor(self.dialect)
if processor:
value = processor(value)
return self.render_literal_value(value, bindparam.type)
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index bf055f0b2..f090d14d6 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -2470,9 +2470,6 @@ class _BindParamClause(ColumnElement):
self.key = _generated_label('%%(%d %s)s' % (id(self),
self._orig_key or 'param'))
- def bind_processor(self, dialect):
- return self.type.dialect_impl(dialect).bind_processor(dialect)
-
def compare(self, other, **kw):
"""Compare this :class:`_BindParamClause` to the given
clause."""
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index 434fb07c3..480d9f883 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -41,28 +41,43 @@ if util.jython:
import array
class AbstractType(Visitable):
+ """Base for all types - not needed except for backwards
+ compatibility."""
+
+class TypeEngine(AbstractType):
+ """Base for built-in types."""
def copy_value(self, value):
return value
def bind_processor(self, dialect):
- """Defines a bind parameter processing function.
-
+ """Return a conversion function for processing bind values.
+
+ Returns a callable which will receive a bind parameter value
+ as the sole positional argument and will return a value to
+ send to the DB-API.
+
+ If processing is not necessary, the method should return ``None``.
+
:param dialect: Dialect instance in use.
"""
-
return None
def result_processor(self, dialect, coltype):
- """Defines a result-column processing function.
-
+ """Return a conversion function for processing result row values.
+
+ Returns a callable which will receive a result row column
+ value as the sole positional argument and will return a value
+ to return to the user.
+
+ If processing is not necessary, the method should return ``None``.
+
:param dialect: Dialect instance in use.
:param coltype: DBAPI coltype argument received in cursor.description.
-
- """
+ """
return None
def compare_values(self, x, y):
@@ -115,6 +130,44 @@ class AbstractType(Visitable):
typ = t
else:
return self.__class__
+
+ @util.memoized_property
+ def _impl_dict(self):
+ return {}
+
+ def __getstate__(self):
+ d = self.__dict__.copy()
+ d.pop('_impl_dict', None)
+ return d
+
+ def dialect_impl(self, dialect, **kwargs):
+ key = dialect.__class__, dialect.server_version_info
+ try:
+ return self._impl_dict[key]
+ except KeyError:
+ return self._impl_dict.setdefault(key,
+ dialect.type_descriptor(self))
+
+ def _cached_bind_processor(self, dialect):
+ key = "bind", dialect.__class__, dialect.server_version_info
+ try:
+ return self._impl_dict[key]
+ except KeyError:
+ self._impl_dict[key] = bp = \
+ self.dialect_impl(dialect).bind_processor(dialect)
+ return bp
+
+ def _cached_result_processor(self, dialect, coltype):
+ key = "result", dialect.__class__, dialect.server_version_info, coltype
+ try:
+ return self._impl_dict[key]
+ except KeyError:
+ self._impl_dict[key] = rp = self.dialect_impl(dialect).\
+ result_processor(dialect, coltype)
+ return rp
+
+ def adapt(self, cls):
+ return cls()
def _coerce_compared_value(self, op, value):
_coerced_type = _type_map.get(type(value), NULLTYPE)
@@ -164,52 +217,6 @@ class AbstractType(Visitable):
", ".join("%s=%r" % (k, getattr(self, k, None))
for k in inspect.getargspec(self.__init__)[0][1:]))
-class TypeEngine(AbstractType):
- """Base for built-in types."""
-
- @util.memoized_property
- def _impl_dict(self):
- return {}
-
- def dialect_impl(self, dialect, **kwargs):
- key = dialect.__class__, dialect.server_version_info
- try:
- return self._impl_dict[key]
- except KeyError:
- return self._impl_dict.setdefault(key,
- dialect.type_descriptor(self))
-
- def __getstate__(self):
- d = self.__dict__.copy()
- d.pop('_impl_dict', None)
- return d
-
- def bind_processor(self, dialect):
- """Return a conversion function for processing bind values.
-
- Returns a callable which will receive a bind parameter value
- as the sole positional argument and will return a value to
- send to the DB-API.
-
- If processing is not necessary, the method should return ``None``.
-
- """
- return None
-
- def result_processor(self, dialect, coltype):
- """Return a conversion function for processing result row values.
-
- Returns a callable which will receive a result row column
- value as the sole positional argument and will return a value
- to return to the user.
-
- If processing is not necessary, the method should return ``None``.
-
- """
- return None
-
- def adapt(self, cls):
- return cls()
class UserDefinedType(TypeEngine):
"""Base for user defined types.
@@ -264,7 +271,7 @@ class UserDefinedType(TypeEngine):
"""
return op
-class TypeDecorator(AbstractType):
+class TypeDecorator(TypeEngine):
"""Allows the creation of types which add additional functionality
to an existing type.
@@ -355,9 +362,6 @@ class TypeDecorator(AbstractType):
"type being decorated")
self.impl = to_instance(self.__class__.impl, *args, **kwargs)
- def adapt(self, cls):
- return cls()
-
def dialect_impl(self, dialect):
key = (dialect.__class__, dialect.server_version_info)
@@ -386,10 +390,6 @@ class TypeDecorator(AbstractType):
return tt
@util.memoized_property
- def _impl_dict(self):
- return {}
-
- @util.memoized_property
def _type_affinity(self):
return self.impl._type_affinity
@@ -1320,6 +1320,7 @@ class _Binary(TypeEngine):
def bind_processor(self, dialect):
DBAPIBinary = dialect.dbapi.Binary
def process(value):
+ x = self
if value is not None:
return DBAPIBinary(value)
else:
@@ -1618,7 +1619,13 @@ class PickleType(MutableType, TypeDecorator):
self.mutable = mutable
self.comparator = comparator
super(PickleType, self).__init__()
-
+
+ def __reduce__(self):
+ return PickleType, (self.protocol,
+ None,
+ self.mutable,
+ self.comparator)
+
def bind_processor(self, dialect):
impl_processor = self.impl.bind_processor(dialect)
dumps = self.pickler.dumps
diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py
index ef315445d..98c894e5b 100644
--- a/lib/sqlalchemy/util/_collections.py
+++ b/lib/sqlalchemy/util/_collections.py
@@ -186,7 +186,7 @@ class OrderedDict(dict):
return [self[key] for key in self._list]
def itervalues(self):
- return iter(self.values())
+ return iter([self[key] for key in self._list])
def keys(self):
return list(self._list)