Packages update

This commit is contained in:
Ruud
2012-02-11 16:28:06 +01:00
parent 3bbf1126c3
commit 02e01fb2d6
217 changed files with 26395 additions and 21194 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# mssql/__init__.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
+3 -2
View File
@@ -1,5 +1,5 @@
# mssql/adodbapi.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -8,6 +8,7 @@
The adodbapi dialect is not implemented for 0.6 at this time.
"""
import datetime
from sqlalchemy import types as sqltypes, util
from sqlalchemy.dialects.mssql.base import MSDateTime, MSDialect
import sys
@@ -61,7 +62,7 @@ class MSDialect_adodbapi(MSDialect):
connectors.append("Integrated Security=SSPI")
return [[";".join (connectors)], {}]
def is_disconnect(self, e):
def is_disconnect(self, e, connection, cursor):
return isinstance(e, self.dbapi.adodbapi.DatabaseError) and \
"'connection failure'" in str(e)
+144 -69
View File
@@ -1,5 +1,5 @@
# mssql/base.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -56,7 +56,7 @@ MSNVarchar, MSText, and MSNText. For example::
from sqlalchemy.dialects.mssql import VARCHAR
Column('login', VARCHAR(32, collation='Latin1_General_CI_AS'))
When such a column is associated with a :class:`Table`, the
When such a column is associated with a :class:`.Table`, the
CREATE TABLE statement for this column will yield::
login VARCHAR(32) COLLATE Latin1_General_CI_AS NULL
@@ -130,17 +130,57 @@ which has triggers::
# ...,
implicit_returning=False
)
Declarative form::
class MyClass(Base):
# ...
__table_args__ = {'implicit_returning':False}
This option can also be specified engine-wide using the
``implicit_returning=False`` argument on :func:`.create_engine`.
Enabling Snapshot Isolation
---------------------------
Not necessarily specific to SQLAlchemy, SQL Server has a default transaction
isolation mode that locks entire tables, and causes even mildly concurrent
applications to have long held locks and frequent deadlocks.
Enabling snapshot isolation for the database as a whole is recommended
for modern levels of concurrency support. This is accomplished via the
following ALTER DATABASE commands executed at the SQL prompt::
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
Background on SQL Server snapshot isolation is available at
http://msdn.microsoft.com/en-us/library/ms175095.aspx.
Scalar Select Comparisons
-------------------------
The MSSQL dialect contains a legacy behavior whereby comparing
a scalar select to a value using the ``=`` or ``!=`` operator
will resolve to IN or NOT IN, respectively. This behavior is
deprecated and will be removed in 0.8 - the ``s.in_()``/``~s.in_()`` operators
should be used when IN/NOT IN are desired.
For the time being, the existing behavior prevents a comparison
between scalar select and another value that actually wants to use ``=``.
To remove this behavior in a forwards-compatible way, apply this
compilation rule by placing the following code at the module import
level::
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import _BinaryExpression
from sqlalchemy.sql.compiler import SQLCompiler
@compiles(_BinaryExpression, 'mssql')
def override_legacy_binary(element, compiler, **kw):
return SQLCompiler.visit_binary(compiler, element, **kw)
Known Issues
------------
@@ -149,20 +189,19 @@ Known Issues
SQL Server 2005
"""
import datetime, decimal, inspect, operator, sys, re
import itertools
import datetime, operator, re
from sqlalchemy import sql, schema as sa_schema, exc, util
from sqlalchemy.sql import select, compiler, expression, \
operators as sql_operators, \
functions as sql_functions, util as sql_util
util as sql_util, cast
from sqlalchemy.engine import default, base, reflection
from sqlalchemy import types as sqltypes
from sqlalchemy import processors
from sqlalchemy.types import INTEGER, BIGINT, SMALLINT, DECIMAL, NUMERIC, \
FLOAT, TIMESTAMP, DATETIME, DATE, BINARY,\
VARBINARY, BLOB
from sqlalchemy.dialects.mssql import information_schema as ischema
MS_2008_VERSION = (10,)
@@ -200,14 +239,13 @@ RESERVED_WORDS = set(
'writetext',
])
class REAL(sqltypes.Float):
"""A type for ``real`` numbers."""
class REAL(sqltypes.REAL):
__visit_name__ = 'REAL'
def __init__(self):
super(REAL, self).__init__(precision=24)
def __init__(self, **kw):
# REAL is a synonym for FLOAT(24) on SQL server
kw['precision'] = 24
super(REAL, self).__init__(**kw)
class TINYINT(sqltypes.Integer):
__visit_name__ = 'TINYINT'
@@ -258,7 +296,7 @@ class TIME(sqltypes.TIME):
return value
return process
_reg = re.compile(r"(\d+):(\d+):(\d+)(?:\.(\d+))?")
_reg = re.compile(r"(\d+):(\d+):(\d+)(?:\.(\d{0,6}))?")
def result_processor(self, dialect, coltype):
def process(value):
if isinstance(value, datetime.datetime):
@@ -289,7 +327,8 @@ class SMALLDATETIME(_DateTimeBase, sqltypes.DateTime):
class DATETIME2(_DateTimeBase, sqltypes.DateTime):
__visit_name__ = 'DATETIME2'
def __init__(self, precision=None, **kwargs):
def __init__(self, precision=None, **kw):
super(DATETIME2, self).__init__(**kw)
self.precision = precision
@@ -309,16 +348,15 @@ class _StringType(object):
class TEXT(_StringType, sqltypes.TEXT):
"""MSSQL TEXT type, for variable-length text up to 2^31 characters."""
def __init__(self, *args, **kw):
def __init__(self, length=None, collation=None, **kw):
"""Construct a TEXT.
:param collation: Optional, a column-level collation for this string
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.Text.__init__(self, *args, **kw)
sqltypes.Text.__init__(self, length, **kw)
class NTEXT(_StringType, sqltypes.UnicodeText):
"""MSSQL NTEXT type, for variable-length unicode text up to 2^30
@@ -326,24 +364,22 @@ class NTEXT(_StringType, sqltypes.UnicodeText):
__visit_name__ = 'NTEXT'
def __init__(self, *args, **kwargs):
def __init__(self, length=None, collation=None, **kw):
"""Construct a NTEXT.
:param collation: Optional, a column-level collation for this string
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kwargs.pop('collation', None)
_StringType.__init__(self, collation)
length = kwargs.pop('length', None)
sqltypes.UnicodeText.__init__(self, length, **kwargs)
sqltypes.UnicodeText.__init__(self, length, **kw)
class VARCHAR(_StringType, sqltypes.VARCHAR):
"""MSSQL VARCHAR type, for variable-length non-Unicode data with a maximum
of 8,000 characters."""
def __init__(self, *args, **kw):
def __init__(self, length=None, collation=None, **kw):
"""Construct a VARCHAR.
:param length: Optinal, maximum data length, in characters.
@@ -364,16 +400,15 @@ class VARCHAR(_StringType, sqltypes.VARCHAR):
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.VARCHAR.__init__(self, *args, **kw)
sqltypes.VARCHAR.__init__(self, length, **kw)
class NVARCHAR(_StringType, sqltypes.NVARCHAR):
"""MSSQL NVARCHAR type.
For variable-length unicode character data up to 4,000 characters."""
def __init__(self, *args, **kw):
def __init__(self, length=None, collation=None, **kw):
"""Construct a NVARCHAR.
:param length: Optional, Maximum data length, in characters.
@@ -382,15 +417,14 @@ class NVARCHAR(_StringType, sqltypes.NVARCHAR):
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.NVARCHAR.__init__(self, *args, **kw)
sqltypes.NVARCHAR.__init__(self, length, **kw)
class CHAR(_StringType, sqltypes.CHAR):
"""MSSQL CHAR type, for fixed-length non-Unicode data with a maximum
of 8,000 characters."""
def __init__(self, *args, **kw):
def __init__(self, length=None, collation=None, **kw):
"""Construct a CHAR.
:param length: Optinal, maximum data length, in characters.
@@ -411,16 +445,15 @@ class CHAR(_StringType, sqltypes.CHAR):
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.CHAR.__init__(self, *args, **kw)
sqltypes.CHAR.__init__(self, length, **kw)
class NCHAR(_StringType, sqltypes.NCHAR):
"""MSSQL NCHAR type.
For fixed-length unicode character data up to 4,000 characters."""
def __init__(self, *args, **kw):
def __init__(self, length=None, collation=None, **kw):
"""Construct an NCHAR.
:param length: Optional, Maximum data length, in characters.
@@ -429,9 +462,8 @@ class NCHAR(_StringType, sqltypes.NCHAR):
value. Accepts a Windows Collation Name or a SQL Collation Name.
"""
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.NCHAR.__init__(self, *args, **kw)
sqltypes.NCHAR.__init__(self, length, **kw)
class IMAGE(sqltypes.LargeBinary):
__visit_name__ = 'IMAGE'
@@ -510,7 +542,7 @@ ischema_names = {
class MSTypeCompiler(compiler.GenericTypeCompiler):
def _extend(self, spec, type_):
def _extend(self, spec, type_, length=None):
"""Extend a string-type declaration with standard SQL
COLLATE annotations.
@@ -521,8 +553,11 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
else:
collation = None
if type_.length:
spec = spec + "(%d)" % type_.length
if not length:
length = type_.length
if length:
spec = spec + "(%s)" % length
return ' '.join([c for c in (spec, collation)
if c is not None])
@@ -534,9 +569,6 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
else:
return "FLOAT(%(precision)s)" % {'precision': precision}
def visit_REAL(self, type_):
return "REAL"
def visit_TINYINT(self, type_):
return "TINYINT"
@@ -576,7 +608,8 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
return self._extend("TEXT", type_)
def visit_VARCHAR(self, type_):
return self._extend("VARCHAR", type_)
return self._extend("VARCHAR", type_,
length = type_.length or 'max')
def visit_CHAR(self, type_):
return self._extend("CHAR", type_)
@@ -585,7 +618,8 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
return self._extend("NCHAR", type_)
def visit_NVARCHAR(self, type_):
return self._extend("NVARCHAR", type_)
return self._extend("NVARCHAR", type_,
length = type_.length or 'max')
def visit_date(self, type_):
if self.dialect.server_version_info < MS_2008_VERSION:
@@ -605,6 +639,12 @@ class MSTypeCompiler(compiler.GenericTypeCompiler):
def visit_IMAGE(self, type_):
return "IMAGE"
def visit_VARBINARY(self, type_):
return self._extend(
"VARBINARY",
type_,
length=type_.length or 'max')
def visit_boolean(self, type_):
return self.visit_BIT(type_)
@@ -709,8 +749,8 @@ class MSSQLCompiler(compiler.SQLCompiler):
})
def __init__(self, *args, **kwargs):
super(MSSQLCompiler, self).__init__(*args, **kwargs)
self.tablealiases = {}
super(MSSQLCompiler, self).__init__(*args, **kwargs)
def visit_now_func(self, fn, **kw):
return "CURRENT_TIMESTAMP"
@@ -736,15 +776,21 @@ class MSSQLCompiler(compiler.SQLCompiler):
def get_select_precolumns(self, select):
""" MS-SQL puts TOP, it's version of LIMIT here """
if select._distinct or select._limit:
if select._distinct or select._limit is not None:
s = select._distinct and "DISTINCT " or ""
if select._limit:
# ODBC drivers and possibly others
# don't support bind params in the SELECT clause on SQL Server.
# so have to use literal here.
if select._limit is not None:
if not select._offset:
s += "TOP %s " % (select._limit,)
s += "TOP %d " % select._limit
return s
return compiler.SQLCompiler.get_select_precolumns(self, select)
def get_from_hint_text(self, table, text):
return text
def limit_clause(self, select):
# Limit in mssql is after the select keyword
return ""
@@ -758,7 +804,7 @@ class MSSQLCompiler(compiler.SQLCompiler):
# to use ROW_NUMBER(), an ORDER BY is required.
orderby = self.process(select._order_by_clause)
if not orderby:
raise exc.InvalidRequestError('MSSQL requires an order_by when '
raise exc.CompileError('MSSQL requires an order_by when '
'using an offset.')
_offset = select._offset
@@ -769,12 +815,12 @@ class MSSQLCompiler(compiler.SQLCompiler):
% orderby).label("mssql_rn")
).order_by(None).alias()
mssql_rn = sql.column('mssql_rn')
limitselect = sql.select([c for c in select.c if
c.key!='mssql_rn'])
limitselect.append_whereclause("mssql_rn>%d" % _offset)
limitselect.append_whereclause(mssql_rn> _offset)
if _limit is not None:
limitselect.append_whereclause("mssql_rn<=%d" %
(_limit + _offset))
limitselect.append_whereclause(mssql_rn<=(_limit + _offset))
return self.process(limitselect, iswrapper=True, **kwargs)
else:
return compiler.SQLCompiler.visit_select(self, select, **kwargs)
@@ -800,7 +846,6 @@ class MSSQLCompiler(compiler.SQLCompiler):
def visit_alias(self, alias, **kwargs):
# translate for schema-qualified table aliases
self.tablealiases[alias.original] = alias
kwargs['mssql_aliased'] = alias.original
return super(MSSQLCompiler, self).visit_alias(alias, **kwargs)
@@ -809,6 +854,9 @@ class MSSQLCompiler(compiler.SQLCompiler):
return 'DATEPART("%s", %s)' % \
(field, self.process(extract.expr, **kw))
def visit_savepoint(self, savepoint_stmt):
return "SAVE TRANSACTION %s" % self.preparer.format_savepoint(savepoint_stmt)
def visit_rollback_to_savepoint(self, savepoint_stmt):
return ("ROLLBACK TRANSACTION %s"
% self.preparer.format_savepoint(savepoint_stmt))
@@ -866,6 +914,10 @@ class MSSQLCompiler(compiler.SQLCompiler):
)
):
op = binary.operator == operator.eq and "IN" or "NOT IN"
util.warn_deprecated("Comparing a scalar select using ``=``/``!=`` will "
"no longer produce IN/NOT IN in 0.8. To remove this "
"behavior immediately, use the recipe at "
"http://www.sqlalchemy.org/docs/07/dialects/mssql.html#scalar-select-comparisons")
return self.process(
expression._BinaryExpression(binary.left,
binary.right, op),
@@ -977,7 +1029,7 @@ class MSDDLCompiler(compiler.DDLCompiler):
colspec += " NULL"
if column.table is None:
raise exc.InvalidRequestError(
raise exc.CompileError(
"mssql requires Table-bound columns "
"in order to generate DDL")
@@ -1066,12 +1118,12 @@ class MSDialect(default.DefaultDialect):
super(MSDialect, self).__init__(**opts)
def do_savepoint(self, connection, name):
util.warn("Savepoint support in mssql is experimental and "
"may lead to data loss.")
# give the DBAPI a push
connection.execute("IF @@TRANCOUNT = 0 BEGIN TRANSACTION")
connection.execute("SAVE TRANSACTION %s" % name)
super(MSDialect, self).do_savepoint(connection, name)
def do_release_savepoint(self, connection, name):
# SQL Server does not support RELEASE SAVEPOINT
pass
def initialize(self, connection):
@@ -1108,15 +1160,20 @@ class MSDialect(default.DefaultDialect):
pass
return self.schema_name
def _unicode_cast(self, column):
if self.server_version_info >= MS_2005_VERSION:
return cast(column, NVARCHAR(_warn_on_bytestring=False))
else:
return column
def has_table(self, connection, tablename, schema=None):
current_schema = schema or self.default_schema_name
columns = ischema.columns
whereclause = self._unicode_cast(columns.c.table_name)==tablename
if current_schema:
whereclause = sql.and_(columns.c.table_name==tablename,
whereclause = sql.and_(whereclause,
columns.c.table_schema==current_schema)
else:
whereclause = columns.c.table_name==tablename
s = sql.select([columns], whereclause)
c = connection.execute(s)
return c.first() is not None
@@ -1180,7 +1237,10 @@ class MSDialect(default.DefaultDialect):
sqltypes.String(convert_unicode=True)),
sql.bindparam('schname', current_schema,
sqltypes.String(convert_unicode=True))
]
],
typemap = {
'name':sqltypes.Unicode()
}
)
)
indexes = {}
@@ -1206,7 +1266,11 @@ class MSDialect(default.DefaultDialect):
sqltypes.String(convert_unicode=True)),
sql.bindparam('schname', current_schema,
sqltypes.String(convert_unicode=True))
]),
],
typemap = {
'name':sqltypes.Unicode()
}
),
)
for row in rp:
if row['index_id'] in indexes:
@@ -1217,14 +1281,25 @@ class MSDialect(default.DefaultDialect):
@reflection.cache
def get_view_definition(self, connection, viewname, schema=None, **kw):
current_schema = schema or self.default_schema_name
views = ischema.views
s = sql.select([views.c.view_definition],
sql.and_(
views.c.table_schema == current_schema,
views.c.table_name == viewname
),
rp = connection.execute(
sql.text(
"select definition from sys.sql_modules as mod, "
"sys.views as views, "
"sys.schemas as sch"
" where "
"mod.object_id=views.object_id and "
"views.schema_id=sch.schema_id and "
"views.name=:viewname and sch.name=:schname",
bindparams=[
sql.bindparam('viewname', viewname,
sqltypes.String(convert_unicode=True)),
sql.bindparam('schname', current_schema,
sqltypes.String(convert_unicode=True))
]
)
)
rp = connection.execute(s)
if rp:
view_def = rp.scalar()
return view_def
@@ -1,12 +1,12 @@
# mssql/information_schema.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
# TODO: should be using the sys. catalog with SQL Server, not information schema
from sqlalchemy import Table, MetaData, Column, ForeignKey
from sqlalchemy import Table, MetaData, Column
from sqlalchemy.types import String, Unicode, Integer, TypeDecorator
ischema = MetaData()
+2 -6
View File
@@ -1,5 +1,5 @@
# mssql/mxodbc.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -51,15 +51,11 @@ of ``False`` will uncondtionally use string-escaped parameters.
"""
import re
import sys
from sqlalchemy import types as sqltypes
from sqlalchemy import util
from sqlalchemy.connectors.mxodbc import MxODBCConnector
from sqlalchemy.dialects.mssql.pyodbc import MSExecutionContext_pyodbc
from sqlalchemy.dialects.mssql.base import (MSExecutionContext, MSDialect,
MSSQLCompiler,
from sqlalchemy.dialects.mssql.base import (MSDialect,
MSSQLStrictCompiler,
_MSDateTime, _MSDate, TIME)
+2 -4
View File
@@ -1,5 +1,5 @@
# mssql/pymssql.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -41,7 +41,6 @@ Please consult the pymssql documentation for further information.
from sqlalchemy.dialects.mssql.base import MSDialect
from sqlalchemy import types as sqltypes, util, processors
import re
import decimal
class _MSNumeric_pymssql(sqltypes.Numeric):
def result_processor(self, dialect, type_):
@@ -52,7 +51,6 @@ class _MSNumeric_pymssql(sqltypes.Numeric):
class MSDialect_pymssql(MSDialect):
supports_sane_rowcount = False
max_identifier_length = 30
driver = 'pymssql'
colspecs = util.update_copy(
@@ -96,7 +94,7 @@ class MSDialect_pymssql(MSDialect):
opts['host'] = "%s:%s" % (opts['host'], port)
return [[], opts]
def is_disconnect(self, e):
def is_disconnect(self, e, connection, cursor):
for msg in (
"Error 10054",
"Not connected to any MS SQL server",
+32 -17
View File
@@ -1,5 +1,5 @@
# mssql/pyodbc.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -35,27 +35,31 @@ Examples of pyodbc connection string URLs:
dsn=mydsn;UID=user;PWD=pass;LANGUAGE=us_english
* ``mssql+pyodbc://user:pass@host/db`` - connects using a connection string
dynamically created that would appear like::
* ``mssql+pyodbc://user:pass@host/db`` - connects using a connection
that would appear like::
DRIVER={SQL Server};Server=host;Database=db;UID=user;PWD=pass
* ``mssql+pyodbc://user:pass@host:123/db`` - connects using a connection
string that is dynamically created, which also includes the port
information using the comma syntax. If your connection string
requires the port information to be passed as a ``port`` keyword
see the next example. This will create the following connection
string::
string which includes the port
information using the comma syntax. This will create the following
connection string::
DRIVER={SQL Server};Server=host,123;Database=db;UID=user;PWD=pass
* ``mssql+pyodbc://user:pass@host/db?port=123`` - connects using a connection
string that is dynamically created that includes the port
string that includes the port
information as a separate ``port`` keyword. This will create the
following connection string::
DRIVER={SQL Server};Server=host;Database=db;UID=user;PWD=pass;port=123
* ``mssql+pyodbc://user:pass@host/db?driver=MyDriver`` - connects using a connection
string that includes a custom
ODBC driver name. This will create the following connection string::
DRIVER={MyDriver};Server=host;Database=db;UID=user;PWD=pass
If you require a connection string that is outside the options
presented above, use the ``odbc_connect`` keyword to pass in a
urlencoded connection string. What gets passed in will be urldecoded
@@ -94,7 +98,12 @@ class _MSNumeric_pyodbc(sqltypes.Numeric):
"""
def bind_processor(self, dialect):
super_process = super(_MSNumeric_pyodbc, self).bind_processor(dialect)
super_process = super(_MSNumeric_pyodbc, self).\
bind_processor(dialect)
if not dialect._need_decimal_fix:
return super_process
def process(value):
if self.asdecimal and \
@@ -112,31 +121,35 @@ class _MSNumeric_pyodbc(sqltypes.Numeric):
return value
return process
# these routines needed for older versions of pyodbc.
# as of 2.1.8 this logic is integrated.
def _small_dec_to_string(self, value):
return "%s0.%s%s" % (
(value < 0 and '-' or ''),
'0' * (abs(value.adjusted()) - 1),
"".join([str(nint) for nint in value._int]))
"".join([str(nint) for nint in value.as_tuple()[1]]))
def _large_dec_to_string(self, value):
_int = value.as_tuple()[1]
if 'E' in str(value):
result = "%s%s%s" % (
(value < 0 and '-' or ''),
"".join([str(s) for s in value._int]),
"0" * (value.adjusted() - (len(value._int)-1)))
"".join([str(s) for s in _int]),
"0" * (value.adjusted() - (len(_int)-1)))
else:
if (len(value._int) - 1) > value.adjusted():
if (len(_int) - 1) > value.adjusted():
result = "%s%s.%s" % (
(value < 0 and '-' or ''),
"".join(
[str(s) for s in value._int][0:value.adjusted() + 1]),
[str(s) for s in _int][0:value.adjusted() + 1]),
"".join(
[str(s) for s in value._int][value.adjusted() + 1:]))
[str(s) for s in _int][value.adjusted() + 1:]))
else:
result = "%s%s" % (
(value < 0 and '-' or ''),
"".join(
[str(s) for s in value._int][0:value.adjusted() + 1]))
[str(s) for s in _int][0:value.adjusted() + 1]))
return result
@@ -206,5 +219,7 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect):
self.description_encoding = description_encoding
self.use_scope_identity = self.dbapi and \
hasattr(self.dbapi.Cursor, 'nextset')
self._need_decimal_fix = self.dbapi and \
self._dbapi_version() < (2, 1, 8)
dialect = MSDialect_pyodbc
+1 -1
View File
@@ -1,5 +1,5 @@
# mssql/zxjdbc.py
# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php