summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-06-17 01:18:31 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-06-17 01:18:31 +0000
commit6ba5ecb379698830f4112a52d42cadbfeb5c8d09 (patch)
tree0fbabb097d6d85e734d44354c71d0d162981f69b /lib/sqlalchemy
parent909758df8edf5e319127216bc2c4ce0fe780de21 (diff)
downloadsqlalchemy-6ba5ecb379698830f4112a52d42cadbfeb5c8d09.tar.gz
- added Interval type to types.py [ticket:595]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/types.py68
1 files changed, 66 insertions, 2 deletions
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index ce642c158..7b2d49c37 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -8,11 +8,12 @@ __all__ = [ 'TypeEngine', 'TypeDecorator', 'NullTypeEngine',
'INT', 'CHAR', 'VARCHAR', 'NCHAR', 'TEXT', 'FLOAT', 'DECIMAL',
'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', 'BOOLEAN', 'String', 'Integer', 'SmallInteger','Smallinteger',
'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'Binary', 'Boolean', 'Unicode', 'PickleType', 'NULLTYPE',
- 'SMALLINT', 'DATE', 'TIME'
+ 'SMALLINT', 'DATE', 'TIME','Interval'
]
from sqlalchemy import util, exceptions
import inspect, weakref
+import datetime as dt
try:
import cPickle as pickle
except:
@@ -89,7 +90,7 @@ class TypeDecorator(AbstractType):
try:
return self.impl_dict[dialect]
except:
- typedesc = dialect.type_descriptor(self.impl)
+ typedesc = self.load_dialect_impl(dialect)
tt = self.copy()
if not isinstance(tt, self.__class__):
raise exceptions.AssertionError("Type object %s does not properly implement the copy() method, it must return an object of type %s" % (self, self.__class__))
@@ -97,6 +98,15 @@ class TypeDecorator(AbstractType):
self.impl_dict[dialect] = tt
return tt
+ def load_dialect_impl(self, dialect):
+ """loads the dialect-specific implementation of this type.
+
+ by default calls dialect.type_descriptor(self.impl), but
+ can be overridden to provide different behavior.
+ """
+
+ return dialect.type_descriptor(self.impl)
+
def __getattr__(self, key):
"""Proxy all other undefined accessors to the underlying implementation."""
@@ -334,6 +344,60 @@ class PickleType(MutableType, TypeDecorator):
class Boolean(TypeEngine):
pass
+
+class Interval(TypeDecorator):
+ """Type to be used in Column statements to store python timedeltas.
+
+ If it's possible it uses native engine features to store timedeltas
+ (now it's only PostgreSQL Interval type), if there is no such it
+ fallbacks to DateTime storage with converting from/to timedelta on the fly
+
+ Converting is very simple - just use epoch(zero timestamp, 01.01.1970) as
+ base, so if we need to store timedelta = 1 day (24 hours) in database it
+ will be stored as DateTime = '2nd Jan 1970 00:00', see convert_bind_param
+ and convert_result_value to actual conversion code
+ """
+ impl = None
+
+ def __init__(self,*args,**kwargs):
+ #avoid of getting instance of None type in __init__ of TypeDecorator
+ pass
+
+ def load_dialect_impl(self, dialect):
+ import sqlalchemy.databases.postgres as pg
+ """Checks if engine has native implementation of timedelta python type,
+ if so it returns right class to handle it, if there is no native support,
+ it fallback to engine's DateTime implementation class
+ """
+
+ if self.__hasNativeImpl(dialect):
+ #For now, only PostgreSQL has native timedelta types support
+ return pg.PGInterval()
+ else:
+ #All others should fallback to DateTime
+ return dialect.type_descriptor(DateTime)
+
+ def __hasNativeImpl(self,dialect):
+ import sqlalchemy.databases.postgres as pg
+ return dialect.__class__ in [pg.PGDialect]
+
+ def convert_bind_param(self, value, dialect):
+ if not self.__hasNativeImpl(dialect):
+ tmpval = dt.datetime.utcfromtimestamp(0) + value
+ return self.impl.convert_bind_param(tmpval,dialect)
+ else:
+ return self.impl.convert_bind_param(value,dialect)
+
+ def convert_result_value(self, value, dialect):
+ retval = self.impl.convert_result_value(value,dialect)
+ if not self.__hasNativeImpl(dialect):
+ return retval - dt.datetime.utcfromtimestamp(0)
+ else:
+ return retval
+
+ def is_mutable(self):
+ #neither datetime, nor PGInterval are mutable types
+ return False
class FLOAT(Float):pass
class TEXT(String):pass