summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-27 20:03:33 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-27 20:03:33 +0000
commitcd6af2e03b8ffba0c7d6b8906c178fd1aa742920 (patch)
tree4da300a9f8441274624b3db49236322476954c07 /lib/sqlalchemy
parent8b1096eea4fdc081a803279c57226ac07481d788 (diff)
downloadsqlalchemy-cd6af2e03b8ffba0c7d6b8906c178fd1aa742920.tar.gz
working on pyodbc / mxodbc
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/connectors/mxodbc.py17
-rw-r--r--lib/sqlalchemy/connectors/pyodbc.py1
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py77
-rw-r--r--lib/sqlalchemy/dialects/mssql/mxodbc.py3
-rw-r--r--lib/sqlalchemy/dialects/mssql/pyodbc.py3
-rw-r--r--lib/sqlalchemy/engine/default.py5
-rw-r--r--lib/sqlalchemy/sql/compiler.py1
-rw-r--r--lib/sqlalchemy/test/requires.py6
8 files changed, 75 insertions, 38 deletions
diff --git a/lib/sqlalchemy/connectors/mxodbc.py b/lib/sqlalchemy/connectors/mxodbc.py
index 93e323fb9..ef7852f61 100644
--- a/lib/sqlalchemy/connectors/mxodbc.py
+++ b/lib/sqlalchemy/connectors/mxodbc.py
@@ -1,5 +1,7 @@
import sys
+import re
+
from sqlalchemy.connectors import Connector
class MxODBCConnector(Connector):
@@ -8,7 +10,8 @@ class MxODBCConnector(Connector):
supports_sane_multi_rowcount = False
supports_unicode_statements = False
supports_unicode_binds = False
-
+ supports_native_decimal = False
+
@classmethod
def dbapi(cls):
platform = sys.platform
@@ -61,4 +64,14 @@ class MxODBCConnector(Connector):
else:
return False
-
+ def _get_server_version_info(self, connection):
+ dbapi_con = connection.connection
+ version = []
+ r = re.compile('[.\-]')
+ # 18 == pyodbc.SQL_DBMS_VER
+ for n in r.split(dbapi_con.getinfo(18)[1]):
+ try:
+ version.append(int(n))
+ except ValueError:
+ version.append(n)
+ return tuple(version)
diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py
index 46b0556d5..6abdbf0dd 100644
--- a/lib/sqlalchemy/connectors/pyodbc.py
+++ b/lib/sqlalchemy/connectors/pyodbc.py
@@ -12,6 +12,7 @@ class PyODBCConnector(Connector):
# PyODBC unicode is broken on UCS-4 builds
supports_unicode = sys.maxunicode == 65535
supports_unicode_statements = supports_unicode
+ supports_native_decimal = True
default_paramstyle = 'named'
# for non-DSN connections, this should
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index 1ce3cbde8..dc767882b 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -279,13 +279,17 @@ RESERVED_WORDS = set(
class _MSNumeric(sqltypes.Numeric):
def result_processor(self, dialect, coltype):
if self.asdecimal:
- return processors.to_decimal_processor_factory(decimal.Decimal)
+ if getattr(self, 'scale', None) is not None and dialect.supports_native_decimal:
+ return None
+ else:
+ return processors.to_decimal_processor_factory(decimal.Decimal)
else:
#XXX: if the DBAPI returns a float (this is likely, given the
# processor when asdecimal is True), this should be a None
# processor instead.
return processors.to_float
-
+ return None
+
def bind_processor(self, dialect):
def process(value):
if isinstance(value, decimal.Decimal):
@@ -797,14 +801,18 @@ class MSExecutionContext(default.DefaultExecutionContext):
else:
self.cursor.execute("SELECT @@identity AS lastrowid")
# fetchall() ensures the cursor is consumed without closing it
- row = self.cursor.fetchall()[0]
+ row = self.cursor.fetchall()[0]
self._lastrowid = int(row[0])
if (self.isinsert or self.isupdate or self.isdelete) and self.compiled.returning:
self._result_proxy = base.FullyBufferedResultProxy(self)
if self._enable_identity_insert:
- self.cursor.execute("SET IDENTITY_INSERT %s OFF" % self.dialect.identifier_preparer.format_table(self.compiled.statement.table))
+ self.cursor.execute(
+ "SET IDENTITY_INSERT %s OFF" %
+ self.dialect.identifier_preparer.
+ format_table(self.compiled.statement.table)
+ )
def get_lastrowid(self):
return self._lastrowid
@@ -1080,7 +1088,7 @@ class MSDialect(default.DefaultDialect):
query_timeout=None,
use_scope_identity=True,
max_identifier_length=None,
- schema_name="dbo", **opts):
+ schema_name=u"dbo", **opts):
self.query_timeout = int(query_timeout or 0)
self.schema_name = schema_name
@@ -1099,7 +1107,8 @@ class MSDialect(default.DefaultDialect):
def initialize(self, connection):
super(MSDialect, self).initialize(connection)
- if self.server_version_info >= MS_2005_VERSION and 'implicit_returning' not in self.__dict__:
+ if self.server_version_info >= MS_2005_VERSION and \
+ 'implicit_returning' not in self.__dict__:
self.implicit_returning = True
def _get_default_schema_name(self, connection):
@@ -1115,7 +1124,7 @@ class MSDialect(default.DefaultDialect):
try:
default_schema_name = connection.scalar(query, [user_name])
if default_schema_name is not None:
- return default_schema_name
+ return unicode(default_schema_name)
except:
pass
return self.schema_name
@@ -1282,34 +1291,34 @@ class MSDialect(default.DefaultDialect):
name='%s_identity' % col_name)
break
cursor.close()
- if ic is not None:
- try:
- # is this table_fullname reliable?
- table_fullname = "%s.%s" % (current_schema, tablename)
- cursor = connection.execute(
- sql.text("select ident_seed(:seed), ident_incr(:incr)"),
- {'seed':table_fullname, 'incr':table_fullname}
+
+ if ic is not None and self.server_version_info >= MS_2005_VERSION:
+ table_fullname = "%s.%s" % (current_schema, tablename)
+ cursor = connection.execute(
+ sql.text("select ident_seed(:tname), ident_incr(:tname)",
+ bindparams=[
+ sql.bindparam('tname', table_fullname)
+ ]
)
- row = cursor.first()
- if not row is None:
- colmap[ic]['sequence'].update({
- 'start' : int(row[0]),
- 'increment' : int(row[1])
- })
- except:
- # ignoring it, works just like before
- pass
+ )
+ row = cursor.first()
+ if not row is None:
+ colmap[ic]['sequence'].update({
+ 'start' : int(row[0]),
+ 'increment' : int(row[1])
+ })
return cols
@reflection.cache
def get_primary_keys(self, connection, tablename, schema=None, **kw):
current_schema = schema or self.default_schema_name
pkeys = []
- # Add constraints
- RR = ischema.ref_constraints #information_schema.referential_constraints
- TC = ischema.constraints #information_schema.table_constraints
- C = ischema.key_constraints.alias('C') #information_schema.constraint_column_usage: the constrained column
- R = ischema.key_constraints.alias('R') #information_schema.constraint_column_usage: the referenced column
+ RR = ischema.ref_constraints # information_schema.referential_constraints
+ TC = ischema.constraints # information_schema.table_constraints
+ C = ischema.key_constraints.alias('C') # information_schema.constraint_column_usage:
+ # the constrained column
+ R = ischema.key_constraints.alias('R') # information_schema.constraint_column_usage:
+ # the referenced column
# Primary key constraints
s = sql.select([C.c.column_name, TC.c.constraint_type],
@@ -1329,13 +1338,16 @@ class MSDialect(default.DefaultDialect):
# Add constraints
RR = ischema.ref_constraints #information_schema.referential_constraints
TC = ischema.constraints #information_schema.table_constraints
- C = ischema.key_constraints.alias('C') #information_schema.constraint_column_usage: the constrained column
- R = ischema.key_constraints.alias('R') #information_schema.constraint_column_usage: the referenced column
+ C = ischema.key_constraints.alias('C') # information_schema.constraint_column_usage:
+ # the constrained column
+ R = ischema.key_constraints.alias('R') # information_schema.constraint_column_usage:
+ # the referenced column
# Foreign key constraints
s = sql.select([C.c.column_name,
R.c.table_schema, R.c.table_name, R.c.column_name,
- RR.c.constraint_name, RR.c.match_option, RR.c.update_rule, RR.c.delete_rule],
+ RR.c.constraint_name, RR.c.match_option, RR.c.update_rule,
+ RR.c.delete_rule],
sql.and_(C.c.table_name == tablename,
C.c.table_schema == current_schema,
C.c.constraint_name == RR.c.constraint_name,
@@ -1378,6 +1390,3 @@ class MSDialect(default.DefaultDialect):
return fkeys.values()
-
-# fixme. I added this for the tests to run. -Randall
-MSSQLDialect = MSDialect
diff --git a/lib/sqlalchemy/dialects/mssql/mxodbc.py b/lib/sqlalchemy/dialects/mssql/mxodbc.py
index bbaccd328..38d559e2b 100644
--- a/lib/sqlalchemy/dialects/mssql/mxodbc.py
+++ b/lib/sqlalchemy/dialects/mssql/mxodbc.py
@@ -10,7 +10,8 @@ from sqlalchemy.dialects.mssql.pyodbc import MSExecutionContext_pyodbc
MSExecutionContext_mxodbc = MSExecutionContext_pyodbc
class MSDialect_mxodbc(MxODBCConnector, MSDialect):
- supports_sane_rowcount = True
+ # FIXME: yikes, plain rowcount doesn't work ?
+ supports_sane_rowcount = False #True
supports_sane_multi_rowcount = False
execution_ctx_cls = MSExecutionContext_mxodbc
diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py
index 9a2a9e4e7..23ab0320c 100644
--- a/lib/sqlalchemy/dialects/mssql/pyodbc.py
+++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py
@@ -35,7 +35,8 @@ class MSExecutionContext_pyodbc(MSExecutionContext):
# We may have to skip over a number of result sets with no data (due to triggers, etc.)
while True:
try:
- # fetchall() ensures the cursor is consumed without closing it (FreeTDS particularly)
+ # fetchall() ensures the cursor is consumed
+ # without closing it (FreeTDS particularly)
row = self.cursor.fetchall()[0]
break
except self.dialect.dbapi.Error, e:
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index 74562a70e..ac933bdf4 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -39,6 +39,11 @@ class DefaultDialect(base.Dialect):
supports_native_enum = False
supports_native_boolean = False
+ # if the NUMERIC type
+ # returns decimal.Decimal.
+ # *not* the FLOAT type however.
+ supports_native_decimal = False
+
# Py3K
#supports_unicode_statements = True
#supports_unicode_binds = True
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 32aa2a992..60f74e923 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -852,6 +852,7 @@ class SQLCompiler(engine.Compiled):
if c.primary_key and \
need_pks and \
(
+ implicit_returning or
not postfetch_lastrowid or
c is not stmt.table._autoincrement_column
):
diff --git a/lib/sqlalchemy/test/requires.py b/lib/sqlalchemy/test/requires.py
index c97e6f5bb..0bf4689df 100644
--- a/lib/sqlalchemy/test/requires.py
+++ b/lib/sqlalchemy/test/requires.py
@@ -190,6 +190,12 @@ def unicode_ddl(fn):
exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'),
)
+def sane_rowcount(fn):
+ return _chain_decorators_on(
+ fn,
+ skip_if(lambda: not testing.db.dialect.supports_sane_rowcount)
+ )
+
def python2(fn):
return _chain_decorators_on(
fn,