diff options
author | Gaëtan de Menten <gdementen@gmail.com> | 2010-02-13 22:53:39 +0000 |
---|---|---|
committer | Gaëtan de Menten <gdementen@gmail.com> | 2010-02-13 22:53:39 +0000 |
commit | 165609a190665f5453417c9c935a834714c7f5a5 (patch) | |
tree | 90d3d0da3f233cf6fc211f367eea0dba661b098e /lib/sqlalchemy/processors.py | |
parent | f2974ef3993e02646a2dfade5feb74afb78f370f (diff) | |
download | sqlalchemy-165609a190665f5453417c9c935a834714c7f5a5.tar.gz |
- Added an optional C extension to speed up the sql layer by
reimplementing the highest impact functions.
The actual speedups will depend heavily on your DBAPI and
the mix of datatypes used in your tables, and can vary from
a 50% improvement to more than 200%. It also provides a modest
(~20%) indirect improvement to ORM speed for large queries.
Note that it is *not* built/installed by default.
See README for installation instructions.
- The most common result processors conversion function were
moved to the new "processors" module. Dialect authors are
encouraged to use those functions whenever they correspond
to their needs instead of implementing custom ones.
Diffstat (limited to 'lib/sqlalchemy/processors.py')
-rw-r--r-- | lib/sqlalchemy/processors.py | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/sqlalchemy/processors.py b/lib/sqlalchemy/processors.py new file mode 100644 index 000000000..cb4b72545 --- /dev/null +++ b/lib/sqlalchemy/processors.py @@ -0,0 +1,90 @@ +# processors.py +# Copyright (C) 2010 Gaetan de Menten gdementen@gmail.com +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +"""defines generic type conversion functions, as used in result processors. + +They all share one common characteristic: None is passed through unchanged. + +""" + +import codecs +import re +import datetime + +def str_to_datetime_processor_factory(regexp, type_): + rmatch = regexp.match + # Even on python2.6 datetime.strptime is both slower than this code + # and it does not support microseconds. + def process(value): + if value is None: + return None + else: + return type_(*map(int, rmatch(value).groups(0))) + return process + +try: + from sqlalchemy.cprocessors import UnicodeResultProcessor, \ + DecimalResultProcessor, \ + to_float, to_str, int_to_boolean, \ + str_to_datetime, str_to_time, \ + str_to_date + + def to_unicode_processor_factory(encoding): + return UnicodeResultProcessor(encoding).process + + def to_decimal_processor_factory(target_class): + return DecimalResultProcessor(target_class).process + +except ImportError: + def to_unicode_processor_factory(encoding): + decoder = codecs.getdecoder(encoding) + + def process(value): + if value is None: + return None + else: + # decoder returns a tuple: (value, len). Simply dropping the + # len part is safe: it is done that way in the normal + # 'xx'.decode(encoding) code path. + # cfr python-source/Python/codecs.c:PyCodec_Decode + return decoder(value)[0] + return process + + def to_decimal_processor_factory(target_class): + def process(value): + if value is None: + return None + else: + return target_class(str(value)) + return process + + def to_float(value): + if value is None: + return None + else: + return float(value) + + def to_str(value): + if value is None: + return None + else: + return str(value) + + def int_to_boolean(value): + if value is None: + return None + else: + return value and True or False + + DATETIME_RE = re.compile("(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)(?:\.(\d+))?") + TIME_RE = re.compile("(\d+):(\d+):(\d+)(?:\.(\d+))?") + DATE_RE = re.compile("(\d+)-(\d+)-(\d+)") + + str_to_datetime = str_to_datetime_processor_factory(DATETIME_RE, + datetime.datetime) + str_to_time = str_to_datetime_processor_factory(TIME_RE, datetime.time) + str_to_date = str_to_datetime_processor_factory(DATE_RE, datetime.date) + |