diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-06-17 01:18:31 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-06-17 01:18:31 +0000 |
| commit | 6ba5ecb379698830f4112a52d42cadbfeb5c8d09 (patch) | |
| tree | 0fbabb097d6d85e734d44354c71d0d162981f69b /lib/sqlalchemy | |
| parent | 909758df8edf5e319127216bc2c4ce0fe780de21 (diff) | |
| download | sqlalchemy-6ba5ecb379698830f4112a52d42cadbfeb5c8d09.tar.gz | |
- added Interval type to types.py [ticket:595]
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/types.py | 68 |
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 |
