summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-06-17 00:53:33 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-06-17 00:53:33 +0000
commit1ffed8432e282aa57ecde9f3e4ca778a1756ddc0 (patch)
tree0849938da765ee182bc23284337b214e3202e5d1 /lib
parent3736b3ddff65f6d4b7e273b040b48b19dbac9b66 (diff)
downloadsqlalchemy-1ffed8432e282aa57ecde9f3e4ca778a1756ddc0.tar.gz
cast converted into its own ClauseElement so that it can have an explicit compilationrel_0_2_3
function in ANSICompiler MySQLCompiler then skips most CAST calls since it only seems to support the standard syntax for Date types; other types now a TODO for MySQL then, polymorphic_union() function now CASTs null()s to the type corresponding to the columns in the UNION, since postgres doesnt like mixing NULL with integer types (long road for that .....)
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/ansisql.py8
-rw-r--r--lib/sqlalchemy/databases/mysql.py10
-rw-r--r--lib/sqlalchemy/orm/util.py5
-rw-r--r--lib/sqlalchemy/sql.py25
4 files changed, 37 insertions, 11 deletions
diff --git a/lib/sqlalchemy/ansisql.py b/lib/sqlalchemy/ansisql.py
index cdd860440..82abb9577 100644
--- a/lib/sqlalchemy/ansisql.py
+++ b/lib/sqlalchemy/ansisql.py
@@ -231,7 +231,13 @@ class ANSICompiler(sql.Compiled):
self.strings[list] = "(" + string.join([self.get_str(c) for c in list.clauses], ' ') + ")"
else:
self.strings[list] = string.join([self.get_str(c) for c in list.clauses], ' ')
-
+
+ def visit_cast(self, cast):
+ if len(self.select_stack):
+ # not sure if we want to set the typemap here...
+ self.typemap.setdefault("CAST", cast.type)
+ self.strings[cast] = "CAST(%s AS %s)" % (self.strings[cast.clause],self.strings[cast.typeclause])
+
def visit_function(self, func):
if len(self.select_stack):
self.typemap.setdefault(func.name, func.type)
diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py
index aa05134d0..e32d6f120 100644
--- a/lib/sqlalchemy/databases/mysql.py
+++ b/lib/sqlalchemy/databases/mysql.py
@@ -9,7 +9,6 @@ import sys, StringIO, string, types, re, datetime
from sqlalchemy import sql,engine,schema,ansisql
from sqlalchemy.engine import default
import sqlalchemy.types as sqltypes
-import sqlalchemy.databases.information_schema as ischema
import sqlalchemy.exceptions as exceptions
try:
@@ -250,6 +249,15 @@ class MySQLDialect(ansisql.ANSIDialect):
class MySQLCompiler(ansisql.ANSICompiler):
+ def visit_cast(self, cast):
+ """hey ho MySQL supports almost no types at all for CAST"""
+ if (isinstance(cast.type, sqltypes.Date) or isinstance(cast.type, sqltypes.Time) or isinstance(cast.type, sqltypes.DateTime)):
+ return super(MySQLCompiler, self).visit_cast(cast)
+ else:
+ # so just skip the CAST altogether for now.
+ # TODO: put whatever MySQL does for CAST here.
+ self.strings[cast] = self.strings[cast.clause]
+
def limit_clause(self, select):
text = ""
if select.limit is not None:
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 86799b311..10f7b4e80 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -24,7 +24,7 @@ class CascadeOptions(object):
def polymorphic_union(table_map, typecolname, aliasname='p_union'):
colnames = util.Set()
colnamemaps = {}
-
+ types = {}
for key in table_map.keys():
table = table_map[key]
@@ -37,13 +37,14 @@ def polymorphic_union(table_map, typecolname, aliasname='p_union'):
for c in table.c:
colnames.add(c.name)
m[c.name] = c
+ types[c.name] = c.type
colnamemaps[table] = m
def col(name, table):
try:
return colnamemaps[table][name]
except KeyError:
- return sql.null().label(name)
+ return sql.cast(sql.null(), types[name]).label(name)
result = []
for type, table in table_map.iteritems():
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py
index 0cacea12d..d978ee208 100644
--- a/lib/sqlalchemy/sql.py
+++ b/lib/sqlalchemy/sql.py
@@ -153,12 +153,9 @@ def cast(clause, totype, **kwargs):
or
cast(table.c.timestamp, DATE)
"""
- # handle non-column clauses (e.g. cast(1234, TEXT)
- if not hasattr(clause, 'label'):
- clause = literal(clause)
- totype = sqltypes.to_instance(totype)
- return Function('CAST', CompoundClause("AS", clause, TypeClause(totype)), type=totype, **kwargs)
-
+ return Cast(clause, totype, **kwargs)
+
+
def exists(*args, **params):
params['correlate'] = True
s = select(*args, **params)
@@ -320,6 +317,7 @@ class ClauseVisitor(object):
def visit_clauselist(self, list):pass
def visit_calculatedclause(self, calcclause):pass
def visit_function(self, func):pass
+ def visit_cast(self, cast):pass
def visit_label(self, label):pass
def visit_typeclause(self, typeclause):pass
@@ -974,7 +972,20 @@ class Function(CalculatedClause):
c.accept_visitor(visitor)
visitor.visit_function(self)
-
+class Cast(ColumnElement):
+ def __init__(self, clause, totype, **kwargs):
+ if not hasattr(clause, 'label'):
+ clause = literal(clause)
+ self.type = sqltypes.to_instance(totype)
+ self.clause = clause
+ self.typeclause = TypeClause(self.type)
+ def accept_visitor(self, visitor):
+ self.clause.accept_visitor(visitor)
+ self.typeclause.accept_visitor(visitor)
+ visitor.visit_cast(self)
+ def _get_from_objects(self):
+ return self.clause._get_from_objects()
+
class FunctionGenerator(object):
"""generates Function objects based on getattr calls"""
def __init__(self, engine=None):