summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-10-23 16:40:39 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-10-23 16:40:39 -0400
commit79c25ede440e80e15c4c789234157d0e9497349c (patch)
treee9517ef97e2b0a1ed8426b909135d21c23557772 /lib/sqlalchemy/sql
parentc01c6baf5715a13d707a4d57717f9ad1bc12027a (diff)
downloadsqlalchemy-79c25ede440e80e15c4c789234157d0e9497349c.tar.gz
- Added type_coerce(expr, type_) expression element.
Treats the given expression as the given type when evaluating expressions and processing result rows, but does not affect the generation of SQL, other than an anonymous label.
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/__init__.py1
-rw-r--r--lib/sqlalchemy/sql/compiler.py8
-rw-r--r--lib/sqlalchemy/sql/expression.py52
3 files changed, 57 insertions, 4 deletions
diff --git a/lib/sqlalchemy/sql/__init__.py b/lib/sqlalchemy/sql/__init__.py
index aa18eac17..2bb5f6ab4 100644
--- a/lib/sqlalchemy/sql/__init__.py
+++ b/lib/sqlalchemy/sql/__init__.py
@@ -47,6 +47,7 @@ from sqlalchemy.sql.expression import (
table,
text,
tuple_,
+ type_coerce,
union,
union_all,
update,
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index e47db7e28..d3b8bf023 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -153,6 +153,10 @@ class _CompileLabel(visitors.Visitable):
def __init__(self, col, name):
self.element = col
self.name = name
+
+ @property
+ def type(self):
+ return self.element.type
@property
def quote(self):
@@ -317,7 +321,7 @@ class SQLCompiler(engine.Compiled):
if result_map is not None:
result_map[labelname.lower()] = \
- (label.name, (label, label.element, labelname), label.element.type)
+ (label.name, (label, label.element, labelname), label.type)
return self.process(label.element,
within_columns_clause=True,
@@ -329,7 +333,7 @@ class SQLCompiler(engine.Compiled):
return self.process(label.element,
within_columns_clause=False,
**kw)
-
+
def visit_column(self, column, result_map=None, **kwargs):
name = column.name
if name is None:
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 219e3bf14..625893a68 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -45,8 +45,8 @@ __all__ = [
'except_', 'except_all', 'exists', 'extract', 'func', 'modifier',
'collate', 'insert', 'intersect', 'intersect_all', 'join', 'label',
'literal', 'literal_column', 'not_', 'null', 'or_', 'outparam',
- 'outerjoin', 'select', 'subquery', 'table', 'text', 'tuple_', 'union',
- 'union_all', 'update', ]
+ 'outerjoin', 'select', 'subquery', 'table', 'text', 'tuple_', 'type_coerce',
+ 'union', 'union_all', 'update', ]
PARSE_AUTOCOMMIT = util._symbol('PARSE_AUTOCOMMIT')
@@ -666,6 +666,54 @@ def tuple_(*expr):
"""
return _Tuple(*expr)
+
+def type_coerce(expr, type_):
+ """Coerce the given expression into the given type, on the Python side only.
+
+ :func:`.type_coerce` is roughly similar to :func:.`cast`, except no
+ "CAST" expression is rendered - the given type is only applied towards
+ expression typing and against received result values.
+
+ e.g.::
+
+ from sqlalchemy.types import TypeDecorator
+ import uuid
+
+ class AsGuid(TypeDecorator):
+ impl = String
+
+ def process_bind_param(self, value, dialect):
+ if value is not None:
+ return str(value)
+ else:
+ return None
+
+ def process_result_value(self, value, dialect):
+ if value is not None:
+ return uuid.UUID(value)
+ else:
+ return None
+
+ conn.execute(
+ select([type_coerce(mytable.c.ident, AsGuid)]).\\
+ where(
+ type_coerce(mytable.c.ident, AsGuid) ==
+ uuid.uuid3(uuid.NAMESPACE_URL, 'bar')
+ )
+ )
+
+ """
+ if hasattr(expr, '__clause_expr__'):
+ return type_coerce(expr.__clause_expr__())
+
+ elif not isinstance(expr, Visitable):
+ if expr is None:
+ return null()
+ else:
+ return literal(expr, type_=type_)
+ else:
+ return _Label(None, expr, type_=type_)
+
def label(name, obj):
"""Return a :class:`_Label` object for the