Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# mssql/mxodbc.py 

2# Copyright (C) 2005-2020 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: http://www.opensource.org/licenses/mit-license.php 

7 

8""" 

9.. dialect:: mssql+mxodbc 

10 :name: mxODBC 

11 :dbapi: mxodbc 

12 :connectstring: mssql+mxodbc://<username>:<password>@<dsnname> 

13 :url: http://www.egenix.com/ 

14 

15Execution Modes 

16--------------- 

17 

18mxODBC features two styles of statement execution, using the 

19``cursor.execute()`` and ``cursor.executedirect()`` methods (the second being 

20an extension to the DBAPI specification). The former makes use of a particular 

21API call specific to the SQL Server Native Client ODBC driver known 

22SQLDescribeParam, while the latter does not. 

23 

24mxODBC apparently only makes repeated use of a single prepared statement 

25when SQLDescribeParam is used. The advantage to prepared statement reuse is 

26one of performance. The disadvantage is that SQLDescribeParam has a limited 

27set of scenarios in which bind parameters are understood, including that they 

28cannot be placed within the argument lists of function calls, anywhere outside 

29the FROM, or even within subqueries within the FROM clause - making the usage 

30of bind parameters within SELECT statements impossible for all but the most 

31simplistic statements. 

32 

33For this reason, the mxODBC dialect uses the "native" mode by default only for 

34INSERT, UPDATE, and DELETE statements, and uses the escaped string mode for 

35all other statements. 

36 

37This behavior can be controlled via 

38:meth:`~sqlalchemy.sql.expression.Executable.execution_options` using the 

39``native_odbc_execute`` flag with a value of ``True`` or ``False``, where a 

40value of ``True`` will unconditionally use native bind parameters and a value 

41of ``False`` will unconditionally use string-escaped parameters. 

42 

43""" 

44 

45 

46from .base import _MSDate 

47from .base import _MSDateTime 

48from .base import _MSTime 

49from .base import MSDialect 

50from .base import VARBINARY 

51from .pyodbc import _MSNumeric_pyodbc 

52from .pyodbc import MSExecutionContext_pyodbc 

53from ... import types as sqltypes 

54from ...connectors.mxodbc import MxODBCConnector 

55 

56 

57class _MSNumeric_mxodbc(_MSNumeric_pyodbc): 

58 """Include pyodbc's numeric processor. 

59 """ 

60 

61 

62class _MSDate_mxodbc(_MSDate): 

63 def bind_processor(self, dialect): 

64 def process(value): 

65 if value is not None: 

66 return "%s-%s-%s" % (value.year, value.month, value.day) 

67 else: 

68 return None 

69 

70 return process 

71 

72 

73class _MSTime_mxodbc(_MSTime): 

74 def bind_processor(self, dialect): 

75 def process(value): 

76 if value is not None: 

77 return "%s:%s:%s" % (value.hour, value.minute, value.second) 

78 else: 

79 return None 

80 

81 return process 

82 

83 

84class _VARBINARY_mxodbc(VARBINARY): 

85 

86 """ 

87 mxODBC Support for VARBINARY column types. 

88 

89 This handles the special case for null VARBINARY values, 

90 which maps None values to the mx.ODBC.Manager.BinaryNull symbol. 

91 """ 

92 

93 def bind_processor(self, dialect): 

94 if dialect.dbapi is None: 

95 return None 

96 

97 DBAPIBinary = dialect.dbapi.Binary 

98 

99 def process(value): 

100 if value is not None: 

101 return DBAPIBinary(value) 

102 else: 

103 # should pull from mx.ODBC.Manager.BinaryNull 

104 return dialect.dbapi.BinaryNull 

105 

106 return process 

107 

108 

109class MSExecutionContext_mxodbc(MSExecutionContext_pyodbc): 

110 """ 

111 The pyodbc execution context is useful for enabling 

112 SELECT SCOPE_IDENTITY in cases where OUTPUT clause 

113 does not work (tables with insert triggers). 

114 """ 

115 

116 # todo - investigate whether the pyodbc execution context 

117 # is really only being used in cases where OUTPUT 

118 # won't work. 

119 

120 

121class MSDialect_mxodbc(MxODBCConnector, MSDialect): 

122 

123 # this is only needed if "native ODBC" mode is used, 

124 # which is now disabled by default. 

125 # statement_compiler = MSSQLStrictCompiler 

126 

127 execution_ctx_cls = MSExecutionContext_mxodbc 

128 

129 # flag used by _MSNumeric_mxodbc 

130 _need_decimal_fix = True 

131 

132 colspecs = { 

133 sqltypes.Numeric: _MSNumeric_mxodbc, 

134 sqltypes.DateTime: _MSDateTime, 

135 sqltypes.Date: _MSDate_mxodbc, 

136 sqltypes.Time: _MSTime_mxodbc, 

137 VARBINARY: _VARBINARY_mxodbc, 

138 sqltypes.LargeBinary: _VARBINARY_mxodbc, 

139 } 

140 

141 def __init__(self, description_encoding=None, **params): 

142 super(MSDialect_mxodbc, self).__init__(**params) 

143 self.description_encoding = description_encoding 

144 

145 

146dialect = MSDialect_mxodbc